Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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/crankshaft/hydrogen.h" | 5 #include "src/crankshaft/hydrogen.h" |
| 6 | 6 |
| 7 #include <sstream> | 7 #include <sstream> |
| 8 | 8 |
| 9 #include "src/allocation-site-scopes.h" | 9 #include "src/allocation-site-scopes.h" |
| 10 #include "src/ast/ast-numbering.h" | 10 #include "src/ast/ast-numbering.h" |
| (...skipping 6316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6327 access_ = HObjectAccess::ForField(map, index, representation(), name_); | 6327 access_ = HObjectAccess::ForField(map, index, representation(), name_); |
| 6328 | 6328 |
| 6329 // Load field map for heap objects. | 6329 // Load field map for heap objects. |
| 6330 return LoadFieldMaps(map); | 6330 return LoadFieldMaps(map); |
| 6331 } else if (IsAccessorConstant()) { | 6331 } else if (IsAccessorConstant()) { |
| 6332 Handle<Object> accessors = GetAccessorsFromMap(map); | 6332 Handle<Object> accessors = GetAccessorsFromMap(map); |
| 6333 if (!accessors->IsAccessorPair()) return false; | 6333 if (!accessors->IsAccessorPair()) return false; |
| 6334 Object* raw_accessor = | 6334 Object* raw_accessor = |
| 6335 IsLoad() ? Handle<AccessorPair>::cast(accessors)->getter() | 6335 IsLoad() ? Handle<AccessorPair>::cast(accessors)->getter() |
| 6336 : Handle<AccessorPair>::cast(accessors)->setter(); | 6336 : Handle<AccessorPair>::cast(accessors)->setter(); |
| 6337 if (!raw_accessor->IsJSFunction()) return false; | 6337 if (!raw_accessor->IsJSFunction() && |
| 6338 Handle<JSFunction> accessor = handle(JSFunction::cast(raw_accessor)); | 6338 !raw_accessor->IsFunctionTemplateInfo()) |
| 6339 if (accessor->shared()->IsApiFunction()) { | 6339 return false; |
| 6340 CallOptimization call_optimization(accessor); | 6340 Handle<Object> accessor = handle(HeapObject::cast(raw_accessor)); |
| 6341 if (call_optimization.is_simple_api_call()) { | 6341 CallOptimization call_optimization(accessor); |
| 6342 CallOptimization::HolderLookup holder_lookup; | 6342 if (call_optimization.is_simple_api_call()) { |
| 6343 api_holder_ = | 6343 CallOptimization::HolderLookup holder_lookup; |
| 6344 call_optimization.LookupHolderOfExpectedType(map_, &holder_lookup); | 6344 api_holder_ = |
| 6345 } | 6345 call_optimization.LookupHolderOfExpectedType(map_, &holder_lookup); |
| 6346 } | 6346 } |
| 6347 accessor_ = accessor; | 6347 accessor_ = accessor; |
| 6348 } else if (IsDataConstant()) { | 6348 } else if (IsDataConstant()) { |
| 6349 constant_ = GetConstantFromMap(map); | 6349 constant_ = GetConstantFromMap(map); |
| 6350 } | 6350 } |
| 6351 | 6351 |
| 6352 return true; | 6352 return true; |
| 6353 } | 6353 } |
| 6354 | 6354 |
| 6355 | 6355 |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6573 } | 6573 } |
| 6574 | 6574 |
| 6575 if (info->IsAccessorConstant()) { | 6575 if (info->IsAccessorConstant()) { |
| 6576 Push(checked_object); | 6576 Push(checked_object); |
| 6577 int argument_count = 1; | 6577 int argument_count = 1; |
| 6578 if (!info->IsLoad()) { | 6578 if (!info->IsLoad()) { |
| 6579 argument_count = 2; | 6579 argument_count = 2; |
| 6580 Push(value); | 6580 Push(value); |
| 6581 } | 6581 } |
| 6582 | 6582 |
| 6583 if (info->NeedsWrappingFor(info->accessor())) { | 6583 if (info->accessor()->IsJSFunction() && |
| 6584 info->NeedsWrappingFor(Handle<JSFunction>::cast(info->accessor()))) { | |
|
Toon Verwaest
2016/01/28 12:05:19
If you could get a FunctionTemplate here, shouldn'
epertoso
2016/02/01 16:18:03
Technically, it seems unlikely that TryInlineGette
| |
| 6584 HValue* function = Add<HConstant>(info->accessor()); | 6585 HValue* function = Add<HConstant>(info->accessor()); |
| 6585 PushArgumentsFromEnvironment(argument_count); | 6586 PushArgumentsFromEnvironment(argument_count); |
| 6586 return New<HCallFunction>(function, argument_count, | 6587 return New<HCallFunction>(function, argument_count, |
| 6587 ConvertReceiverMode::kNotNullOrUndefined, | 6588 ConvertReceiverMode::kNotNullOrUndefined, |
| 6588 TailCallMode::kDisallow); | 6589 TailCallMode::kDisallow); |
| 6589 } else if (FLAG_inline_accessors && can_inline_accessor) { | 6590 } else if (FLAG_inline_accessors && can_inline_accessor) { |
| 6590 bool success = info->IsLoad() | 6591 bool success = info->IsLoad() |
| 6591 ? TryInlineGetter(info->accessor(), info->map(), ast_id, return_id) | 6592 ? TryInlineGetter(info->accessor(), info->map(), ast_id, return_id) |
| 6592 : TryInlineSetter( | 6593 : TryInlineSetter( |
| 6593 info->accessor(), info->map(), ast_id, return_id, value); | 6594 info->accessor(), info->map(), ast_id, return_id, value); |
| 6594 if (success || HasStackOverflow()) return NULL; | 6595 if (success || HasStackOverflow()) return NULL; |
| 6595 } | 6596 } |
| 6596 | 6597 |
| 6597 PushArgumentsFromEnvironment(argument_count); | 6598 PushArgumentsFromEnvironment(argument_count); |
| 6598 return BuildCallConstantFunction(info->accessor(), argument_count); | 6599 DCHECK(info->accessor()->IsJSFunction()); |
| 6600 return BuildCallConstantFunction(Handle<JSFunction>::cast(info->accessor()), | |
| 6601 argument_count); | |
| 6599 } | 6602 } |
| 6600 | 6603 |
| 6601 DCHECK(info->IsDataConstant()); | 6604 DCHECK(info->IsDataConstant()); |
| 6602 if (info->IsLoad()) { | 6605 if (info->IsLoad()) { |
| 6603 return New<HConstant>(info->constant()); | 6606 return New<HConstant>(info->constant()); |
| 6604 } else { | 6607 } else { |
| 6605 return New<HCheckValue>(value, Handle<JSFunction>::cast(info->constant())); | 6608 return New<HCheckValue>(value, Handle<JSFunction>::cast(info->constant())); |
| 6606 } | 6609 } |
| 6607 } | 6610 } |
| 6608 | 6611 |
| (...skipping 2011 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8620 } | 8623 } |
| 8621 | 8624 |
| 8622 | 8625 |
| 8623 bool HOptimizedGraphBuilder::TryInlineConstruct(CallNew* expr, | 8626 bool HOptimizedGraphBuilder::TryInlineConstruct(CallNew* expr, |
| 8624 HValue* implicit_return_value) { | 8627 HValue* implicit_return_value) { |
| 8625 return TryInline(expr->target(), expr->arguments()->length(), | 8628 return TryInline(expr->target(), expr->arguments()->length(), |
| 8626 implicit_return_value, expr->id(), expr->ReturnId(), | 8629 implicit_return_value, expr->id(), expr->ReturnId(), |
| 8627 CONSTRUCT_CALL_RETURN); | 8630 CONSTRUCT_CALL_RETURN); |
| 8628 } | 8631 } |
| 8629 | 8632 |
| 8630 | 8633 bool HOptimizedGraphBuilder::TryInlineGetter(Handle<Object> getter, |
| 8631 bool HOptimizedGraphBuilder::TryInlineGetter(Handle<JSFunction> getter, | |
| 8632 Handle<Map> receiver_map, | 8634 Handle<Map> receiver_map, |
| 8633 BailoutId ast_id, | 8635 BailoutId ast_id, |
| 8634 BailoutId return_id) { | 8636 BailoutId return_id) { |
| 8635 if (TryInlineApiGetter(getter, receiver_map, ast_id)) return true; | 8637 if (TryInlineApiGetter(getter, receiver_map, ast_id)) return true; |
| 8636 return TryInline(getter, 0, NULL, ast_id, return_id, GETTER_CALL_RETURN); | 8638 return getter->IsJSFunction() && |
| 8639 TryInline(Handle<JSFunction>::cast(getter), 0, NULL, ast_id, return_id, | |
| 8640 GETTER_CALL_RETURN); | |
| 8637 } | 8641 } |
| 8638 | 8642 |
| 8639 | 8643 bool HOptimizedGraphBuilder::TryInlineSetter(Handle<Object> setter, |
| 8640 bool HOptimizedGraphBuilder::TryInlineSetter(Handle<JSFunction> setter, | |
| 8641 Handle<Map> receiver_map, | 8644 Handle<Map> receiver_map, |
| 8642 BailoutId id, | 8645 BailoutId id, |
| 8643 BailoutId assignment_id, | 8646 BailoutId assignment_id, |
| 8644 HValue* implicit_return_value) { | 8647 HValue* implicit_return_value) { |
| 8645 if (TryInlineApiSetter(setter, receiver_map, id)) return true; | 8648 if (TryInlineApiSetter(setter, receiver_map, id)) return true; |
| 8646 return TryInline(setter, 1, implicit_return_value, id, assignment_id, | 8649 return setter->IsJSFunction() && |
| 8647 SETTER_CALL_RETURN); | 8650 TryInline(Handle<JSFunction>::cast(setter), 1, implicit_return_value, |
| 8651 id, assignment_id, SETTER_CALL_RETURN); | |
| 8648 } | 8652 } |
| 8649 | 8653 |
| 8650 | 8654 |
| 8651 bool HOptimizedGraphBuilder::TryInlineIndirectCall(Handle<JSFunction> function, | 8655 bool HOptimizedGraphBuilder::TryInlineIndirectCall(Handle<JSFunction> function, |
| 8652 Call* expr, | 8656 Call* expr, |
| 8653 int arguments_count) { | 8657 int arguments_count) { |
| 8654 return TryInline(function, arguments_count, NULL, expr->id(), | 8658 return TryInline(function, arguments_count, NULL, expr->id(), |
| 8655 expr->ReturnId(), NORMAL_RETURN); | 8659 expr->ReturnId(), NORMAL_RETURN); |
| 8656 } | 8660 } |
| 8657 | 8661 |
| (...skipping 473 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 9131 Handle<JSFunction> function = expr->target(); | 9135 Handle<JSFunction> function = expr->target(); |
| 9132 int argc = expr->arguments()->length(); | 9136 int argc = expr->arguments()->length(); |
| 9133 return TryInlineApiCall(function, | 9137 return TryInlineApiCall(function, |
| 9134 receiver, | 9138 receiver, |
| 9135 receiver_maps, | 9139 receiver_maps, |
| 9136 argc, | 9140 argc, |
| 9137 expr->id(), | 9141 expr->id(), |
| 9138 kCallApiMethod); | 9142 kCallApiMethod); |
| 9139 } | 9143 } |
| 9140 | 9144 |
| 9141 | 9145 bool HOptimizedGraphBuilder::TryInlineApiGetter(Handle<Object> function, |
| 9142 bool HOptimizedGraphBuilder::TryInlineApiGetter(Handle<JSFunction> function, | |
| 9143 Handle<Map> receiver_map, | 9146 Handle<Map> receiver_map, |
| 9144 BailoutId ast_id) { | 9147 BailoutId ast_id) { |
| 9145 SmallMapList receiver_maps(1, zone()); | 9148 SmallMapList receiver_maps(1, zone()); |
| 9146 receiver_maps.Add(receiver_map, zone()); | 9149 receiver_maps.Add(receiver_map, zone()); |
| 9147 return TryInlineApiCall(function, | 9150 return TryInlineApiCall(function, |
| 9148 NULL, // Receiver is on expression stack. | 9151 NULL, // Receiver is on expression stack. |
| 9149 &receiver_maps, | 9152 &receiver_maps, |
| 9150 0, | 9153 0, |
| 9151 ast_id, | 9154 ast_id, |
| 9152 kCallApiGetter); | 9155 kCallApiGetter); |
| 9153 } | 9156 } |
| 9154 | 9157 |
| 9155 | 9158 bool HOptimizedGraphBuilder::TryInlineApiSetter(Handle<Object> function, |
| 9156 bool HOptimizedGraphBuilder::TryInlineApiSetter(Handle<JSFunction> function, | |
| 9157 Handle<Map> receiver_map, | 9159 Handle<Map> receiver_map, |
| 9158 BailoutId ast_id) { | 9160 BailoutId ast_id) { |
| 9159 SmallMapList receiver_maps(1, zone()); | 9161 SmallMapList receiver_maps(1, zone()); |
| 9160 receiver_maps.Add(receiver_map, zone()); | 9162 receiver_maps.Add(receiver_map, zone()); |
| 9161 return TryInlineApiCall(function, | 9163 return TryInlineApiCall(function, |
| 9162 NULL, // Receiver is on expression stack. | 9164 NULL, // Receiver is on expression stack. |
| 9163 &receiver_maps, | 9165 &receiver_maps, |
| 9164 1, | 9166 1, |
| 9165 ast_id, | 9167 ast_id, |
| 9166 kCallApiSetter); | 9168 kCallApiSetter); |
| 9167 } | 9169 } |
| 9168 | 9170 |
| 9169 | 9171 bool HOptimizedGraphBuilder::TryInlineApiCall(Handle<Object> function, |
| 9170 bool HOptimizedGraphBuilder::TryInlineApiCall(Handle<JSFunction> function, | 9172 HValue* receiver, |
| 9171 HValue* receiver, | 9173 SmallMapList* receiver_maps, |
| 9172 SmallMapList* receiver_maps, | 9174 int argc, BailoutId ast_id, |
| 9173 int argc, | 9175 ApiCallType call_type) { |
| 9174 BailoutId ast_id, | 9176 if (function->IsJSFunction() && |
| 9175 ApiCallType call_type) { | 9177 Handle<JSFunction>::cast(function)->context()->native_context() != |
| 9176 if (function->context()->native_context() != | 9178 top_info()->closure()->context()->native_context()) { |
| 9177 top_info()->closure()->context()->native_context()) { | |
| 9178 return false; | 9179 return false; |
| 9179 } | 9180 } |
| 9180 CallOptimization optimization(function); | 9181 CallOptimization optimization(function); |
| 9181 if (!optimization.is_simple_api_call()) return false; | 9182 if (!optimization.is_simple_api_call()) return false; |
| 9182 Handle<Map> holder_map; | 9183 Handle<Map> holder_map; |
| 9183 for (int i = 0; i < receiver_maps->length(); ++i) { | 9184 for (int i = 0; i < receiver_maps->length(); ++i) { |
| 9184 auto map = receiver_maps->at(i); | 9185 auto map = receiver_maps->at(i); |
| 9185 // Don't inline calls to receivers requiring accesschecks. | 9186 // Don't inline calls to receivers requiring accesschecks. |
| 9186 if (map->is_access_check_needed()) return false; | 9187 if (map->is_access_check_needed()) return false; |
| 9187 } | 9188 } |
| 9188 if (call_type == kCallApiFunction) { | 9189 if (call_type == kCallApiFunction) { |
| 9189 // Cannot embed a direct reference to the global proxy map | 9190 // Cannot embed a direct reference to the global proxy map |
| 9190 // as it maybe dropped on deserialization. | 9191 // as it maybe dropped on deserialization. |
| 9191 CHECK(!isolate()->serializer_enabled()); | 9192 CHECK(!isolate()->serializer_enabled()); |
| 9193 DCHECK(function->IsJSFunction()); | |
| 9192 DCHECK_EQ(0, receiver_maps->length()); | 9194 DCHECK_EQ(0, receiver_maps->length()); |
| 9193 receiver_maps->Add(handle(function->global_proxy()->map()), zone()); | 9195 receiver_maps->Add( |
| 9196 handle(Handle<JSFunction>::cast(function)->global_proxy()->map()), | |
| 9197 zone()); | |
| 9194 } | 9198 } |
| 9195 CallOptimization::HolderLookup holder_lookup = | 9199 CallOptimization::HolderLookup holder_lookup = |
| 9196 CallOptimization::kHolderNotFound; | 9200 CallOptimization::kHolderNotFound; |
| 9197 Handle<JSObject> api_holder = optimization.LookupHolderOfExpectedType( | 9201 Handle<JSObject> api_holder = optimization.LookupHolderOfExpectedType( |
| 9198 receiver_maps->first(), &holder_lookup); | 9202 receiver_maps->first(), &holder_lookup); |
| 9199 if (holder_lookup == CallOptimization::kHolderNotFound) return false; | 9203 if (holder_lookup == CallOptimization::kHolderNotFound) return false; |
| 9200 | 9204 |
| 9201 if (FLAG_trace_inlining) { | 9205 if (FLAG_trace_inlining) { |
| 9202 PrintF("Inlining api function "); | 9206 PrintF("Inlining api function "); |
| 9203 function->ShortPrint(); | 9207 function->ShortPrint(); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 9263 ExternalReference ref = ExternalReference(&fun, | 9267 ExternalReference ref = ExternalReference(&fun, |
| 9264 ExternalReference::DIRECT_API_CALL, | 9268 ExternalReference::DIRECT_API_CALL, |
| 9265 isolate()); | 9269 isolate()); |
| 9266 HValue* api_function_address = Add<HConstant>(ExternalReference(ref)); | 9270 HValue* api_function_address = Add<HConstant>(ExternalReference(ref)); |
| 9267 | 9271 |
| 9268 HValue* op_vals[] = {context(), Add<HConstant>(function), call_data, holder, | 9272 HValue* op_vals[] = {context(), Add<HConstant>(function), call_data, holder, |
| 9269 api_function_address, nullptr}; | 9273 api_function_address, nullptr}; |
| 9270 | 9274 |
| 9271 HInstruction* call = nullptr; | 9275 HInstruction* call = nullptr; |
| 9272 if (!is_function) { | 9276 if (!is_function) { |
| 9273 CallApiAccessorStub stub(isolate(), is_store, call_data_undefined); | 9277 CallApiAccessorStub stub(isolate(), is_store, call_data_undefined, |
| 9278 !optimization.is_constant_call()); | |
| 9274 Handle<Code> code = stub.GetCode(); | 9279 Handle<Code> code = stub.GetCode(); |
| 9275 HConstant* code_value = Add<HConstant>(code); | 9280 HConstant* code_value = Add<HConstant>(code); |
| 9276 ApiAccessorDescriptor descriptor(isolate()); | 9281 ApiAccessorDescriptor descriptor(isolate()); |
| 9277 call = New<HCallWithDescriptor>( | 9282 call = New<HCallWithDescriptor>( |
| 9278 code_value, argc + 1, descriptor, | 9283 code_value, argc + 1, descriptor, |
| 9279 Vector<HValue*>(op_vals, arraysize(op_vals) - 1)); | 9284 Vector<HValue*>(op_vals, arraysize(op_vals) - 1)); |
| 9280 } else if (argc <= CallApiFunctionWithFixedArgsStub::kMaxFixedArgs) { | 9285 } else if (argc <= CallApiFunctionWithFixedArgsStub::kMaxFixedArgs) { |
| 9281 CallApiFunctionWithFixedArgsStub stub(isolate(), argc, call_data_undefined); | 9286 CallApiFunctionWithFixedArgsStub stub(isolate(), argc, call_data_undefined); |
| 9282 Handle<Code> code = stub.GetCode(); | 9287 Handle<Code> code = stub.GetCode(); |
| 9283 HConstant* code_value = Add<HConstant>(code); | 9288 HConstant* code_value = Add<HConstant>(code); |
| (...skipping 4343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 13627 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 13632 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 13628 } | 13633 } |
| 13629 | 13634 |
| 13630 #ifdef DEBUG | 13635 #ifdef DEBUG |
| 13631 graph_->Verify(false); // No full verify. | 13636 graph_->Verify(false); // No full verify. |
| 13632 #endif | 13637 #endif |
| 13633 } | 13638 } |
| 13634 | 13639 |
| 13635 } // namespace internal | 13640 } // namespace internal |
| 13636 } // namespace v8 | 13641 } // namespace v8 |
| OLD | NEW |