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

Unified 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, 11 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/hydrogen.h ('k') | src/ia32/code-stubs-ia32.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/hydrogen.cc
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index 78a703b5652d8282edc0fc7a77e6e791cc9f2541..98191ce650daab15f282f0ab7a496e084c606d34 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -7952,6 +7952,118 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
}
+bool HOptimizedGraphBuilder::TryInlineApiFunctionCall(Call* expr,
+ HValue* receiver,
+ bool drop_extra) {
+ return TryInlineApiCall(
+ expr, receiver, Handle<Map>::null(), drop_extra, true);
+}
+
+
+bool HOptimizedGraphBuilder::TryInlineApiMethodCall(Call* expr,
+ HValue* receiver,
+ Handle<Map> receiver_map) {
+ return TryInlineApiCall(expr, receiver, receiver_map, false, false);
+}
+
+bool HOptimizedGraphBuilder::TryInlineApiCall(Call* expr,
+ HValue* receiver,
+ Handle<Map> receiver_map,
+ bool drop_extra,
+ bool is_function_call) {
+ if (!expr->IsMonomorphic() || expr->check_type() != RECEIVER_MAP_CHECK) {
+ return false;
+ }
+ CallOptimization optimization(expr->target());
+ if (!optimization.is_simple_api_call()) return false;
+ Handle<Map> holder_map;
+ if (is_function_call) {
+ // Cannot embed a direct reference to the global proxy map
+ // as it maybe dropped on deserialization.
+ CHECK(!Serializer::enabled());
+ receiver_map = Handle<Map>(
+ expr->target()->context()->global_object()->global_receiver()->map());
+ }
+ CallOptimization::HolderLookup holder_lookup =
+ CallOptimization::kHolderNotFound;
+ Handle<JSObject> api_holder = optimization.LookupHolderOfExpectedType(
+ receiver_map, &holder_lookup);
+ if (holder_lookup == CallOptimization::kHolderNotFound) return false;
+
+ if (FLAG_trace_inlining) {
+ PrintF("Inlining api function ");
+ expr->target()->ShortPrint();
+ PrintF("\n");
+ }
+
+ // Need to ensure the chain between receiver and api_holder is intact
+ AddCheckMap(receiver, receiver_map);
+ if (holder_lookup == CallOptimization::kHolderFound) {
+ AddCheckPrototypeMaps(api_holder, receiver_map);
+ } else {
+ ASSERT_EQ(holder_lookup, CallOptimization::kHolderIsReceiver);
+ }
+
+ // TODO(verwaest): remove.
+ if (!is_function_call) {
+ AddCheckConstantFunction(expr->holder(), receiver, receiver_map);
+ }
+
+ HValue* holder = NULL;
+ switch (holder_lookup) {
+ case CallOptimization::kHolderFound:
+ holder = Add<HConstant>(api_holder);
+ break;
+ case CallOptimization::kHolderIsReceiver:
+ holder = environment()->ExpressionStackAt(expr->arguments()->length());
+ break;
+ case CallOptimization::kHolderNotFound:
+ UNREACHABLE();
+ break;
+ }
+ Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
+ Handle<Object> call_data_obj(api_call_info->data(), isolate());
+ bool call_data_is_undefined = call_data_obj->IsUndefined();
+ HValue* call_data = Add<HConstant>(call_data_obj);
+ ApiFunction fun(v8::ToCData<Address>(api_call_info->callback()));
+ ExternalReference ref = ExternalReference(&fun,
+ ExternalReference::DIRECT_API_CALL,
+ isolate());
+ HValue* api_function_address = Add<HConstant>(ExternalReference(ref));
+
+ HValue* op_vals[] = {
+ // callee
+ Add<HConstant>(expr->target()),
+ call_data,
+ holder,
+ api_function_address,
+ context()
+ };
+
+ const int argc = expr->arguments()->length();
+ // Includes receiver.
+ PushArgumentsFromEnvironment(argc + 1);
+
+ CallInterfaceDescriptor* descriptor =
+ isolate()->call_descriptor(Isolate::ApiFunctionCall);
+
+ CallApiFunctionStub stub(true, call_data_is_undefined, argc);
+ Handle<Code> code = stub.GetCode(isolate());
+ HConstant* code_value = Add<HConstant>(code);
+
+ ASSERT((sizeof(op_vals) / kPointerSize) ==
+ descriptor->environment_length());
+
+ HInstruction* call = New<HCallWithDescriptor>(
+ code_value, argc + 1, descriptor,
+ Vector<HValue*>(op_vals, descriptor->environment_length()));
+
+ if (drop_extra) Drop(1); // Drop function.
+ ast_context()->ReturnInstruction(call, expr->id());
+ return true;
+}
+
+
bool HOptimizedGraphBuilder::TryCallApply(Call* expr) {
Expression* callee = expr->expression();
Property* prop = callee->AsProperty();
@@ -8040,16 +8152,12 @@ HValue* HOptimizedGraphBuilder::ImplicitReceiverFor(HValue* function,
Handle<JSFunction> target) {
SharedFunctionInfo* shared = target->shared();
if (shared->is_classic_mode() && !shared->native()) {
- HValue* context = Add<HLoadNamedField>(
- function, static_cast<HValue*>(NULL),
- HObjectAccess::ForJSObjectOffset(JSFunction::kContextOffset));
- HValue* global_object = Add<HLoadNamedField>(
- context, static_cast<HValue*>(NULL),
- HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
- return Add<HLoadNamedField>(
- global_object, static_cast<HValue*>(NULL),
- HObjectAccess::ForJSObjectOffset(
- GlobalObject::kGlobalReceiverOffset));
+ // Cannot embed a direct reference to the global proxy
+ // as is it dropped on deserialization.
+ CHECK(!Serializer::enabled());
+ Handle<JSObject> global_receiver(
+ target->context()->global_object()->global_receiver());
+ return Add<HConstant>(global_receiver);
}
return graph()->GetConstantUndefined();
}
@@ -8122,12 +8230,9 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) {
}
return;
}
+ if (TryInlineApiMethodCall(expr, receiver, map)) return;
- if (CallStubCompiler::HasCustomCallGenerator(expr->target()) ||
- expr->check_type() != RECEIVER_MAP_CHECK) {
- // When the target has a custom call IC generator, use the IC,
- // because it is likely to generate better code. Also use the IC
- // when a primitive receiver check is required.
+ if (expr->check_type() != RECEIVER_MAP_CHECK) {
call = NewCallNamed(name, argument_count);
PushArgumentsFromEnvironment(argument_count);
} else {
@@ -8193,28 +8298,15 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) {
}
return;
}
+ if (TryInlineApiFunctionCall(expr, receiver, false)) return;
if (TryInlineCall(expr)) return;
if (expr->target().is_identical_to(current_info()->closure())) {
graph()->MarkRecursive();
}
- if (CallStubCompiler::HasCustomCallGenerator(expr->target())) {
- // We're about to install a contextual IC, which expects the global
- // object as receiver rather than the global proxy.
- HValue* global_object = Add<HLoadNamedField>(
- context(), static_cast<HValue*>(NULL),
- HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
- const int receiver_index = argument_count - 1;
- environment()->SetExpressionStackAt(receiver_index, global_object);
- // When the target has a custom call IC generator, use the IC,
- // because it is likely to generate better code.
- call = NewCallNamed(var->name(), argument_count);
- PushArgumentsFromEnvironment(argument_count);
- } else {
- call = BuildCallConstantFunction(expr->target(), argument_count);
- PushArgumentsFromEnvironment(argument_count);
- }
+ call = BuildCallConstantFunction(expr->target(), argument_count);
+ PushArgumentsFromEnvironment(argument_count);
} else {
HValue* receiver = Add<HLoadNamedField>(
context(), static_cast<HValue*>(NULL),
@@ -8247,6 +8339,7 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) {
}
return;
}
+ if (TryInlineApiFunctionCall(expr, receiver, true)) return;
if (TryInlineCall(expr, true)) { // Drop function from environment.
return;
« 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