Index: src/compiler/js-native-context-specialization.cc |
diff --git a/src/compiler/js-native-context-specialization.cc b/src/compiler/js-native-context-specialization.cc |
index f6b29ab81c74d93fcef3cf7a182bf4d2b42dda42..57e933b1aa0c3b28db60ff0567db144605787a47 100644 |
--- a/src/compiler/js-native-context-specialization.cc |
+++ b/src/compiler/js-native-context-specialization.cc |
@@ -869,12 +869,26 @@ JSNativeContextSpecialization::BuildPropertyAccess( |
context, target, frame_state); |
// Introduce the call to the getter function. |
- value = effect = graph()->NewNode( |
- javascript()->CallFunction( |
- 2, 0.0f, VectorSlotPair(), |
- ConvertReceiverMode::kNotNullOrUndefined), |
- target, receiver, context, frame_state0, effect, control); |
- control = graph()->NewNode(common()->IfSuccess(), value); |
+ if (access_info.constant()->IsJSFunction()) { |
+ value = effect = graph()->NewNode( |
+ javascript()->CallFunction( |
+ 2, 0.0f, VectorSlotPair(), |
+ ConvertReceiverMode::kNotNullOrUndefined), |
+ target, receiver, context, frame_state0, effect, control); |
+ control = graph()->NewNode(common()->IfSuccess(), value); |
+ } else { |
+ DCHECK(access_info.constant()->IsFunctionTemplateInfo()); |
+ Handle<FunctionTemplateInfo> function_template_info( |
+ Handle<FunctionTemplateInfo>::cast(access_info.constant())); |
+ DCHECK(!function_template_info->call_code()->IsUndefined(isolate())); |
+ ZoneVector<Node*> stack_parameters(graph()->zone()); |
+ ValueEffectControl value_effect_control = InlineApiCall( |
+ receiver, context, target, frame_state0, &stack_parameters, |
+ effect, control, shared_info, function_template_info); |
+ value = value_effect_control.value(); |
+ effect = value_effect_control.effect(); |
+ control = value_effect_control.control(); |
+ } |
break; |
} |
case AccessMode::kStore: { |
@@ -892,12 +906,27 @@ JSNativeContextSpecialization::BuildPropertyAccess( |
context, target, frame_state); |
// Introduce the call to the setter function. |
- effect = graph()->NewNode(javascript()->CallFunction( |
- 3, 0.0f, VectorSlotPair(), |
- ConvertReceiverMode::kNotNullOrUndefined), |
- target, receiver, value, context, |
- frame_state0, effect, control); |
- control = graph()->NewNode(common()->IfSuccess(), effect); |
+ if (access_info.constant()->IsJSFunction()) { |
+ effect = graph()->NewNode( |
+ javascript()->CallFunction( |
+ 3, 0.0f, VectorSlotPair(), |
+ ConvertReceiverMode::kNotNullOrUndefined), |
+ target, receiver, value, context, frame_state0, effect, control); |
+ control = graph()->NewNode(common()->IfSuccess(), effect); |
+ } else { |
+ DCHECK(access_info.constant()->IsFunctionTemplateInfo()); |
+ Handle<FunctionTemplateInfo> function_template_info( |
+ Handle<FunctionTemplateInfo>::cast(access_info.constant())); |
+ DCHECK(!function_template_info->call_code()->IsUndefined(isolate())); |
+ ZoneVector<Node*> stack_parameters(graph()->zone()); |
+ stack_parameters.push_back(value); |
+ ValueEffectControl value_effect_control = InlineApiCall( |
+ receiver, context, target, frame_state0, &stack_parameters, |
+ effect, control, shared_info, function_template_info); |
+ value = value_effect_control.value(); |
+ effect = value_effect_control.effect(); |
+ control = value_effect_control.control(); |
+ } |
break; |
} |
} |
@@ -1323,6 +1352,65 @@ JSNativeContextSpecialization::BuildElementAccess( |
return ValueEffectControl(value, effect, control); |
} |
+JSNativeContextSpecialization::ValueEffectControl |
+JSNativeContextSpecialization::InlineApiCall( |
+ Node* receiver, Node* context, Node* target, Node* frame_state, |
+ ZoneVector<Node*>* stack_parameters, Node* effect, Node* control, |
+ Handle<SharedFunctionInfo> shared_info, |
+ Handle<FunctionTemplateInfo> function_template_info) { |
+ Handle<CallHandlerInfo> call_handler_info = handle( |
+ CallHandlerInfo::cast(function_template_info->call_code()), isolate()); |
+ Handle<Object> call_data_object(call_handler_info->data(), isolate()); |
+ |
+ // The stub always expects the receiver as the first param on the stack. |
+ CallApiCallbackStub stub( |
+ isolate(), static_cast<int>(stack_parameters->size()), |
+ call_data_object->IsUndefined(isolate()), |
+ true /* TODO(epertoso): similar to CallOptimization */); |
+ CallInterfaceDescriptor call_interface_descriptor = |
+ stub.GetCallInterfaceDescriptor(); |
+ CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor( |
+ isolate(), graph()->zone(), call_interface_descriptor, |
+ call_interface_descriptor.GetStackParameterCount() + |
+ static_cast<int>(stack_parameters->size()) + 1, |
+ CallDescriptor::kNeedsFrameState, Operator::kNoProperties, |
+ MachineType::AnyTagged(), 1); |
+ |
+ Node* data = jsgraph()->Constant(call_data_object); |
+ ApiFunction function(v8::ToCData<Address>(call_handler_info->callback())); |
+ Node* function_reference = |
+ graph()->NewNode(common()->ExternalConstant(ExternalReference( |
+ &function, ExternalReference::DIRECT_API_CALL, isolate()))); |
+ Node* code = jsgraph()->HeapConstant(stub.GetCode()); |
+ |
+ ZoneVector<Node*> inputs(zone()); |
+ inputs.push_back(code); |
+ |
+ // CallApiCallbackStub's register arguments. |
+ inputs.push_back(target); |
+ inputs.push_back(data); |
+ inputs.push_back(receiver); |
+ inputs.push_back(function_reference); |
+ |
+ // Stack parameters: CallApiCallbackStub expects the first one to be the |
+ // receiver. |
+ inputs.push_back(receiver); |
+ for (Node* node : *stack_parameters) { |
+ inputs.push_back(node); |
+ } |
+ inputs.push_back(context); |
+ inputs.push_back(frame_state); |
+ inputs.push_back(effect); |
+ inputs.push_back(control); |
+ |
+ Node* effect0; |
+ Node* value0 = effect0 = |
+ graph()->NewNode(common()->Call(call_descriptor), |
+ static_cast<int>(inputs.size()), inputs.data()); |
+ Node* control0 = graph()->NewNode(common()->IfSuccess(), value0); |
+ return ValueEffectControl(value0, effect0, control0); |
+} |
+ |
Node* JSNativeContextSpecialization::BuildCheckMaps( |
Node* receiver, Node* effect, Node* control, |
std::vector<Handle<Map>> const& maps) { |