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

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: fix 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') | src/ia32/code-stubs-ia32.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 7934 matching lines...) Expand 10 before | Expand all | Expand 10 after
7945 return true; 7945 return true;
7946 } 7946 }
7947 default: 7947 default:
7948 // Not yet supported for inlining. 7948 // Not yet supported for inlining.
7949 break; 7949 break;
7950 } 7950 }
7951 return false; 7951 return false;
7952 } 7952 }
7953 7953
7954 7954
7955 bool HOptimizedGraphBuilder::TryInlineApiFunctionCall(Call* expr,
7956 HValue* receiver,
7957 bool drop_extra) {
7958 return TryInlineApiCall(
7959 expr, receiver, Handle<Map>::null(), drop_extra, true);
7960 }
7961
7962
7963 bool HOptimizedGraphBuilder::TryInlineApiMethodCall(Call* expr,
7964 HValue* receiver,
7965 Handle<Map> receiver_map) {
7966 return TryInlineApiCall(expr, receiver, receiver_map, false, false);
7967 }
7968
7969 bool HOptimizedGraphBuilder::TryInlineApiCall(Call* expr,
7970 HValue* receiver,
7971 Handle<Map> receiver_map,
7972 bool drop_extra,
7973 bool is_function_call) {
7974 if (!expr->IsMonomorphic() || expr->check_type() != RECEIVER_MAP_CHECK) {
7975 return false;
7976 }
7977 CallOptimization optimization(expr->target());
7978 if (!optimization.is_simple_api_call()) return false;
7979 Handle<Map> holder_map;
7980 if (is_function_call) {
7981 // Cannot embed a direct reference to the global proxy map
7982 // as it maybe dropped on deserialization.
7983 CHECK(!Serializer::enabled());
7984 receiver_map = Handle<Map>(
7985 expr->target()->context()->global_object()->global_receiver()->map());
7986 }
7987 CallOptimization::HolderLookup holder_lookup =
7988 CallOptimization::kHolderNotFound;
7989 Handle<JSObject> api_holder = optimization.LookupHolderOfExpectedType(
7990 receiver_map, &holder_lookup);
7991 if (holder_lookup == CallOptimization::kHolderNotFound) return false;
7992
7993 if (FLAG_trace_inlining) {
7994 PrintF("Inlining api function ");
7995 expr->target()->ShortPrint();
7996 PrintF("\n");
7997 }
7998
7999 // Need to ensure the chain between receiver and api_holder is intact
8000 AddCheckMap(receiver, receiver_map);
8001 if (holder_lookup == CallOptimization::kHolderFound) {
8002 AddCheckPrototypeMaps(api_holder, receiver_map);
8003 } else {
8004 ASSERT_EQ(holder_lookup, CallOptimization::kHolderIsReceiver);
8005 }
8006
8007 // TODO(verwaest): remove.
8008 if (!is_function_call) {
8009 AddCheckConstantFunction(expr->holder(), receiver, receiver_map);
8010 }
8011
8012 HValue* holder = NULL;
8013 switch (holder_lookup) {
8014 case CallOptimization::kHolderFound:
8015 holder = Add<HConstant>(api_holder);
8016 break;
8017 case CallOptimization::kHolderIsReceiver:
8018 holder = environment()->ExpressionStackAt(expr->arguments()->length());
8019 break;
8020 case CallOptimization::kHolderNotFound:
8021 UNREACHABLE();
8022 break;
8023 }
8024 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
8025 Handle<Object> call_data_obj(api_call_info->data(), isolate());
8026 bool call_data_is_undefined = call_data_obj->IsUndefined();
8027 HValue* call_data = Add<HConstant>(call_data_obj);
8028 ApiFunction fun(v8::ToCData<Address>(api_call_info->callback()));
8029 ExternalReference ref = ExternalReference(&fun,
8030 ExternalReference::DIRECT_API_CALL,
8031 isolate());
8032 HValue* api_function_address = Add<HConstant>(ExternalReference(ref));
8033
8034 HValue* op_vals[] = {
8035 // callee
8036 Add<HConstant>(expr->target()),
8037 call_data,
8038 holder,
8039 api_function_address,
8040 context()
8041 };
8042
8043 const int argc = expr->arguments()->length();
8044 // Includes receiver.
8045 PushArgumentsFromEnvironment(argc + 1);
8046
8047 CallInterfaceDescriptor* descriptor =
8048 isolate()->call_descriptor(Isolate::ApiFunctionCall);
8049
8050 CallApiFunctionStub stub(true, call_data_is_undefined, argc);
8051 Handle<Code> code = stub.GetCode(isolate());
8052 HConstant* code_value = Add<HConstant>(code);
8053
8054 ASSERT((sizeof(op_vals) / kPointerSize) ==
8055 descriptor->environment_length());
8056
8057 HInstruction* call = New<HCallWithDescriptor>(
8058 code_value, argc + 1, descriptor,
8059 Vector<HValue*>(op_vals, descriptor->environment_length()));
8060
8061 if (drop_extra) Drop(1); // Drop function.
8062 ast_context()->ReturnInstruction(call, expr->id());
8063 return true;
8064 }
8065
8066
7955 bool HOptimizedGraphBuilder::TryCallApply(Call* expr) { 8067 bool HOptimizedGraphBuilder::TryCallApply(Call* expr) {
7956 Expression* callee = expr->expression(); 8068 Expression* callee = expr->expression();
7957 Property* prop = callee->AsProperty(); 8069 Property* prop = callee->AsProperty();
7958 ASSERT(prop != NULL); 8070 ASSERT(prop != NULL);
7959 8071
7960 if (!expr->IsMonomorphic() || expr->check_type() != RECEIVER_MAP_CHECK) { 8072 if (!expr->IsMonomorphic() || expr->check_type() != RECEIVER_MAP_CHECK) {
7961 return false; 8073 return false;
7962 } 8074 }
7963 Handle<Map> function_map = expr->GetReceiverTypes()->first(); 8075 Handle<Map> function_map = expr->GetReceiverTypes()->first();
7964 if (function_map->instance_type() != JS_FUNCTION_TYPE || 8076 if (function_map->instance_type() != JS_FUNCTION_TYPE ||
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
8033 ast_context()->ReturnInstruction(call, expr->id()); 8145 ast_context()->ReturnInstruction(call, expr->id());
8034 return true; 8146 return true;
8035 } 8147 }
8036 } 8148 }
8037 8149
8038 8150
8039 HValue* HOptimizedGraphBuilder::ImplicitReceiverFor(HValue* function, 8151 HValue* HOptimizedGraphBuilder::ImplicitReceiverFor(HValue* function,
8040 Handle<JSFunction> target) { 8152 Handle<JSFunction> target) {
8041 SharedFunctionInfo* shared = target->shared(); 8153 SharedFunctionInfo* shared = target->shared();
8042 if (shared->is_classic_mode() && !shared->native()) { 8154 if (shared->is_classic_mode() && !shared->native()) {
8043 HValue* context = Add<HLoadNamedField>( 8155 // Cannot embed a direct reference to the global proxy
8044 function, static_cast<HValue*>(NULL), 8156 // as is it dropped on deserialization.
8045 HObjectAccess::ForJSObjectOffset(JSFunction::kContextOffset)); 8157 CHECK(!Serializer::enabled());
8046 HValue* global_object = Add<HLoadNamedField>( 8158 Handle<JSObject> global_receiver(
8047 context, static_cast<HValue*>(NULL), 8159 target->context()->global_object()->global_receiver());
8048 HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)); 8160 return Add<HConstant>(global_receiver);
8049 return Add<HLoadNamedField>(
8050 global_object, static_cast<HValue*>(NULL),
8051 HObjectAccess::ForJSObjectOffset(
8052 GlobalObject::kGlobalReceiverOffset));
8053 } 8161 }
8054 return graph()->GetConstantUndefined(); 8162 return graph()->GetConstantUndefined();
8055 } 8163 }
8056 8164
8057 8165
8058 void HOptimizedGraphBuilder::VisitCall(Call* expr) { 8166 void HOptimizedGraphBuilder::VisitCall(Call* expr) {
8059 ASSERT(!HasStackOverflow()); 8167 ASSERT(!HasStackOverflow());
8060 ASSERT(current_block() != NULL); 8168 ASSERT(current_block() != NULL);
8061 ASSERT(current_block()->HasPredecessor()); 8169 ASSERT(current_block()->HasPredecessor());
8062 Expression* callee = expr->expression(); 8170 Expression* callee = expr->expression();
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
8115 if (monomorphic) { 8223 if (monomorphic) {
8116 Handle<Map> map = types->first(); 8224 Handle<Map> map = types->first();
8117 if (TryInlineBuiltinMethodCall(expr, receiver, map, expr->check_type())) { 8225 if (TryInlineBuiltinMethodCall(expr, receiver, map, expr->check_type())) {
8118 if (FLAG_trace_inlining) { 8226 if (FLAG_trace_inlining) {
8119 PrintF("Inlining builtin "); 8227 PrintF("Inlining builtin ");
8120 expr->target()->ShortPrint(); 8228 expr->target()->ShortPrint();
8121 PrintF("\n"); 8229 PrintF("\n");
8122 } 8230 }
8123 return; 8231 return;
8124 } 8232 }
8233 if (TryInlineApiMethodCall(expr, receiver, map)) return;
8125 8234
8126 if (CallStubCompiler::HasCustomCallGenerator(expr->target()) || 8235 if (expr->check_type() != RECEIVER_MAP_CHECK) {
8127 expr->check_type() != RECEIVER_MAP_CHECK) {
8128 // When the target has a custom call IC generator, use the IC,
8129 // because it is likely to generate better code. Also use the IC
8130 // when a primitive receiver check is required.
8131 call = NewCallNamed(name, argument_count); 8236 call = NewCallNamed(name, argument_count);
8132 PushArgumentsFromEnvironment(argument_count); 8237 PushArgumentsFromEnvironment(argument_count);
8133 } else { 8238 } else {
8134 AddCheckConstantFunction(expr->holder(), receiver, map); 8239 AddCheckConstantFunction(expr->holder(), receiver, map);
8135 8240
8136 if (TryInlineCall(expr)) return; 8241 if (TryInlineCall(expr)) return;
8137 call = BuildCallConstantFunction(expr->target(), argument_count); 8242 call = BuildCallConstantFunction(expr->target(), argument_count);
8138 PushArgumentsFromEnvironment(argument_count); 8243 PushArgumentsFromEnvironment(argument_count);
8139 } 8244 }
8140 } else if (types != NULL && types->length() > 1) { 8245 } else if (types != NULL && types->length() > 1) {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
8186 environment()->SetExpressionStackAt(receiver_index, receiver); 8291 environment()->SetExpressionStackAt(receiver_index, receiver);
8187 8292
8188 if (TryInlineBuiltinFunctionCall(expr, false)) { // Nothing to drop. 8293 if (TryInlineBuiltinFunctionCall(expr, false)) { // Nothing to drop.
8189 if (FLAG_trace_inlining) { 8294 if (FLAG_trace_inlining) {
8190 PrintF("Inlining builtin "); 8295 PrintF("Inlining builtin ");
8191 expr->target()->ShortPrint(); 8296 expr->target()->ShortPrint();
8192 PrintF("\n"); 8297 PrintF("\n");
8193 } 8298 }
8194 return; 8299 return;
8195 } 8300 }
8301 if (TryInlineApiFunctionCall(expr, receiver, false)) return;
8196 if (TryInlineCall(expr)) return; 8302 if (TryInlineCall(expr)) return;
8197 8303
8198 if (expr->target().is_identical_to(current_info()->closure())) { 8304 if (expr->target().is_identical_to(current_info()->closure())) {
8199 graph()->MarkRecursive(); 8305 graph()->MarkRecursive();
8200 } 8306 }
8201 8307
8202 if (CallStubCompiler::HasCustomCallGenerator(expr->target())) { 8308 call = BuildCallConstantFunction(expr->target(), argument_count);
8203 // We're about to install a contextual IC, which expects the global 8309 PushArgumentsFromEnvironment(argument_count);
8204 // object as receiver rather than the global proxy.
8205 HValue* global_object = Add<HLoadNamedField>(
8206 context(), static_cast<HValue*>(NULL),
8207 HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
8208 const int receiver_index = argument_count - 1;
8209 environment()->SetExpressionStackAt(receiver_index, global_object);
8210 // When the target has a custom call IC generator, use the IC,
8211 // because it is likely to generate better code.
8212 call = NewCallNamed(var->name(), argument_count);
8213 PushArgumentsFromEnvironment(argument_count);
8214 } else {
8215 call = BuildCallConstantFunction(expr->target(), argument_count);
8216 PushArgumentsFromEnvironment(argument_count);
8217 }
8218 } else { 8310 } else {
8219 HValue* receiver = Add<HLoadNamedField>( 8311 HValue* receiver = Add<HLoadNamedField>(
8220 context(), static_cast<HValue*>(NULL), 8312 context(), static_cast<HValue*>(NULL),
8221 HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)); 8313 HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
8222 Push(Add<HPushArgument>(receiver)); 8314 Push(Add<HPushArgument>(receiver));
8223 CHECK_ALIVE(VisitArgumentList(expr->arguments())); 8315 CHECK_ALIVE(VisitArgumentList(expr->arguments()));
8224 8316
8225 call = NewCallNamed(var->name(), argument_count); 8317 call = NewCallNamed(var->name(), argument_count);
8226 Drop(argument_count); 8318 Drop(argument_count);
8227 } 8319 }
(...skipping 12 matching lines...) Expand all
8240 CHECK_ALIVE(VisitExpressions(expr->arguments())); 8332 CHECK_ALIVE(VisitExpressions(expr->arguments()));
8241 8333
8242 if (TryInlineBuiltinFunctionCall(expr, true)) { // Drop the function. 8334 if (TryInlineBuiltinFunctionCall(expr, true)) { // Drop the function.
8243 if (FLAG_trace_inlining) { 8335 if (FLAG_trace_inlining) {
8244 PrintF("Inlining builtin "); 8336 PrintF("Inlining builtin ");
8245 expr->target()->ShortPrint(); 8337 expr->target()->ShortPrint();
8246 PrintF("\n"); 8338 PrintF("\n");
8247 } 8339 }
8248 return; 8340 return;
8249 } 8341 }
8342 if (TryInlineApiFunctionCall(expr, receiver, true)) return;
8250 8343
8251 if (TryInlineCall(expr, true)) { // Drop function from environment. 8344 if (TryInlineCall(expr, true)) { // Drop function from environment.
8252 return; 8345 return;
8253 } else { 8346 } else {
8254 call = PreProcessCall(New<HInvokeFunction>(function, expr->target(), 8347 call = PreProcessCall(New<HInvokeFunction>(function, expr->target(),
8255 argument_count)); 8348 argument_count));
8256 Drop(1); // The function. 8349 Drop(1); // The function.
8257 } 8350 }
8258 8351
8259 } else { 8352 } else {
(...skipping 3102 matching lines...) Expand 10 before | Expand all | Expand 10 after
11362 if (ShouldProduceTraceOutput()) { 11455 if (ShouldProduceTraceOutput()) {
11363 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); 11456 isolate()->GetHTracer()->TraceHydrogen(name(), graph_);
11364 } 11457 }
11365 11458
11366 #ifdef DEBUG 11459 #ifdef DEBUG
11367 graph_->Verify(false); // No full verify. 11460 graph_->Verify(false); // No full verify.
11368 #endif 11461 #endif
11369 } 11462 }
11370 11463
11371 } } // namespace v8::internal 11464 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/ia32/code-stubs-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698