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:
parent
f0bf110448
commit
6df537d631
@ -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;
|
||||||
|
@ -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,
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user