inline api setters in crankshaft

R=verwaest@chromium.org

BUG=

Review URL: https://codereview.chromium.org/155913002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19129 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
dcarney@chromium.org 2014-02-06 07:31:08 +00:00
parent f0bf110448
commit 6df537d631
3 changed files with 62 additions and 15 deletions

View File

@ -5585,7 +5585,8 @@ HInstruction* HOptimizedGraphBuilder::BuildMonomorphicAccess(
} else if (FLAG_inline_accessors && can_inline_accessor) { } else if (FLAG_inline_accessors && can_inline_accessor) {
bool success = info->IsLoad() bool success = info->IsLoad()
? TryInlineGetter(info->accessor(), info->map(), ast_id, return_id) ? TryInlineGetter(info->accessor(), info->map(), ast_id, return_id)
: TryInlineSetter(info->accessor(), ast_id, return_id, value); : TryInlineSetter(
info->accessor(), info->map(), ast_id, return_id, value);
if (success) return NULL; if (success) return NULL;
} }
@ -7420,9 +7421,11 @@ bool HOptimizedGraphBuilder::TryInlineGetter(Handle<JSFunction> getter,
bool HOptimizedGraphBuilder::TryInlineSetter(Handle<JSFunction> setter, bool HOptimizedGraphBuilder::TryInlineSetter(Handle<JSFunction> setter,
Handle<Map> receiver_map,
BailoutId id, BailoutId id,
BailoutId assignment_id, BailoutId assignment_id,
HValue* implicit_return_value) { HValue* implicit_return_value) {
if (TryInlineApiSetter(setter, receiver_map, id)) return true;
return TryInline(setter, return TryInline(setter,
1, 1,
implicit_return_value, implicit_return_value,
@ -7733,6 +7736,20 @@ bool HOptimizedGraphBuilder::TryInlineApiGetter(Handle<JSFunction> function,
} }
bool HOptimizedGraphBuilder::TryInlineApiSetter(Handle<JSFunction> function,
Handle<Map> receiver_map,
BailoutId ast_id) {
SmallMapList receiver_maps(1, zone());
receiver_maps.Add(receiver_map, zone());
return TryInlineApiCall(function,
NULL, // Receiver is on expression stack.
&receiver_maps,
1,
ast_id,
kCallApiSetter);
}
bool HOptimizedGraphBuilder::TryInlineApiCall(Handle<JSFunction> function, bool HOptimizedGraphBuilder::TryInlineApiCall(Handle<JSFunction> function,
HValue* receiver, HValue* receiver,
SmallMapList* receiver_maps, SmallMapList* receiver_maps,
@ -7788,6 +7805,18 @@ bool HOptimizedGraphBuilder::TryInlineApiCall(Handle<JSFunction> function,
receiver = Pop(); receiver = Pop();
Add<HPushArgument>(receiver); Add<HPushArgument>(receiver);
break; break;
case kCallApiSetter:
{
// Receiver and prototype chain cannot have changed.
ASSERT_EQ(1, argc);
ASSERT_EQ(NULL, receiver);
// Receiver and value are on expression stack.
HValue* value = Pop();
receiver = Pop();
Add<HPushArgument>(receiver);
Add<HPushArgument>(value);
break;
}
} }
HValue* holder = NULL; HValue* holder = NULL;

View File

@ -2222,6 +2222,7 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
BailoutId ast_id, BailoutId ast_id,
BailoutId return_id); BailoutId return_id);
bool TryInlineSetter(Handle<JSFunction> setter, bool TryInlineSetter(Handle<JSFunction> setter,
Handle<Map> receiver_map,
BailoutId id, BailoutId id,
BailoutId assignment_id, BailoutId assignment_id,
HValue* implicit_return_value); HValue* implicit_return_value);
@ -2235,7 +2236,8 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
enum ApiCallType { enum ApiCallType {
kCallApiFunction, kCallApiFunction,
kCallApiMethod, kCallApiMethod,
kCallApiGetter kCallApiGetter,
kCallApiSetter
}; };
bool TryInlineApiMethodCall(Call* expr, bool TryInlineApiMethodCall(Call* expr,
HValue* receiver, HValue* receiver,
@ -2244,6 +2246,9 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
bool TryInlineApiGetter(Handle<JSFunction> function, bool TryInlineApiGetter(Handle<JSFunction> function,
Handle<Map> receiver_map, Handle<Map> receiver_map,
BailoutId ast_id); BailoutId ast_id);
bool TryInlineApiSetter(Handle<JSFunction> function,
Handle<Map> receiver_map,
BailoutId ast_id);
bool TryInlineApiCall(Handle<JSFunction> function, bool TryInlineApiCall(Handle<JSFunction> function,
HValue* receiver, HValue* receiver,
SmallMapList* receiver_maps, SmallMapList* receiver_maps,

View File

@ -21912,6 +21912,9 @@ class ApiCallOptimizationChecker {
CHECK(callee == info.Callee()); CHECK(callee == info.Callee());
CHECK(data == info.Data()); CHECK(data == info.Data());
CHECK(receiver == info.This()); CHECK(receiver == info.This());
if (info.Length() == 1) {
CHECK_EQ(v8_num(1), info[0]);
}
CHECK(holder == info.Holder()); CHECK(holder == info.Holder());
count++; count++;
} }
@ -21974,9 +21977,9 @@ class ApiCallOptimizationChecker {
Local<Object> global_holder = Local<Object>::Cast( Local<Object> global_holder = Local<Object>::Cast(
inner_global->GetPrototype()); inner_global->GetPrototype());
global_holder->Set(v8_str("g_f"), function); global_holder->Set(v8_str("g_f"), function);
SetAccessorProperty(global_holder, v8_str("g_p1"), function); SetAccessorProperty(global_holder, v8_str("g_acc"), function, function);
function_holder->Set(v8_str("f"), function); function_holder->Set(v8_str("f"), function);
SetAccessorProperty(function_holder, v8_str("p1"), function); SetAccessorProperty(function_holder, v8_str("acc"), function, function);
// Initialize expected values. // Initialize expected values.
callee = function; callee = function;
count = 0; count = 0;
@ -22007,14 +22010,16 @@ class ApiCallOptimizationChecker {
i::OS::SNPrintF( i::OS::SNPrintF(
wrap_function, wrap_function,
"function wrap_f_%d() { var f = g_f; return f(); }\n" "function wrap_f_%d() { var f = g_f; return f(); }\n"
"function wrap_p1_%d() { return this.g_p1; }\n", "function wrap_get_%d() { return this.g_acc; }\n"
key, key); "function wrap_set_%d() { this.g_acc = 1; }\n",
key, key, key);
} else { } else {
i::OS::SNPrintF( i::OS::SNPrintF(
wrap_function, wrap_function,
"function wrap_f_%d() { return receiver_subclass.f(); }\n" "function wrap_f_%d() { return receiver_subclass.f(); }\n"
"function wrap_p1_%d() { return receiver_subclass.p1; }\n", "function wrap_get_%d() { return receiver_subclass.acc; }\n"
key, key); "function wrap_set_%d() { receiver_subclass.acc = 1; }\n",
key, key, key);
} }
// build source string // build source string
i::ScopedVector<char> source(500); i::ScopedVector<char> source(500);
@ -22022,20 +22027,28 @@ class ApiCallOptimizationChecker {
source, source,
"%s\n" // wrap functions "%s\n" // wrap functions
"function wrap_f() { wrap_f_%d(); }\n" "function wrap_f() { wrap_f_%d(); }\n"
"function wrap_p1() { wrap_p1_%d(); }\n" "function wrap_get() { wrap_get_%d(); }\n"
"function wrap_set() { wrap_set_%d(); }\n"
"\n"
"wrap_f();\n" "wrap_f();\n"
"wrap_f();\n" "wrap_f();\n"
"%%OptimizeFunctionOnNextCall(wrap_f_%d);\n" "%%OptimizeFunctionOnNextCall(wrap_f_%d);\n"
"wrap_f();\n" "wrap_f();\n"
"wrap_p1();\n" "\n"
"wrap_p1();\n" "wrap_get();\n"
"%%OptimizeFunctionOnNextCall(wrap_p1_%d);\n" "wrap_get();\n"
"wrap_p1();\n", "%%OptimizeFunctionOnNextCall(wrap_get_%d);\n"
wrap_function.start(), key, key, key, key); "wrap_get();\n"
"\n"
"wrap_set();\n"
"wrap_set();\n"
"%%OptimizeFunctionOnNextCall(wrap_set_%d);\n"
"wrap_set();\n",
wrap_function.start(), key, key, key, key, key, key);
v8::TryCatch try_catch; v8::TryCatch try_catch;
CompileRun(source.start()); CompileRun(source.start());
ASSERT(!try_catch.HasCaught()); ASSERT(!try_catch.HasCaught());
CHECK_EQ(6, count); CHECK_EQ(9, count);
} }
}; };