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

Side by Side Diff: src/hydrogen.cc

Issue 146023004: inline api getters in crankshaft (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: rebase Created 6 years, 10 months 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 | Annotate | Revision Log
« no previous file with comments | « src/hydrogen.h ('k') | test/cctest/test-api.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 5343 matching lines...) Expand 10 before | Expand all | Expand 10 after
5354 if (!lookup_.IsFound()) { 5354 if (!lookup_.IsFound()) {
5355 return (!info->lookup_.IsFound() || info->has_holder()) && 5355 return (!info->lookup_.IsFound() || info->has_holder()) &&
5356 map()->prototype() == info->map()->prototype(); 5356 map()->prototype() == info->map()->prototype();
5357 } 5357 }
5358 5358
5359 // Mismatch if the other access info found the property in the prototype 5359 // Mismatch if the other access info found the property in the prototype
5360 // chain. 5360 // chain.
5361 if (info->has_holder()) return false; 5361 if (info->has_holder()) return false;
5362 5362
5363 if (lookup_.IsPropertyCallbacks()) { 5363 if (lookup_.IsPropertyCallbacks()) {
5364 return accessor_.is_identical_to(info->accessor_); 5364 return accessor_.is_identical_to(info->accessor_) &&
5365 api_holder_.is_identical_to(info->api_holder_);
5365 } 5366 }
5366 5367
5367 if (lookup_.IsConstant()) { 5368 if (lookup_.IsConstant()) {
5368 return constant_.is_identical_to(info->constant_); 5369 return constant_.is_identical_to(info->constant_);
5369 } 5370 }
5370 5371
5371 ASSERT(lookup_.IsField()); 5372 ASSERT(lookup_.IsField());
5372 if (!info->lookup_.IsField()) return false; 5373 if (!info->lookup_.IsField()) return false;
5373 5374
5374 Representation r = access_.representation(); 5375 Representation r = access_.representation();
(...skipping 25 matching lines...) Expand all
5400 if (lookup_.IsField()) { 5401 if (lookup_.IsField()) {
5401 access_ = HObjectAccess::ForField(map, &lookup_, name_); 5402 access_ = HObjectAccess::ForField(map, &lookup_, name_);
5402 } else if (lookup_.IsPropertyCallbacks()) { 5403 } else if (lookup_.IsPropertyCallbacks()) {
5403 Handle<Object> callback(lookup_.GetValueFromMap(*map), isolate()); 5404 Handle<Object> callback(lookup_.GetValueFromMap(*map), isolate());
5404 if (!callback->IsAccessorPair()) return false; 5405 if (!callback->IsAccessorPair()) return false;
5405 Object* raw_accessor = IsLoad() 5406 Object* raw_accessor = IsLoad()
5406 ? Handle<AccessorPair>::cast(callback)->getter() 5407 ? Handle<AccessorPair>::cast(callback)->getter()
5407 : Handle<AccessorPair>::cast(callback)->setter(); 5408 : Handle<AccessorPair>::cast(callback)->setter();
5408 if (!raw_accessor->IsJSFunction()) return false; 5409 if (!raw_accessor->IsJSFunction()) return false;
5409 Handle<JSFunction> accessor = handle(JSFunction::cast(raw_accessor)); 5410 Handle<JSFunction> accessor = handle(JSFunction::cast(raw_accessor));
5410 CallOptimization call_optimization(accessor); 5411 if (accessor->shared()->IsApiFunction()) {
5411 // TODO(dcarney): temporary hack unless crankshaft can handle api calls. 5412 CallOptimization call_optimization(accessor);
5412 if (call_optimization.is_simple_api_call()) return false; 5413 if (!call_optimization.is_simple_api_call()) return false;
5414 CallOptimization::HolderLookup holder_lookup;
5415 api_holder_ = call_optimization.LookupHolderOfExpectedType(
5416 map, &holder_lookup);
5417 switch (holder_lookup) {
5418 case CallOptimization::kHolderNotFound:
5419 return false;
5420 case CallOptimization::kHolderIsReceiver:
5421 case CallOptimization::kHolderFound:
5422 break;
5423 }
5424 }
5413 accessor_ = accessor; 5425 accessor_ = accessor;
5414 } else if (lookup_.IsConstant()) { 5426 } else if (lookup_.IsConstant()) {
5415 constant_ = handle(lookup_.GetConstantFromMap(*map), isolate()); 5427 constant_ = handle(lookup_.GetConstantFromMap(*map), isolate());
5416 } 5428 }
5417 5429
5418 return true; 5430 return true;
5419 } 5431 }
5420 5432
5421 5433
5422 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes() { 5434 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes() {
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
5565 argument_count = 2; 5577 argument_count = 2;
5566 Push(value); 5578 Push(value);
5567 } 5579 }
5568 5580
5569 if (NeedsWrappingFor(info->type(), info->accessor())) { 5581 if (NeedsWrappingFor(info->type(), info->accessor())) {
5570 HValue* function = Add<HConstant>(info->accessor()); 5582 HValue* function = Add<HConstant>(info->accessor());
5571 PushArgumentsFromEnvironment(argument_count); 5583 PushArgumentsFromEnvironment(argument_count);
5572 return New<HCallFunction>(function, argument_count, WRAP_AND_CALL); 5584 return New<HCallFunction>(function, argument_count, WRAP_AND_CALL);
5573 } else if (FLAG_inline_accessors && can_inline_accessor) { 5585 } else if (FLAG_inline_accessors && can_inline_accessor) {
5574 bool success = info->IsLoad() 5586 bool success = info->IsLoad()
5575 ? TryInlineGetter(info->accessor(), ast_id, return_id) 5587 ? TryInlineGetter(info->accessor(), info->map(), ast_id, return_id)
5576 : TryInlineSetter(info->accessor(), ast_id, return_id, value); 5588 : TryInlineSetter(info->accessor(), ast_id, return_id, value);
5577 if (success) return NULL; 5589 if (success) return NULL;
5578 } 5590 }
5579 5591
5580 PushArgumentsFromEnvironment(argument_count); 5592 PushArgumentsFromEnvironment(argument_count);
5581 return BuildCallConstantFunction(info->accessor(), argument_count); 5593 return BuildCallConstantFunction(info->accessor(), argument_count);
5582 } 5594 }
5583 5595
5584 ASSERT(info->lookup()->IsConstant()); 5596 ASSERT(info->lookup()->IsConstant());
5585 if (info->IsLoad()) { 5597 if (info->IsLoad()) {
(...skipping 1801 matching lines...) Expand 10 before | Expand all | Expand 10 after
7387 return TryInline(expr->target(), 7399 return TryInline(expr->target(),
7388 expr->arguments()->length(), 7400 expr->arguments()->length(),
7389 implicit_return_value, 7401 implicit_return_value,
7390 expr->id(), 7402 expr->id(),
7391 expr->ReturnId(), 7403 expr->ReturnId(),
7392 CONSTRUCT_CALL_RETURN); 7404 CONSTRUCT_CALL_RETURN);
7393 } 7405 }
7394 7406
7395 7407
7396 bool HOptimizedGraphBuilder::TryInlineGetter(Handle<JSFunction> getter, 7408 bool HOptimizedGraphBuilder::TryInlineGetter(Handle<JSFunction> getter,
7409 Handle<Map> receiver_map,
7397 BailoutId ast_id, 7410 BailoutId ast_id,
7398 BailoutId return_id) { 7411 BailoutId return_id) {
7412 if (TryInlineApiGetter(getter, receiver_map, ast_id)) return true;
7399 return TryInline(getter, 7413 return TryInline(getter,
7400 0, 7414 0,
7401 NULL, 7415 NULL,
7402 ast_id, 7416 ast_id,
7403 return_id, 7417 return_id,
7404 GETTER_CALL_RETURN); 7418 GETTER_CALL_RETURN);
7405 } 7419 }
7406 7420
7407 7421
7408 bool HOptimizedGraphBuilder::TryInlineSetter(Handle<JSFunction> setter, 7422 bool HOptimizedGraphBuilder::TryInlineSetter(Handle<JSFunction> setter,
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after
7671 default: 7685 default:
7672 // Not yet supported for inlining. 7686 // Not yet supported for inlining.
7673 break; 7687 break;
7674 } 7688 }
7675 return false; 7689 return false;
7676 } 7690 }
7677 7691
7678 7692
7679 bool HOptimizedGraphBuilder::TryInlineApiFunctionCall(Call* expr, 7693 bool HOptimizedGraphBuilder::TryInlineApiFunctionCall(Call* expr,
7680 HValue* receiver) { 7694 HValue* receiver) {
7681 return TryInlineApiCall( 7695 Handle<JSFunction> function = expr->target();
7682 expr, receiver, Handle<Map>::null(), true); 7696 int argc = expr->arguments()->length();
7697 SmallMapList receiver_maps;
7698 return TryInlineApiCall(function,
7699 receiver,
7700 &receiver_maps,
7701 argc,
7702 expr->id(),
7703 kCallApiFunction);
7683 } 7704 }
7684 7705
7685 7706
7686 bool HOptimizedGraphBuilder::TryInlineApiMethodCall(Call* expr, 7707 bool HOptimizedGraphBuilder::TryInlineApiMethodCall(
7687 HValue* receiver, 7708 Call* expr,
7688 Handle<Map> receiver_map) { 7709 HValue* receiver,
7689 return TryInlineApiCall(expr, receiver, receiver_map, false); 7710 SmallMapList* receiver_maps) {
7711 Handle<JSFunction> function = expr->target();
7712 int argc = expr->arguments()->length();
7713 return TryInlineApiCall(function,
7714 receiver,
7715 receiver_maps,
7716 argc,
7717 expr->id(),
7718 kCallApiMethod);
7690 } 7719 }
7691 7720
7692 bool HOptimizedGraphBuilder::TryInlineApiCall(Call* expr, 7721
7693 HValue* receiver, 7722 bool HOptimizedGraphBuilder::TryInlineApiGetter(Handle<JSFunction> function,
7694 Handle<Map> receiver_map, 7723 Handle<Map> receiver_map,
7695 bool is_function_call) { 7724 BailoutId ast_id) {
7696 if (!expr->IsMonomorphic()) return false; 7725 SmallMapList receiver_maps(1, zone());
7697 CallOptimization optimization(expr->target()); 7726 receiver_maps.Add(receiver_map, zone());
7727 return TryInlineApiCall(function,
7728 NULL, // Receiver is on expression stack.
7729 &receiver_maps,
7730 0,
7731 ast_id,
7732 kCallApiGetter);
7733 }
7734
7735
7736 bool HOptimizedGraphBuilder::TryInlineApiCall(Handle<JSFunction> function,
7737 HValue* receiver,
7738 SmallMapList* receiver_maps,
7739 int argc,
7740 BailoutId ast_id,
7741 ApiCallType call_type) {
7742 CallOptimization optimization(function);
7698 if (!optimization.is_simple_api_call()) return false; 7743 if (!optimization.is_simple_api_call()) return false;
7699 Handle<Map> holder_map; 7744 Handle<Map> holder_map;
7700 if (is_function_call) { 7745 if (call_type == kCallApiFunction) {
7701 // Cannot embed a direct reference to the global proxy map 7746 // Cannot embed a direct reference to the global proxy map
7702 // as it maybe dropped on deserialization. 7747 // as it maybe dropped on deserialization.
7703 CHECK(!Serializer::enabled()); 7748 CHECK(!Serializer::enabled());
7704 receiver_map = Handle<Map>( 7749 ASSERT_EQ(0, receiver_maps->length());
7705 expr->target()->context()->global_object()->global_receiver()->map()); 7750 receiver_maps->Add(handle(
7751 function->context()->global_object()->global_receiver()->map()),
7752 zone());
7706 } 7753 }
7707 CallOptimization::HolderLookup holder_lookup = 7754 CallOptimization::HolderLookup holder_lookup =
7708 CallOptimization::kHolderNotFound; 7755 CallOptimization::kHolderNotFound;
7709 Handle<JSObject> api_holder = optimization.LookupHolderOfExpectedType( 7756 Handle<JSObject> api_holder = optimization.LookupHolderOfExpectedType(
7710 receiver_map, &holder_lookup); 7757 receiver_maps->first(), &holder_lookup);
7711 if (holder_lookup == CallOptimization::kHolderNotFound) return false; 7758 if (holder_lookup == CallOptimization::kHolderNotFound) return false;
7712 7759
7713 if (FLAG_trace_inlining) { 7760 if (FLAG_trace_inlining) {
7714 PrintF("Inlining api function "); 7761 PrintF("Inlining api function ");
7715 expr->target()->ShortPrint(); 7762 function->ShortPrint();
7716 PrintF("\n"); 7763 PrintF("\n");
7717 } 7764 }
7718 7765
7719 const int argc = expr->arguments()->length(); 7766 bool drop_extra = false;
7720 // Includes receiver. 7767 switch (call_type) {
7721 PushArgumentsFromEnvironment(argc + 1); 7768 case kCallApiFunction:
7722 7769 case kCallApiMethod:
7723 // Need to ensure the chain between receiver and api_holder is intact 7770 // Need to check that none of the receiver maps could have changed.
7724 AddCheckMap(receiver, receiver_map); 7771 Add<HCheckMaps>(receiver, receiver_maps);
7725 if (holder_lookup == CallOptimization::kHolderFound) { 7772 // Need to ensure the chain between receiver and api_holder is intact.
7726 AddCheckPrototypeMaps(api_holder, receiver_map); 7773 if (holder_lookup == CallOptimization::kHolderFound) {
7727 } else { 7774 AddCheckPrototypeMaps(api_holder, receiver_maps->first());
7728 ASSERT_EQ(holder_lookup, CallOptimization::kHolderIsReceiver); 7775 } else {
7776 ASSERT_EQ(holder_lookup, CallOptimization::kHolderIsReceiver);
7777 }
7778 // Includes receiver.
7779 PushArgumentsFromEnvironment(argc + 1);
7780 // Drop function after call.
7781 drop_extra = true;
7782 break;
7783 case kCallApiGetter:
7784 // Receiver and prototype chain cannot have changed.
7785 ASSERT_EQ(0, argc);
7786 ASSERT_EQ(NULL, receiver);
7787 // Receiver is on expression stack.
7788 receiver = Pop();
7789 Add<HPushArgument>(receiver);
7790 break;
7729 } 7791 }
7730 7792
7731 HValue* holder = NULL; 7793 HValue* holder = NULL;
7732 switch (holder_lookup) { 7794 switch (holder_lookup) {
7733 case CallOptimization::kHolderFound: 7795 case CallOptimization::kHolderFound:
7734 holder = Add<HConstant>(api_holder); 7796 holder = Add<HConstant>(api_holder);
7735 break; 7797 break;
7736 case CallOptimization::kHolderIsReceiver: 7798 case CallOptimization::kHolderIsReceiver:
7737 holder = receiver; 7799 holder = receiver;
7738 break; 7800 break;
7739 case CallOptimization::kHolderNotFound: 7801 case CallOptimization::kHolderNotFound:
7740 UNREACHABLE(); 7802 UNREACHABLE();
7741 break; 7803 break;
7742 } 7804 }
7743 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); 7805 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
7744 Handle<Object> call_data_obj(api_call_info->data(), isolate()); 7806 Handle<Object> call_data_obj(api_call_info->data(), isolate());
7745 bool call_data_is_undefined = call_data_obj->IsUndefined(); 7807 bool call_data_is_undefined = call_data_obj->IsUndefined();
7746 HValue* call_data = Add<HConstant>(call_data_obj); 7808 HValue* call_data = Add<HConstant>(call_data_obj);
7747 ApiFunction fun(v8::ToCData<Address>(api_call_info->callback())); 7809 ApiFunction fun(v8::ToCData<Address>(api_call_info->callback()));
7748 ExternalReference ref = ExternalReference(&fun, 7810 ExternalReference ref = ExternalReference(&fun,
7749 ExternalReference::DIRECT_API_CALL, 7811 ExternalReference::DIRECT_API_CALL,
7750 isolate()); 7812 isolate());
7751 HValue* api_function_address = Add<HConstant>(ExternalReference(ref)); 7813 HValue* api_function_address = Add<HConstant>(ExternalReference(ref));
7752 7814
7753 HValue* op_vals[] = { 7815 HValue* op_vals[] = {
7754 // callee 7816 Add<HConstant>(function),
7755 Add<HConstant>(expr->target()),
7756 call_data, 7817 call_data,
7757 holder, 7818 holder,
7758 api_function_address, 7819 api_function_address,
7759 context() 7820 context()
7760 }; 7821 };
7761 7822
7762 CallInterfaceDescriptor* descriptor = 7823 CallInterfaceDescriptor* descriptor =
7763 isolate()->call_descriptor(Isolate::ApiFunctionCall); 7824 isolate()->call_descriptor(Isolate::ApiFunctionCall);
7764 7825
7765 CallApiFunctionStub stub(true, call_data_is_undefined, argc); 7826 CallApiFunctionStub stub(true, call_data_is_undefined, argc);
7766 Handle<Code> code = stub.GetCode(isolate()); 7827 Handle<Code> code = stub.GetCode(isolate());
7767 HConstant* code_value = Add<HConstant>(code); 7828 HConstant* code_value = Add<HConstant>(code);
7768 7829
7769 ASSERT((sizeof(op_vals) / kPointerSize) == 7830 ASSERT((sizeof(op_vals) / kPointerSize) ==
7770 descriptor->environment_length()); 7831 descriptor->environment_length());
7771 7832
7772 HInstruction* call = New<HCallWithDescriptor>( 7833 HInstruction* call = New<HCallWithDescriptor>(
7773 code_value, argc + 1, descriptor, 7834 code_value, argc + 1, descriptor,
7774 Vector<HValue*>(op_vals, descriptor->environment_length())); 7835 Vector<HValue*>(op_vals, descriptor->environment_length()));
7775 7836
7776 Drop(1); // Drop function. 7837 if (drop_extra) Drop(1); // Drop function.
7777 ast_context()->ReturnInstruction(call, expr->id()); 7838 ast_context()->ReturnInstruction(call, ast_id);
7778 return true; 7839 return true;
7779 } 7840 }
7780 7841
7781 7842
7782 bool HOptimizedGraphBuilder::TryCallApply(Call* expr) { 7843 bool HOptimizedGraphBuilder::TryCallApply(Call* expr) {
7783 ASSERT(expr->expression()->IsProperty()); 7844 ASSERT(expr->expression()->IsProperty());
7784 7845
7785 if (!expr->IsMonomorphic()) { 7846 if (!expr->IsMonomorphic()) {
7786 return false; 7847 return false;
7787 } 7848 }
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
7916 7977
7917 Handle<Map> map = types->length() == 1 ? types->first() : Handle<Map>(); 7978 Handle<Map> map = types->length() == 1 ? types->first() : Handle<Map>();
7918 if (TryInlineBuiltinMethodCall(expr, receiver, map)) { 7979 if (TryInlineBuiltinMethodCall(expr, receiver, map)) {
7919 if (FLAG_trace_inlining) { 7980 if (FLAG_trace_inlining) {
7920 PrintF("Inlining builtin "); 7981 PrintF("Inlining builtin ");
7921 known_function->ShortPrint(); 7982 known_function->ShortPrint();
7922 PrintF("\n"); 7983 PrintF("\n");
7923 } 7984 }
7924 return; 7985 return;
7925 } 7986 }
7926 if (TryInlineApiMethodCall(expr, receiver, map)) return; 7987 if (TryInlineApiMethodCall(expr, receiver, types)) return;
7927 7988
7928 // Wrap the receiver if necessary. 7989 // Wrap the receiver if necessary.
7929 if (NeedsWrappingFor(ToType(types->first()), known_function)) { 7990 if (NeedsWrappingFor(ToType(types->first()), known_function)) {
7930 // Since HWrapReceiver currently cannot actually wrap numbers and 7991 // Since HWrapReceiver currently cannot actually wrap numbers and
7931 // strings, use the regular CallFunctionStub for method calls to wrap 7992 // strings, use the regular CallFunctionStub for method calls to wrap
7932 // the receiver. 7993 // the receiver.
7933 // TODO(verwaest): Support creation of value wrappers directly in 7994 // TODO(verwaest): Support creation of value wrappers directly in
7934 // HWrapReceiver. 7995 // HWrapReceiver.
7935 call = New<HCallFunction>( 7996 call = New<HCallFunction>(
7936 function, argument_count, WRAP_AND_CALL); 7997 function, argument_count, WRAP_AND_CALL);
(...skipping 3206 matching lines...) Expand 10 before | Expand all | Expand 10 after
11143 if (ShouldProduceTraceOutput()) { 11204 if (ShouldProduceTraceOutput()) {
11144 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); 11205 isolate()->GetHTracer()->TraceHydrogen(name(), graph_);
11145 } 11206 }
11146 11207
11147 #ifdef DEBUG 11208 #ifdef DEBUG
11148 graph_->Verify(false); // No full verify. 11209 graph_->Verify(false); // No full verify.
11149 #endif 11210 #endif
11150 } 11211 }
11151 11212
11152 } } // namespace v8::internal 11213 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | test/cctest/test-api.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698