Commit 6f81ee6a authored by bmeurer's avatar bmeurer Committed by Commit bot

[runtime] Share constructor/non-constructor bound function maps.

Properly share both the constructor and the non-constructor maps
for bound functions. Previously we had only the non-constructor
map shared on the native context, and we had to create a new map
for every bound function whose [[BoundTargetFunction]] is a
constructor (in the ES6 sense).

This should repair the most recent regression on Speedometer.

CQ_INCLUDE_TRYBOTS=tryserver.v8:v8_linux_nosnap_dbg
R=jarin@chromium.org
BUG=chromium:536114,chromium:535408,v8:4430
LOG=n

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

Cr-Commit-Position: refs/heads/master@{#31086}
parent faa64095
......@@ -766,10 +766,20 @@ void Genesis::CreateStrictModeFunctionMaps(Handle<JSFunction> empty) {
strict_function_map_writable_prototype_ =
CreateStrictFunctionMap(FUNCTION_WITH_WRITEABLE_PROTOTYPE, empty);
// Special map for bound functions.
Handle<Map> bound_function_map =
// Special map for non-constructor bound functions.
// TODO(bmeurer): Bound functions should not be represented as JSFunctions.
Handle<Map> bound_function_without_constructor_map =
CreateStrictFunctionMap(BOUND_FUNCTION, empty);
native_context()->set_bound_function_map(*bound_function_map);
native_context()->set_bound_function_without_constructor_map(
*bound_function_without_constructor_map);
// Special map for constructor bound functions.
// TODO(bmeurer): Bound functions should not be represented as JSFunctions.
Handle<Map> bound_function_with_constructor_map =
Map::Copy(bound_function_without_constructor_map, "IsConstructor");
bound_function_with_constructor_map->set_is_constructor(true);
native_context()->set_bound_function_with_constructor_map(
*bound_function_with_constructor_map);
}
......
......@@ -172,7 +172,10 @@ enum BindingFlags {
V(BOOL32X4_FUNCTION_INDEX, JSFunction, bool32x4_function) \
V(BOOL8X16_FUNCTION_INDEX, JSFunction, bool8x16_function) \
V(BOOLEAN_FUNCTION_INDEX, JSFunction, boolean_function) \
V(BOUND_FUNCTION_MAP_INDEX, Map, bound_function_map) \
V(BOUND_FUNCTION_WITH_CONSTRUCTOR_MAP_INDEX, Map, \
bound_function_with_constructor_map) \
V(BOUND_FUNCTION_WITHOUT_CONSTRUCTOR_MAP_INDEX, Map, \
bound_function_without_constructor_map) \
V(CALL_AS_CONSTRUCTOR_DELEGATE_INDEX, JSFunction, \
call_as_constructor_delegate) \
V(CALL_AS_FUNCTION_DELEGATE_INDEX, JSFunction, call_as_function_delegate) \
......
......@@ -409,19 +409,18 @@ RUNTIME_FUNCTION(Runtime_FunctionBindArguments) {
RUNTIME_ASSERT(bound_function->RemovePrototype());
// The new function should have the same [[Prototype]] as the bindee.
Handle<Map> bound_function_map(
isolate->native_context()->bound_function_map());
Handle<Map> bound_function_map =
bindee->IsConstructor()
? isolate->bound_function_with_constructor_map()
: isolate->bound_function_without_constructor_map();
PrototypeIterator iter(isolate, bindee);
Handle<Object> proto = PrototypeIterator::GetCurrent(iter);
if (bound_function_map->prototype() != *proto) {
bound_function_map = Map::TransitionToPrototype(bound_function_map, proto,
REGULAR_PROTOTYPE);
}
if (bound_function_map->is_constructor() != bindee->IsConstructor()) {
bound_function_map = Map::Copy(bound_function_map, "IsConstructor");
bound_function_map->set_is_constructor(bindee->IsConstructor());
}
JSObject::MigrateToMap(bound_function, bound_function_map);
DCHECK_EQ(bindee->IsConstructor(), bound_function->IsConstructor());
Handle<String> length_string = isolate->factory()->length_string();
// These attributes must be kept in sync with how the bootstrapper
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment