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

Side by Side Diff: src/hydrogen.cc

Issue 148333003: crankshaft support for api method calls (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
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 7748 matching lines...) Expand 10 before | Expand all | Expand 10 after
7759 return true; 7759 return true;
7760 } 7760 }
7761 default: 7761 default:
7762 // Not yet supported for inlining. 7762 // Not yet supported for inlining.
7763 break; 7763 break;
7764 } 7764 }
7765 return false; 7765 return false;
7766 } 7766 }
7767 7767
7768 7768
7769 bool HOptimizedGraphBuilder::TryInlineApiFunctionCall(Call* expr,
7770 HValue* receiver,
7771 bool drop_extra) {
7772 return TryInlineApiCall(
7773 expr, receiver, Handle<Map>::null(), drop_extra, true);
7774 }
7775
7776
7777 bool HOptimizedGraphBuilder::TryInlineApiMethodCall(Call* expr,
7778 HValue* receiver,
7779 Handle<Map> receiver_map) {
7780 return TryInlineApiCall(expr, receiver, receiver_map, false, false);
7781 }
7782
7783 bool HOptimizedGraphBuilder::TryInlineApiCall(Call* expr,
7784 HValue* receiver,
7785 Handle<Map> receiver_map,
7786 bool drop_extra,
7787 bool is_function_call) {
7788 if (!expr->IsMonomorphic() || expr->check_type() != RECEIVER_MAP_CHECK) {
7789 return false;
7790 }
7791 CallOptimization optimization(expr->target());
7792 if (!optimization.is_simple_api_call()) return false;
7793 CallOptimization::HolderLookup holder_lookup =
7794 CallOptimization::kHolderNotFound;
7795 Handle<Map> holder_map;
7796 if (is_function_call) {
7797 // Cannot embed a direct reference to the global proxy map
7798 // as it maybe dropped on deserialization.
7799 CHECK(!Serializer::enabled());
7800 receiver_map = Handle<Map>(
7801 expr->target()->context()->global_object()->global_receiver()->map());
7802 holder_map = Handle<Map>();
7803 } else if (!expr->holder().is_null()) {
7804 holder_map = Handle<Map>(expr->holder()->map());
7805 } else {
7806 holder_map = receiver_map;
7807 }
7808 Handle<Map> holder_lookup_result = optimization.LookupHolderOfExpectedType(
7809 receiver_map, receiver_map, holder_map, &holder_lookup);
7810 if (holder_lookup == CallOptimization::kHolderNotFound) return false;
7811
7812 if (FLAG_trace_inlining) {
7813 PrintF("Inlining api function ");
7814 expr->target()->ShortPrint();
7815 PrintF("\n");
7816 }
7817
7818 if (is_function_call) {
7819 // Need to ensure the chain between receiver and api_holder is intact
7820 AddCheckMap(receiver, receiver_map);
7821 if (holder_lookup == CallOptimization::kHolderIsPrototypeOfMap) {
7822 Handle<JSObject> api_holder(
7823 JSObject::cast(holder_lookup_result->prototype()));
7824 AddCheckPrototypeMaps(api_holder, receiver_map);
7825 } else {
7826 ASSERT_EQ(holder_lookup, CallOptimization::kHolderIsReceiver);
7827 }
7828 } else {
7829 AddCheckConstantFunction(expr->holder(), receiver, receiver_map);
7830 }
7831
7832 HValue* holder = NULL;
7833 switch (holder_lookup) {
7834 case CallOptimization::kHolderIsPrototypeOfMap:
7835 {
7836 Handle<JSObject> api_holder(
7837 JSObject::cast(holder_lookup_result->prototype()));
7838 if (isolate()->heap()->InNewSpace(*api_holder)) {
7839 HValue* lookup_value = Add<HConstant>(holder_lookup_result);
7840 holder = AddLoadNamedField(
7841 lookup_value,
7842 HObjectAccess::ForJSObjectOffset(Map::kPrototypeOffset));
7843 } else {
7844 holder = Add<HConstant>(api_holder);
7845 }
7846 }
7847 break;
7848 case CallOptimization::kHolderIsReceiver:
7849 holder = environment()->ExpressionStackAt(expr->arguments()->length());
7850 break;
7851 case CallOptimization::kHolderNotFound:
7852 UNREACHABLE();
7853 break;
7854 }
7855 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
7856 Handle<Object> call_data_obj(api_call_info->data(), isolate());
7857 bool call_data_is_undefined = call_data_obj->IsUndefined();
7858 HValue* call_data = Add<HConstant>(call_data_obj);
7859 ApiFunction fun(v8::ToCData<Address>(api_call_info->callback()));
7860 ExternalReference ref = ExternalReference(&fun,
7861 ExternalReference::DIRECT_API_CALL,
7862 isolate());
7863 HValue* api_function_address = Add<HConstant>(ExternalReference(ref));
7864
7865 HValue* op_vals[] = {
7866 // callee
7867 Add<HConstant>(expr->target()),
7868 call_data,
7869 holder,
7870 api_function_address,
7871 context()
7872 };
7873
7874 const int argc = expr->arguments()->length();
7875 // Includes receiver.
7876 PushArgumentsFromEnvironment(argc + 1);
7877
7878 CallInterfaceDescriptor* descriptor =
7879 isolate()->call_descriptor(Isolate::ApiFunctionCall);
7880
7881 CallApiFunctionStub stub(true, call_data_is_undefined, argc);
7882 Handle<Code> code = stub.GetCode(isolate());
7883 HConstant* code_value = Add<HConstant>(code);
7884
7885 ASSERT((sizeof(op_vals) / kPointerSize) ==
7886 descriptor->environment_length());
7887
7888 HInstruction* call = New<HCallWithDescriptor>(
7889 code_value, argc + 1, descriptor,
7890 Vector<HValue*>(op_vals, descriptor->environment_length()));
7891
7892 if (drop_extra) Drop(1); // Drop function.
7893 ast_context()->ReturnInstruction(call, expr->id());
7894 return true;
7895 }
7896
7897
7769 bool HOptimizedGraphBuilder::TryCallApply(Call* expr) { 7898 bool HOptimizedGraphBuilder::TryCallApply(Call* expr) {
7770 Expression* callee = expr->expression(); 7899 Expression* callee = expr->expression();
7771 Property* prop = callee->AsProperty(); 7900 Property* prop = callee->AsProperty();
7772 ASSERT(prop != NULL); 7901 ASSERT(prop != NULL);
7773 7902
7774 if (!expr->IsMonomorphic() || expr->check_type() != RECEIVER_MAP_CHECK) { 7903 if (!expr->IsMonomorphic() || expr->check_type() != RECEIVER_MAP_CHECK) {
7775 return false; 7904 return false;
7776 } 7905 }
7777 Handle<Map> function_map = expr->GetReceiverTypes()->first(); 7906 Handle<Map> function_map = expr->GetReceiverTypes()->first();
7778 if (function_map->instance_type() != JS_FUNCTION_TYPE || 7907 if (function_map->instance_type() != JS_FUNCTION_TYPE ||
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
7847 ast_context()->ReturnInstruction(call, expr->id()); 7976 ast_context()->ReturnInstruction(call, expr->id());
7848 return true; 7977 return true;
7849 } 7978 }
7850 } 7979 }
7851 7980
7852 7981
7853 HValue* HOptimizedGraphBuilder::ImplicitReceiverFor(HValue* function, 7982 HValue* HOptimizedGraphBuilder::ImplicitReceiverFor(HValue* function,
7854 Handle<JSFunction> target) { 7983 Handle<JSFunction> target) {
7855 SharedFunctionInfo* shared = target->shared(); 7984 SharedFunctionInfo* shared = target->shared();
7856 if (shared->is_classic_mode() && !shared->native()) { 7985 if (shared->is_classic_mode() && !shared->native()) {
7857 HValue* context = Add<HLoadNamedField>( 7986 // Cannot embed a direct reference to the global proxy
7858 function, static_cast<HValue*>(NULL), 7987 // as is it dropped on deserialization.
7859 HObjectAccess::ForJSObjectOffset(JSFunction::kContextOffset)); 7988 CHECK(!Serializer::enabled());
7860 HValue* global_object = Add<HLoadNamedField>( 7989 Handle<JSObject> global_receiver(
7861 context, static_cast<HValue*>(NULL), 7990 target->context()->global_object()->global_receiver());
7862 HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)); 7991 return Add<HConstant>(global_receiver);
7863 return Add<HLoadNamedField>(
7864 global_object, static_cast<HValue*>(NULL),
7865 HObjectAccess::ForJSObjectOffset(
7866 GlobalObject::kGlobalReceiverOffset));
7867 } 7992 }
7868 return graph()->GetConstantUndefined(); 7993 return graph()->GetConstantUndefined();
7869 } 7994 }
7870 7995
7871 7996
7872 void HOptimizedGraphBuilder::VisitCall(Call* expr) { 7997 void HOptimizedGraphBuilder::VisitCall(Call* expr) {
7873 ASSERT(!HasStackOverflow()); 7998 ASSERT(!HasStackOverflow());
7874 ASSERT(current_block() != NULL); 7999 ASSERT(current_block() != NULL);
7875 ASSERT(current_block()->HasPredecessor()); 8000 ASSERT(current_block()->HasPredecessor());
7876 Expression* callee = expr->expression(); 8001 Expression* callee = expr->expression();
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
7929 if (monomorphic) { 8054 if (monomorphic) {
7930 Handle<Map> map = types->first(); 8055 Handle<Map> map = types->first();
7931 if (TryInlineBuiltinMethodCall(expr, receiver, map, expr->check_type())) { 8056 if (TryInlineBuiltinMethodCall(expr, receiver, map, expr->check_type())) {
7932 if (FLAG_trace_inlining) { 8057 if (FLAG_trace_inlining) {
7933 PrintF("Inlining builtin "); 8058 PrintF("Inlining builtin ");
7934 expr->target()->ShortPrint(); 8059 expr->target()->ShortPrint();
7935 PrintF("\n"); 8060 PrintF("\n");
7936 } 8061 }
7937 return; 8062 return;
7938 } 8063 }
8064 if (TryInlineApiMethodCall(expr, receiver, map)) return;
7939 8065
7940 if (CallStubCompiler::HasCustomCallGenerator(expr->target()) || 8066 AddCheckConstantFunction(expr->holder(), receiver, map);
7941 expr->check_type() != RECEIVER_MAP_CHECK) { 8067 if (TryInlineCall(expr)) return;
7942 // When the target has a custom call IC generator, use the IC, 8068 call = BuildCallConstantFunction(expr->target(), argument_count);
7943 // because it is likely to generate better code. Also use the IC 8069 PushArgumentsFromEnvironment(argument_count);
7944 // when a primitive receiver check is required.
7945 call = NewCallNamed(name, argument_count);
7946 PushArgumentsFromEnvironment(argument_count);
7947 } else {
7948 AddCheckConstantFunction(expr->holder(), receiver, map);
7949
7950 if (TryInlineCall(expr)) return;
7951 call = BuildCallConstantFunction(expr->target(), argument_count);
7952 PushArgumentsFromEnvironment(argument_count);
7953 }
7954 } else if (types != NULL && types->length() > 1) { 8070 } else if (types != NULL && types->length() > 1) {
7955 ASSERT(expr->check_type() == RECEIVER_MAP_CHECK); 8071 ASSERT(expr->check_type() == RECEIVER_MAP_CHECK);
7956 HandlePolymorphicCallNamed(expr, receiver, types, name); 8072 HandlePolymorphicCallNamed(expr, receiver, types, name);
7957 return; 8073 return;
7958 8074
7959 } else { 8075 } else {
7960 call = NewCallNamed(name, argument_count); 8076 call = NewCallNamed(name, argument_count);
7961 PushArgumentsFromEnvironment(argument_count); 8077 PushArgumentsFromEnvironment(argument_count);
7962 } 8078 }
7963 } else { 8079 } else {
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
8000 environment()->SetExpressionStackAt(receiver_index, receiver); 8116 environment()->SetExpressionStackAt(receiver_index, receiver);
8001 8117
8002 if (TryInlineBuiltinFunctionCall(expr, false)) { // Nothing to drop. 8118 if (TryInlineBuiltinFunctionCall(expr, false)) { // Nothing to drop.
8003 if (FLAG_trace_inlining) { 8119 if (FLAG_trace_inlining) {
8004 PrintF("Inlining builtin "); 8120 PrintF("Inlining builtin ");
8005 expr->target()->ShortPrint(); 8121 expr->target()->ShortPrint();
8006 PrintF("\n"); 8122 PrintF("\n");
8007 } 8123 }
8008 return; 8124 return;
8009 } 8125 }
8126 if (TryInlineApiFunctionCall(expr, receiver, false)) return;
8010 if (TryInlineCall(expr)) return; 8127 if (TryInlineCall(expr)) return;
8011 8128
8012 if (expr->target().is_identical_to(current_info()->closure())) { 8129 if (expr->target().is_identical_to(current_info()->closure())) {
8013 graph()->MarkRecursive(); 8130 graph()->MarkRecursive();
8014 } 8131 }
8015 8132
8016 if (CallStubCompiler::HasCustomCallGenerator(expr->target())) { 8133 call = BuildCallConstantFunction(expr->target(), argument_count);
8017 // We're about to install a contextual IC, which expects the global 8134 PushArgumentsFromEnvironment(argument_count);
8018 // object as receiver rather than the global proxy.
8019 HValue* global_object = Add<HLoadNamedField>(
8020 context(), static_cast<HValue*>(NULL),
8021 HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
8022 const int receiver_index = argument_count - 1;
8023 environment()->SetExpressionStackAt(receiver_index, global_object);
8024 // When the target has a custom call IC generator, use the IC,
8025 // because it is likely to generate better code.
8026 call = NewCallNamed(var->name(), argument_count);
8027 PushArgumentsFromEnvironment(argument_count);
8028 } else {
8029 call = BuildCallConstantFunction(expr->target(), argument_count);
8030 PushArgumentsFromEnvironment(argument_count);
8031 }
8032 } else { 8135 } else {
8033 HValue* receiver = Add<HLoadNamedField>( 8136 HValue* receiver = Add<HLoadNamedField>(
8034 context(), static_cast<HValue*>(NULL), 8137 context(), static_cast<HValue*>(NULL),
8035 HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)); 8138 HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
8036 Push(Add<HPushArgument>(receiver)); 8139 Push(Add<HPushArgument>(receiver));
8037 CHECK_ALIVE(VisitArgumentList(expr->arguments())); 8140 CHECK_ALIVE(VisitArgumentList(expr->arguments()));
8038 8141
8039 call = NewCallNamed(var->name(), argument_count); 8142 call = NewCallNamed(var->name(), argument_count);
8040 Drop(argument_count); 8143 Drop(argument_count);
8041 } 8144 }
(...skipping 12 matching lines...) Expand all
8054 CHECK_ALIVE(VisitExpressions(expr->arguments())); 8157 CHECK_ALIVE(VisitExpressions(expr->arguments()));
8055 8158
8056 if (TryInlineBuiltinFunctionCall(expr, true)) { // Drop the function. 8159 if (TryInlineBuiltinFunctionCall(expr, true)) { // Drop the function.
8057 if (FLAG_trace_inlining) { 8160 if (FLAG_trace_inlining) {
8058 PrintF("Inlining builtin "); 8161 PrintF("Inlining builtin ");
8059 expr->target()->ShortPrint(); 8162 expr->target()->ShortPrint();
8060 PrintF("\n"); 8163 PrintF("\n");
8061 } 8164 }
8062 return; 8165 return;
8063 } 8166 }
8167 if (TryInlineApiFunctionCall(expr, receiver, true)) return;
8064 8168
8065 if (TryInlineCall(expr, true)) { // Drop function from environment. 8169 if (TryInlineCall(expr, true)) { // Drop function from environment.
8066 return; 8170 return;
8067 } else { 8171 } else {
8068 call = PreProcessCall(New<HInvokeFunction>(function, expr->target(), 8172 call = PreProcessCall(New<HInvokeFunction>(function, expr->target(),
8069 argument_count)); 8173 argument_count));
8070 Drop(1); // The function. 8174 Drop(1); // The function.
8071 } 8175 }
8072 8176
8073 } else { 8177 } else {
(...skipping 3080 matching lines...) Expand 10 before | Expand all | Expand 10 after
11154 if (ShouldProduceTraceOutput()) { 11258 if (ShouldProduceTraceOutput()) {
11155 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); 11259 isolate()->GetHTracer()->TraceHydrogen(name(), graph_);
11156 } 11260 }
11157 11261
11158 #ifdef DEBUG 11262 #ifdef DEBUG
11159 graph_->Verify(false); // No full verify. 11263 graph_->Verify(false); // No full verify.
11160 #endif 11264 #endif
11161 } 11265 }
11162 11266
11163 } } // namespace v8::internal 11267 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/ia32/code-stubs-ia32.cc » ('j') | src/stub-cache.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698