[turbofan] Add fast path for cached property names.

Port the fast path for accessor inlining to cached property names from
Crankshaft to TurboFan. This constant-folds accesses to document in a
script.

R=jochen@chromium.org
BUG=v8:5548

Review-Url: https://codereview.chromium.org/2646363003
Cr-Commit-Position: refs/heads/master@{#42600}
This commit is contained in:
bmeurer 2017-01-23 04:13:51 -08:00 committed by Commit bot
parent 94266b7d86
commit e347408d4d
4 changed files with 96 additions and 3 deletions

View File

@ -373,6 +373,17 @@ bool AccessInfoFactory::ComputePropertyAccessInfo(
}
if (V8_UNLIKELY(FLAG_runtime_stats)) return false;
}
if (access_mode == AccessMode::kLoad) {
Handle<Name> cached_property_name;
if (FunctionTemplateInfo::TryGetCachedPropertyName(isolate(),
accessor)
.ToHandle(&cached_property_name)) {
if (ComputePropertyAccessInfo(map, cached_property_name,
access_mode, access_info)) {
return true;
}
}
}
*access_info = PropertyAccessInfo::AccessorConstant(
MapList{receiver_map}, accessor, holder);
return true;

View File

@ -62,6 +62,7 @@ FieldAccess ForPropertyCellValue(MachineRepresentation representation,
kTaggedBase, PropertyCell::kValueOffset, name, map, type, r, kind};
return access;
}
} // namespace
Reduction JSGlobalObjectSpecialization::ReduceJSLoadGlobal(Node* node) {
@ -85,6 +86,7 @@ Reduction JSGlobalObjectSpecialization::ReduceJSLoadGlobal(Node* node) {
// Lookup on the global object instead. We only deal with own data
// properties of the global object here (represented as PropertyCell).
LookupIterator it(global_object(), name, LookupIterator::OWN);
it.TryLookupCachedProperty();
if (it.state() != LookupIterator::DATA) return NoChange();
if (!it.GetHolder<JSObject>()->IsJSGlobalObject()) return NoChange();
Handle<PropertyCell> property_cell = it.GetPropertyCell();

View File

@ -349,9 +349,6 @@
['variant == turbofan or variant == ignition_turbofan', {
# BUG(4751). Flaky with Ignition.
'test-cpu-profiler/JsNativeJsSample': [SKIP],
# TODO(vogelheim,5548): Turbofan does support cached accessors.
'test-api-accessors/CachedAccessorCrankshaft': [FAIL],
}], # variant == turbofan or variant == ignition_turbofan
##############################################################################

View File

@ -249,6 +249,89 @@ TEST(CachedAccessorCrankshaft) {
ExpectInt32("g()", 789);
}
TEST(CachedAccessorOnGlobalObject) {
i::FLAG_allow_natives_syntax = true;
LocalContext env;
v8::Isolate* isolate = env->GetIsolate();
v8::HandleScope scope(isolate);
v8::Local<v8::FunctionTemplate> templ =
v8::FunctionTemplate::New(CcTest::isolate());
v8::Local<v8::ObjectTemplate> object_template = templ->InstanceTemplate();
v8::Local<v8::Private> priv =
v8::Private::ForApi(isolate, v8_str("Foo#draft"));
object_template->SetAccessorProperty(
v8_str("draft"),
v8::FunctionTemplate::NewWithCache(isolate, UnreachableCallback, priv,
v8::Local<v8::Value>()));
v8::Local<v8::Context> ctx =
v8::Context::New(CcTest::isolate(), nullptr, object_template);
v8::Local<v8::Object> obj = ctx->Global();
// Install the private property on the instance.
CHECK(obj->SetPrivate(isolate->GetCurrentContext(), priv,
v8::Undefined(isolate))
.FromJust());
{
v8::Context::Scope context_scope(ctx);
// Access surrogate accessor.
ExpectUndefined("draft");
// Set hidden property.
CHECK(obj->SetPrivate(env.local(), priv, v8::Integer::New(isolate, 123))
.FromJust());
// Test ICs.
CompileRun(
"function f() {"
" var x;"
" for (var i = 0; i < 100; i++) {"
" x = draft;"
" }"
" return x;"
"}");
ExpectInt32("f()", 123);
// Reset hidden property.
CHECK(obj->SetPrivate(env.local(), priv, v8::Integer::New(isolate, 456))
.FromJust());
// Test Crankshaft.
CompileRun("%OptimizeFunctionOnNextCall(f);");
ExpectInt32("f()", 456);
CHECK(obj->SetPrivate(env.local(), priv, v8::Integer::New(isolate, 456))
.FromJust());
// Test non-global ICs.
CompileRun(
"var x = this;"
"function g() {"
" var r = 0;"
" for (var i = 0; i < 100; i++) {"
" r = x.draft;"
" }"
" return r;"
"}");
ExpectInt32("g()", 456);
// Reset hidden property.
CHECK(obj->SetPrivate(env.local(), priv, v8::Integer::New(isolate, 789))
.FromJust());
// Test non-global access in Crankshaft.
CompileRun("%OptimizeFunctionOnNextCall(g);");
ExpectInt32("g()", 789);
}
}
namespace {
static void Setter(v8::Local<v8::String> name, v8::Local<v8::Value> value,