| 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 6353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6364 access_ = HObjectAccess::ForField(map, index, representation(), name_); | 6364 access_ = HObjectAccess::ForField(map, index, representation(), name_); |
| 6365 | 6365 |
| 6366 // Load field map for heap objects. | 6366 // Load field map for heap objects. |
| 6367 return LoadFieldMaps(map); | 6367 return LoadFieldMaps(map); |
| 6368 } else if (IsAccessorConstant()) { | 6368 } else if (IsAccessorConstant()) { |
| 6369 Handle<Object> accessors = GetAccessorsFromMap(map); | 6369 Handle<Object> accessors = GetAccessorsFromMap(map); |
| 6370 if (!accessors->IsAccessorPair()) return false; | 6370 if (!accessors->IsAccessorPair()) return false; |
| 6371 Object* raw_accessor = | 6371 Object* raw_accessor = |
| 6372 IsLoad() ? Handle<AccessorPair>::cast(accessors)->getter() | 6372 IsLoad() ? Handle<AccessorPair>::cast(accessors)->getter() |
| 6373 : Handle<AccessorPair>::cast(accessors)->setter(); | 6373 : Handle<AccessorPair>::cast(accessors)->setter(); |
| 6374 if (!raw_accessor->IsJSFunction() && | 6374 if (!raw_accessor->IsJSFunction()) return false; |
| 6375 !raw_accessor->IsFunctionTemplateInfo()) | 6375 Handle<JSFunction> accessor = handle(JSFunction::cast(raw_accessor)); |
| 6376 return false; | 6376 if (accessor->shared()->IsApiFunction()) { |
| 6377 Handle<Object> accessor = handle(HeapObject::cast(raw_accessor)); | 6377 CallOptimization call_optimization(accessor); |
| 6378 CallOptimization call_optimization(accessor); | 6378 if (call_optimization.is_simple_api_call()) { |
| 6379 if (call_optimization.is_simple_api_call()) { | 6379 CallOptimization::HolderLookup holder_lookup; |
| 6380 CallOptimization::HolderLookup holder_lookup; | 6380 api_holder_ = |
| 6381 api_holder_ = | 6381 call_optimization.LookupHolderOfExpectedType(map_, &holder_lookup); |
| 6382 call_optimization.LookupHolderOfExpectedType(map_, &holder_lookup); | 6382 } |
| 6383 } | 6383 } |
| 6384 accessor_ = accessor; | 6384 accessor_ = accessor; |
| 6385 } else if (IsDataConstant()) { | 6385 } else if (IsDataConstant()) { |
| 6386 constant_ = GetConstantFromMap(map); | 6386 constant_ = GetConstantFromMap(map); |
| 6387 } | 6387 } |
| 6388 | 6388 |
| 6389 return true; | 6389 return true; |
| 6390 } | 6390 } |
| 6391 | 6391 |
| 6392 | 6392 |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6610 } | 6610 } |
| 6611 | 6611 |
| 6612 if (info->IsAccessorConstant()) { | 6612 if (info->IsAccessorConstant()) { |
| 6613 Push(checked_object); | 6613 Push(checked_object); |
| 6614 int argument_count = 1; | 6614 int argument_count = 1; |
| 6615 if (!info->IsLoad()) { | 6615 if (!info->IsLoad()) { |
| 6616 argument_count = 2; | 6616 argument_count = 2; |
| 6617 Push(value); | 6617 Push(value); |
| 6618 } | 6618 } |
| 6619 | 6619 |
| 6620 if (info->accessor()->IsJSFunction() && | 6620 if (info->NeedsWrappingFor(info->accessor())) { |
| 6621 info->NeedsWrappingFor(Handle<JSFunction>::cast(info->accessor()))) { | |
| 6622 HValue* function = Add<HConstant>(info->accessor()); | 6621 HValue* function = Add<HConstant>(info->accessor()); |
| 6623 PushArgumentsFromEnvironment(argument_count); | 6622 PushArgumentsFromEnvironment(argument_count); |
| 6624 return New<HCallFunction>(function, argument_count, | 6623 return New<HCallFunction>(function, argument_count, |
| 6625 ConvertReceiverMode::kNotNullOrUndefined, | 6624 ConvertReceiverMode::kNotNullOrUndefined, |
| 6626 TailCallMode::kDisallow); | 6625 TailCallMode::kDisallow); |
| 6627 } else if (FLAG_inline_accessors && can_inline_accessor) { | 6626 } else if (FLAG_inline_accessors && can_inline_accessor) { |
| 6628 bool success = info->IsLoad() | 6627 bool success = info->IsLoad() |
| 6629 ? TryInlineGetter(info->accessor(), info->map(), ast_id, return_id) | 6628 ? TryInlineGetter(info->accessor(), info->map(), ast_id, return_id) |
| 6630 : TryInlineSetter( | 6629 : TryInlineSetter( |
| 6631 info->accessor(), info->map(), ast_id, return_id, value); | 6630 info->accessor(), info->map(), ast_id, return_id, value); |
| 6632 if (success || HasStackOverflow()) return NULL; | 6631 if (success || HasStackOverflow()) return NULL; |
| 6633 } | 6632 } |
| 6634 | 6633 |
| 6635 PushArgumentsFromEnvironment(argument_count); | 6634 PushArgumentsFromEnvironment(argument_count); |
| 6636 if (!info->accessor()->IsJSFunction()) { | 6635 return BuildCallConstantFunction(info->accessor(), argument_count); |
| 6637 Bailout(kInliningBailedOut); | |
| 6638 return nullptr; | |
| 6639 } | |
| 6640 return BuildCallConstantFunction(Handle<JSFunction>::cast(info->accessor()), | |
| 6641 argument_count); | |
| 6642 } | 6636 } |
| 6643 | 6637 |
| 6644 DCHECK(info->IsDataConstant()); | 6638 DCHECK(info->IsDataConstant()); |
| 6645 if (info->IsLoad()) { | 6639 if (info->IsLoad()) { |
| 6646 return New<HConstant>(info->constant()); | 6640 return New<HConstant>(info->constant()); |
| 6647 } else { | 6641 } else { |
| 6648 return New<HCheckValue>(value, Handle<JSFunction>::cast(info->constant())); | 6642 return New<HCheckValue>(value, Handle<JSFunction>::cast(info->constant())); |
| 6649 } | 6643 } |
| 6650 } | 6644 } |
| 6651 | 6645 |
| (...skipping 2013 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8665 } | 8659 } |
| 8666 | 8660 |
| 8667 | 8661 |
| 8668 bool HOptimizedGraphBuilder::TryInlineConstruct(CallNew* expr, | 8662 bool HOptimizedGraphBuilder::TryInlineConstruct(CallNew* expr, |
| 8669 HValue* implicit_return_value) { | 8663 HValue* implicit_return_value) { |
| 8670 return TryInline(expr->target(), expr->arguments()->length(), | 8664 return TryInline(expr->target(), expr->arguments()->length(), |
| 8671 implicit_return_value, expr->id(), expr->ReturnId(), | 8665 implicit_return_value, expr->id(), expr->ReturnId(), |
| 8672 CONSTRUCT_CALL_RETURN); | 8666 CONSTRUCT_CALL_RETURN); |
| 8673 } | 8667 } |
| 8674 | 8668 |
| 8675 bool HOptimizedGraphBuilder::TryInlineGetter(Handle<Object> getter, | 8669 |
| 8670 bool HOptimizedGraphBuilder::TryInlineGetter(Handle<JSFunction> getter, |
| 8676 Handle<Map> receiver_map, | 8671 Handle<Map> receiver_map, |
| 8677 BailoutId ast_id, | 8672 BailoutId ast_id, |
| 8678 BailoutId return_id) { | 8673 BailoutId return_id) { |
| 8679 if (TryInlineApiGetter(getter, receiver_map, ast_id)) return true; | 8674 if (TryInlineApiGetter(getter, receiver_map, ast_id)) return true; |
| 8680 return getter->IsJSFunction() && | 8675 return TryInline(getter, 0, NULL, ast_id, return_id, GETTER_CALL_RETURN); |
| 8681 TryInline(Handle<JSFunction>::cast(getter), 0, NULL, ast_id, return_id, | |
| 8682 GETTER_CALL_RETURN); | |
| 8683 } | 8676 } |
| 8684 | 8677 |
| 8685 bool HOptimizedGraphBuilder::TryInlineSetter(Handle<Object> setter, | 8678 |
| 8679 bool HOptimizedGraphBuilder::TryInlineSetter(Handle<JSFunction> setter, |
| 8686 Handle<Map> receiver_map, | 8680 Handle<Map> receiver_map, |
| 8687 BailoutId id, | 8681 BailoutId id, |
| 8688 BailoutId assignment_id, | 8682 BailoutId assignment_id, |
| 8689 HValue* implicit_return_value) { | 8683 HValue* implicit_return_value) { |
| 8690 if (TryInlineApiSetter(setter, receiver_map, id)) return true; | 8684 if (TryInlineApiSetter(setter, receiver_map, id)) return true; |
| 8691 return setter->IsJSFunction() && | 8685 return TryInline(setter, 1, implicit_return_value, id, assignment_id, |
| 8692 TryInline(Handle<JSFunction>::cast(setter), 1, implicit_return_value, | 8686 SETTER_CALL_RETURN); |
| 8693 id, assignment_id, SETTER_CALL_RETURN); | |
| 8694 } | 8687 } |
| 8695 | 8688 |
| 8696 | 8689 |
| 8697 bool HOptimizedGraphBuilder::TryInlineIndirectCall(Handle<JSFunction> function, | 8690 bool HOptimizedGraphBuilder::TryInlineIndirectCall(Handle<JSFunction> function, |
| 8698 Call* expr, | 8691 Call* expr, |
| 8699 int arguments_count) { | 8692 int arguments_count) { |
| 8700 return TryInline(function, arguments_count, NULL, expr->id(), | 8693 return TryInline(function, arguments_count, NULL, expr->id(), |
| 8701 expr->ReturnId(), NORMAL_RETURN); | 8694 expr->ReturnId(), NORMAL_RETURN); |
| 8702 } | 8695 } |
| 8703 | 8696 |
| (...skipping 473 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9177 Handle<JSFunction> function = expr->target(); | 9170 Handle<JSFunction> function = expr->target(); |
| 9178 int argc = expr->arguments()->length(); | 9171 int argc = expr->arguments()->length(); |
| 9179 return TryInlineApiCall(function, | 9172 return TryInlineApiCall(function, |
| 9180 receiver, | 9173 receiver, |
| 9181 receiver_maps, | 9174 receiver_maps, |
| 9182 argc, | 9175 argc, |
| 9183 expr->id(), | 9176 expr->id(), |
| 9184 kCallApiMethod); | 9177 kCallApiMethod); |
| 9185 } | 9178 } |
| 9186 | 9179 |
| 9187 bool HOptimizedGraphBuilder::TryInlineApiGetter(Handle<Object> function, | 9180 |
| 9181 bool HOptimizedGraphBuilder::TryInlineApiGetter(Handle<JSFunction> function, |
| 9188 Handle<Map> receiver_map, | 9182 Handle<Map> receiver_map, |
| 9189 BailoutId ast_id) { | 9183 BailoutId ast_id) { |
| 9190 SmallMapList receiver_maps(1, zone()); | 9184 SmallMapList receiver_maps(1, zone()); |
| 9191 receiver_maps.Add(receiver_map, zone()); | 9185 receiver_maps.Add(receiver_map, zone()); |
| 9192 return TryInlineApiCall(function, | 9186 return TryInlineApiCall(function, |
| 9193 NULL, // Receiver is on expression stack. | 9187 NULL, // Receiver is on expression stack. |
| 9194 &receiver_maps, | 9188 &receiver_maps, |
| 9195 0, | 9189 0, |
| 9196 ast_id, | 9190 ast_id, |
| 9197 kCallApiGetter); | 9191 kCallApiGetter); |
| 9198 } | 9192 } |
| 9199 | 9193 |
| 9200 bool HOptimizedGraphBuilder::TryInlineApiSetter(Handle<Object> function, | 9194 |
| 9195 bool HOptimizedGraphBuilder::TryInlineApiSetter(Handle<JSFunction> function, |
| 9201 Handle<Map> receiver_map, | 9196 Handle<Map> receiver_map, |
| 9202 BailoutId ast_id) { | 9197 BailoutId ast_id) { |
| 9203 SmallMapList receiver_maps(1, zone()); | 9198 SmallMapList receiver_maps(1, zone()); |
| 9204 receiver_maps.Add(receiver_map, zone()); | 9199 receiver_maps.Add(receiver_map, zone()); |
| 9205 return TryInlineApiCall(function, | 9200 return TryInlineApiCall(function, |
| 9206 NULL, // Receiver is on expression stack. | 9201 NULL, // Receiver is on expression stack. |
| 9207 &receiver_maps, | 9202 &receiver_maps, |
| 9208 1, | 9203 1, |
| 9209 ast_id, | 9204 ast_id, |
| 9210 kCallApiSetter); | 9205 kCallApiSetter); |
| 9211 } | 9206 } |
| 9212 | 9207 |
| 9213 bool HOptimizedGraphBuilder::TryInlineApiCall(Handle<Object> function, | 9208 |
| 9214 HValue* receiver, | 9209 bool HOptimizedGraphBuilder::TryInlineApiCall(Handle<JSFunction> function, |
| 9215 SmallMapList* receiver_maps, | 9210 HValue* receiver, |
| 9216 int argc, BailoutId ast_id, | 9211 SmallMapList* receiver_maps, |
| 9217 ApiCallType call_type) { | 9212 int argc, |
| 9218 if (function->IsJSFunction() && | 9213 BailoutId ast_id, |
| 9219 Handle<JSFunction>::cast(function)->context()->native_context() != | 9214 ApiCallType call_type) { |
| 9220 top_info()->closure()->context()->native_context()) { | 9215 if (function->context()->native_context() != |
| 9216 top_info()->closure()->context()->native_context()) { |
| 9221 return false; | 9217 return false; |
| 9222 } | 9218 } |
| 9223 CallOptimization optimization(function); | 9219 CallOptimization optimization(function); |
| 9224 if (!optimization.is_simple_api_call()) return false; | 9220 if (!optimization.is_simple_api_call()) return false; |
| 9225 Handle<Map> holder_map; | 9221 Handle<Map> holder_map; |
| 9226 for (int i = 0; i < receiver_maps->length(); ++i) { | 9222 for (int i = 0; i < receiver_maps->length(); ++i) { |
| 9227 auto map = receiver_maps->at(i); | 9223 auto map = receiver_maps->at(i); |
| 9228 // Don't inline calls to receivers requiring accesschecks. | 9224 // Don't inline calls to receivers requiring accesschecks. |
| 9229 if (map->is_access_check_needed()) return false; | 9225 if (map->is_access_check_needed()) return false; |
| 9230 } | 9226 } |
| 9231 if (call_type == kCallApiFunction) { | 9227 if (call_type == kCallApiFunction) { |
| 9232 // Cannot embed a direct reference to the global proxy map | 9228 // Cannot embed a direct reference to the global proxy map |
| 9233 // as it maybe dropped on deserialization. | 9229 // as it maybe dropped on deserialization. |
| 9234 CHECK(!isolate()->serializer_enabled()); | 9230 CHECK(!isolate()->serializer_enabled()); |
| 9235 DCHECK(function->IsJSFunction()); | |
| 9236 DCHECK_EQ(0, receiver_maps->length()); | 9231 DCHECK_EQ(0, receiver_maps->length()); |
| 9237 receiver_maps->Add( | 9232 receiver_maps->Add(handle(function->global_proxy()->map()), zone()); |
| 9238 handle(Handle<JSFunction>::cast(function)->global_proxy()->map()), | |
| 9239 zone()); | |
| 9240 } | 9233 } |
| 9241 CallOptimization::HolderLookup holder_lookup = | 9234 CallOptimization::HolderLookup holder_lookup = |
| 9242 CallOptimization::kHolderNotFound; | 9235 CallOptimization::kHolderNotFound; |
| 9243 Handle<JSObject> api_holder = optimization.LookupHolderOfExpectedType( | 9236 Handle<JSObject> api_holder = optimization.LookupHolderOfExpectedType( |
| 9244 receiver_maps->first(), &holder_lookup); | 9237 receiver_maps->first(), &holder_lookup); |
| 9245 if (holder_lookup == CallOptimization::kHolderNotFound) return false; | 9238 if (holder_lookup == CallOptimization::kHolderNotFound) return false; |
| 9246 | 9239 |
| 9247 if (FLAG_trace_inlining) { | 9240 if (FLAG_trace_inlining) { |
| 9248 PrintF("Inlining api function "); | 9241 PrintF("Inlining api function "); |
| 9249 function->ShortPrint(); | 9242 function->ShortPrint(); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9309 ExternalReference ref = ExternalReference(&fun, | 9302 ExternalReference ref = ExternalReference(&fun, |
| 9310 ExternalReference::DIRECT_API_CALL, | 9303 ExternalReference::DIRECT_API_CALL, |
| 9311 isolate()); | 9304 isolate()); |
| 9312 HValue* api_function_address = Add<HConstant>(ExternalReference(ref)); | 9305 HValue* api_function_address = Add<HConstant>(ExternalReference(ref)); |
| 9313 | 9306 |
| 9314 HValue* op_vals[] = {context(), Add<HConstant>(function), call_data, holder, | 9307 HValue* op_vals[] = {context(), Add<HConstant>(function), call_data, holder, |
| 9315 api_function_address, nullptr}; | 9308 api_function_address, nullptr}; |
| 9316 | 9309 |
| 9317 HInstruction* call = nullptr; | 9310 HInstruction* call = nullptr; |
| 9318 if (!is_function) { | 9311 if (!is_function) { |
| 9319 CallApiAccessorStub stub(isolate(), is_store, call_data_undefined, | 9312 CallApiAccessorStub stub(isolate(), is_store, call_data_undefined); |
| 9320 !optimization.is_constant_call()); | |
| 9321 Handle<Code> code = stub.GetCode(); | 9313 Handle<Code> code = stub.GetCode(); |
| 9322 HConstant* code_value = Add<HConstant>(code); | 9314 HConstant* code_value = Add<HConstant>(code); |
| 9323 ApiAccessorDescriptor descriptor(isolate()); | 9315 ApiAccessorDescriptor descriptor(isolate()); |
| 9324 call = New<HCallWithDescriptor>( | 9316 call = New<HCallWithDescriptor>( |
| 9325 code_value, argc + 1, descriptor, | 9317 code_value, argc + 1, descriptor, |
| 9326 Vector<HValue*>(op_vals, arraysize(op_vals) - 1)); | 9318 Vector<HValue*>(op_vals, arraysize(op_vals) - 1)); |
| 9327 } else if (argc <= CallApiFunctionWithFixedArgsStub::kMaxFixedArgs) { | 9319 } else if (argc <= CallApiFunctionWithFixedArgsStub::kMaxFixedArgs) { |
| 9328 CallApiFunctionWithFixedArgsStub stub(isolate(), argc, call_data_undefined); | 9320 CallApiFunctionWithFixedArgsStub stub(isolate(), argc, call_data_undefined); |
| 9329 Handle<Code> code = stub.GetCode(); | 9321 Handle<Code> code = stub.GetCode(); |
| 9330 HConstant* code_value = Add<HConstant>(code); | 9322 HConstant* code_value = Add<HConstant>(code); |
| (...skipping 4334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 13665 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 13657 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 13666 } | 13658 } |
| 13667 | 13659 |
| 13668 #ifdef DEBUG | 13660 #ifdef DEBUG |
| 13669 graph_->Verify(false); // No full verify. | 13661 graph_->Verify(false); // No full verify. |
| 13670 #endif | 13662 #endif |
| 13671 } | 13663 } |
| 13672 | 13664 |
| 13673 } // namespace internal | 13665 } // namespace internal |
| 13674 } // namespace v8 | 13666 } // namespace v8 |
| OLD | NEW |