Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(53)

Side by Side Diff: src/compiler/js-call-reducer.cc

Issue 2555223002: [turbofan] Inlining of API functions. (Closed)
Patch Set: Update. Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/js-call-reducer.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/compiler/js-call-reducer.h" 5 #include "src/compiler/js-call-reducer.h"
6 6
7 #include "src/code-stubs.h"
7 #include "src/compiler/js-graph.h" 8 #include "src/compiler/js-graph.h"
9 #include "src/compiler/linkage.h"
8 #include "src/compiler/node-matchers.h" 10 #include "src/compiler/node-matchers.h"
9 #include "src/compiler/simplified-operator.h" 11 #include "src/compiler/simplified-operator.h"
10 #include "src/objects-inl.h" 12 #include "src/objects-inl.h"
11 #include "src/type-feedback-vector-inl.h" 13 #include "src/type-feedback-vector-inl.h"
12 14
13 namespace v8 { 15 namespace v8 {
14 namespace internal { 16 namespace internal {
15 namespace compiler { 17 namespace compiler {
16 18
17 Reduction JSCallReducer::Reduce(Node* node) { 19 Reduction JSCallReducer::Reduce(Node* node) {
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
250 return MaybeHandle<Map>(); 252 return MaybeHandle<Map>();
251 } 253 }
252 if (dominator->op()->EffectInputCount() != 1) { 254 if (dominator->op()->EffectInputCount() != 1) {
253 // Didn't find any appropriate CheckMaps node. 255 // Didn't find any appropriate CheckMaps node.
254 return MaybeHandle<Map>(); 256 return MaybeHandle<Map>();
255 } 257 }
256 dominator = NodeProperties::GetEffectInput(dominator); 258 dominator = NodeProperties::GetEffectInput(dominator);
257 } 259 }
258 } 260 }
259 261
262 bool CanInlineApiCall(Isolate* isolate, Node* node,
263 Handle<FunctionTemplateInfo> function_template_info) {
264 DCHECK(node->opcode() == IrOpcode::kJSCallFunction);
265 if (function_template_info->call_code()->IsUndefined(isolate)) {
266 return false;
267 }
268 CallFunctionParameters const& params = CallFunctionParametersOf(node->op());
269 int const argc = static_cast<int>(params.arity()) - 2;
Jarin 2016/12/08 12:31:53 As discussed before, it would be good to describe
epertoso 2016/12/08 13:33:19 Done here and in ReduceCallApiFunction.
270 if (argc > CallApiCallbackStub::kArgMax || !params.feedback().IsValid()) {
271 return false;
272 }
273 HeapObjectMatcher receiver(NodeProperties::GetValueInput(node, 1));
274 if (!receiver.HasValue()) {
275 return false;
276 }
277 return receiver.Value()->IsUndefined(isolate) ||
278 (receiver.Value()->map()->IsJSObjectMap() &&
279 !receiver.Value()->map()->is_access_check_needed());
280 }
281
260 } // namespace 282 } // namespace
261 283
284 JSCallReducer::HolderLookup JSCallReducer::LookupHolder(
285 Handle<JSObject> object,
286 Handle<FunctionTemplateInfo> function_template_info,
287 Handle<JSObject>* holder) {
288 DCHECK(object->map()->IsJSObjectMap());
289 Handle<Map> object_map(object->map());
290 Handle<FunctionTemplateInfo> expected_receiver_type;
291 if (!function_template_info->signature()->IsUndefined(isolate())) {
292 expected_receiver_type =
293 handle(FunctionTemplateInfo::cast(function_template_info->signature()));
Jarin 2016/12/08 12:31:53 Hmm, signature of FunctionTemplateInfo is Function
epertoso 2016/12/08 13:33:19 Yes. Not my fault.
294 }
295 if (expected_receiver_type.is_null() ||
296 expected_receiver_type->IsTemplateFor(*object_map)) {
297 *holder = Handle<JSObject>::null();
298 return kHolderIsReceiver;
299 }
300 while (object_map->has_hidden_prototype()) {
301 Handle<JSObject> prototype(JSObject::cast(object_map->prototype()));
302 object_map = handle(prototype->map());
303 if (expected_receiver_type->IsTemplateFor(*object_map)) {
304 *holder = prototype;
305 return kHolderFound;
306 }
307 }
308 return kHolderNotFound;
309 }
310
262 // ES6 section B.2.2.1.1 get Object.prototype.__proto__ 311 // ES6 section B.2.2.1.1 get Object.prototype.__proto__
263 Reduction JSCallReducer::ReduceObjectPrototypeGetProto(Node* node) { 312 Reduction JSCallReducer::ReduceObjectPrototypeGetProto(Node* node) {
264 DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode()); 313 DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode());
265 314
266 // Try to determine the {receiver} map. 315 // Try to determine the {receiver} map.
267 Handle<Map> receiver_map; 316 Handle<Map> receiver_map;
268 if (InferReceiverMap(node).ToHandle(&receiver_map)) { 317 if (InferReceiverMap(node).ToHandle(&receiver_map)) {
269 // Check if we can constant-fold the {receiver} map. 318 // Check if we can constant-fold the {receiver} map.
270 if (!receiver_map->IsJSProxyMap() && 319 if (!receiver_map->IsJSProxyMap() &&
271 !receiver_map->has_hidden_prototype() && 320 !receiver_map->has_hidden_prototype() &&
272 !receiver_map->is_access_check_needed()) { 321 !receiver_map->is_access_check_needed()) {
273 Handle<Object> receiver_prototype(receiver_map->prototype(), isolate()); 322 Handle<Object> receiver_prototype(receiver_map->prototype(), isolate());
274 Node* value = jsgraph()->Constant(receiver_prototype); 323 Node* value = jsgraph()->Constant(receiver_prototype);
275 ReplaceWithValue(node, value); 324 ReplaceWithValue(node, value);
276 return Replace(value); 325 return Replace(value);
277 } 326 }
278 } 327 }
279 328
280 return NoChange(); 329 return NoChange();
281 } 330 }
282 331
332 Reduction JSCallReducer::ReduceCallApiFunction(
333 Node* node, Node* target,
334 Handle<FunctionTemplateInfo> function_template_info) {
335 Isolate* isolate = this->isolate();
336 CHECK(!isolate->serializer_enabled());
337 HeapObjectMatcher m(target);
338 DCHECK(m.HasValue() && m.Value()->IsJSFunction());
339 if (!CanInlineApiCall(isolate, node, function_template_info)) {
340 return NoChange();
341 }
342 Handle<CallHandlerInfo> call_handler_info(
343 handle(CallHandlerInfo::cast(function_template_info->call_code())));
344 Handle<Object> data(call_handler_info->data(), isolate);
345
346 Node* receiver_node = NodeProperties::GetValueInput(node, 1);
347 CallFunctionParameters const& params = CallFunctionParametersOf(node->op());
348
349 Handle<HeapObject> receiver = HeapObjectMatcher(receiver_node).Value();
350 bool const receiver_is_undefined = receiver->IsUndefined(isolate);
351 if (receiver_is_undefined) {
352 receiver = handle(Handle<JSFunction>::cast(m.Value())->global_proxy());
353 } else {
354 DCHECK(receiver->map()->IsJSObjectMap() &&
355 !receiver->map()->is_access_check_needed());
356 }
357
358 Handle<JSObject> holder;
359 HolderLookup lookup = LookupHolder(Handle<JSObject>::cast(receiver),
360 function_template_info, &holder);
361 if (lookup == kHolderNotFound) return NoChange();
362 if (receiver_is_undefined) {
363 receiver_node = jsgraph()->HeapConstant(receiver);
364 NodeProperties::ReplaceValueInput(node, receiver_node, 1);
365 }
366 Node* holder_node =
367 lookup == kHolderFound ? jsgraph()->HeapConstant(holder) : receiver_node;
368
369 Zone* zone = graph()->zone();
370 int const argc = static_cast<int>(params.arity() - 2);
371 CallApiCallbackStub stub(isolate, argc, data->IsUndefined(isolate), false);
372 CallInterfaceDescriptor cid = stub.GetCallInterfaceDescriptor();
373 CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
374 isolate, zone, cid,
375 cid.GetStackParameterCount() + argc + 1 /* including receiver */,
376 CallDescriptor::kNeedsFrameState, Operator::kNoProperties,
377 MachineType::AnyTagged(), 1);
378 ApiFunction api_function(v8::ToCData<Address>(call_handler_info->callback()));
379 ExternalReference function_reference(
380 &api_function, ExternalReference::DIRECT_API_CALL, isolate);
381
382 // CallApiCallbackStub's register arguments: code, target, call data, holder,
383 // function address.
384 node->InsertInput(zone, 0, jsgraph()->HeapConstant(stub.GetCode()));
385 node->InsertInput(zone, 2, jsgraph()->Constant(data));
386 node->InsertInput(zone, 3, holder_node);
387 node->InsertInput(zone, 4, jsgraph()->ExternalConstant(function_reference));
388 NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
389 return Changed(node);
390 }
391
283 Reduction JSCallReducer::ReduceJSCallFunction(Node* node) { 392 Reduction JSCallReducer::ReduceJSCallFunction(Node* node) {
284 DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode()); 393 DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode());
285 CallFunctionParameters const& p = CallFunctionParametersOf(node->op()); 394 CallFunctionParameters const& p = CallFunctionParametersOf(node->op());
286 Node* target = NodeProperties::GetValueInput(node, 0); 395 Node* target = NodeProperties::GetValueInput(node, 0);
287 Node* control = NodeProperties::GetControlInput(node); 396 Node* control = NodeProperties::GetControlInput(node);
288 Node* effect = NodeProperties::GetEffectInput(node); 397 Node* effect = NodeProperties::GetEffectInput(node);
289 398
290 // Try to specialize JSCallFunction {node}s with constant {target}s. 399 // Try to specialize JSCallFunction {node}s with constant {target}s.
291 HeapObjectMatcher m(target); 400 HeapObjectMatcher m(target);
292 if (m.HasValue()) { 401 if (m.HasValue()) {
(...skipping 23 matching lines...) Expand all
316 case Builtins::kObjectPrototypeGetProto: 425 case Builtins::kObjectPrototypeGetProto:
317 return ReduceObjectPrototypeGetProto(node); 426 return ReduceObjectPrototypeGetProto(node);
318 default: 427 default:
319 break; 428 break;
320 } 429 }
321 430
322 // Check for the Array constructor. 431 // Check for the Array constructor.
323 if (*function == function->native_context()->array_function()) { 432 if (*function == function->native_context()->array_function()) {
324 return ReduceArrayConstructor(node); 433 return ReduceArrayConstructor(node);
325 } 434 }
435
436 if (shared->IsApiFunction()) {
437 return ReduceCallApiFunction(
438 node, target,
439 handle(FunctionTemplateInfo::cast(shared->function_data())));
440 }
326 } else if (m.Value()->IsJSBoundFunction()) { 441 } else if (m.Value()->IsJSBoundFunction()) {
327 Handle<JSBoundFunction> function = 442 Handle<JSBoundFunction> function =
328 Handle<JSBoundFunction>::cast(m.Value()); 443 Handle<JSBoundFunction>::cast(m.Value());
329 Handle<JSReceiver> bound_target_function( 444 Handle<JSReceiver> bound_target_function(
330 function->bound_target_function(), isolate()); 445 function->bound_target_function(), isolate());
331 Handle<Object> bound_this(function->bound_this(), isolate()); 446 Handle<Object> bound_this(function->bound_this(), isolate());
332 Handle<FixedArray> bound_arguments(function->bound_arguments(), 447 Handle<FixedArray> bound_arguments(function->bound_arguments(),
333 isolate()); 448 isolate());
334 CallFunctionParameters const& p = CallFunctionParametersOf(node->op()); 449 CallFunctionParameters const& p = CallFunctionParametersOf(node->op());
335 ConvertReceiverMode const convert_mode = 450 ConvertReceiverMode const convert_mode =
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after
547 return jsgraph()->javascript(); 662 return jsgraph()->javascript();
548 } 663 }
549 664
550 SimplifiedOperatorBuilder* JSCallReducer::simplified() const { 665 SimplifiedOperatorBuilder* JSCallReducer::simplified() const {
551 return jsgraph()->simplified(); 666 return jsgraph()->simplified();
552 } 667 }
553 668
554 } // namespace compiler 669 } // namespace compiler
555 } // namespace internal 670 } // namespace internal
556 } // namespace v8 671 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/js-call-reducer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698