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) { ...@@ -766,10 +766,20 @@ void Genesis::CreateStrictModeFunctionMaps(Handle<JSFunction> empty) {
strict_function_map_writable_prototype_ = strict_function_map_writable_prototype_ =
CreateStrictFunctionMap(FUNCTION_WITH_WRITEABLE_PROTOTYPE, empty); CreateStrictFunctionMap(FUNCTION_WITH_WRITEABLE_PROTOTYPE, empty);
// Special map for bound functions. // Special map for non-constructor bound functions.
Handle<Map> bound_function_map = // TODO(bmeurer): Bound functions should not be represented as JSFunctions.
Handle<Map> bound_function_without_constructor_map =
CreateStrictFunctionMap(BOUND_FUNCTION, empty); 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 { ...@@ -172,7 +172,10 @@ enum BindingFlags {
V(BOOL32X4_FUNCTION_INDEX, JSFunction, bool32x4_function) \ V(BOOL32X4_FUNCTION_INDEX, JSFunction, bool32x4_function) \
V(BOOL8X16_FUNCTION_INDEX, JSFunction, bool8x16_function) \ V(BOOL8X16_FUNCTION_INDEX, JSFunction, bool8x16_function) \
V(BOOLEAN_FUNCTION_INDEX, JSFunction, boolean_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, \ V(CALL_AS_CONSTRUCTOR_DELEGATE_INDEX, JSFunction, \
call_as_constructor_delegate) \ call_as_constructor_delegate) \
V(CALL_AS_FUNCTION_DELEGATE_INDEX, JSFunction, call_as_function_delegate) \ V(CALL_AS_FUNCTION_DELEGATE_INDEX, JSFunction, call_as_function_delegate) \
......
...@@ -409,19 +409,18 @@ RUNTIME_FUNCTION(Runtime_FunctionBindArguments) { ...@@ -409,19 +409,18 @@ RUNTIME_FUNCTION(Runtime_FunctionBindArguments) {
RUNTIME_ASSERT(bound_function->RemovePrototype()); RUNTIME_ASSERT(bound_function->RemovePrototype());
// The new function should have the same [[Prototype]] as the bindee. // The new function should have the same [[Prototype]] as the bindee.
Handle<Map> bound_function_map( Handle<Map> bound_function_map =
isolate->native_context()->bound_function_map()); bindee->IsConstructor()
? isolate->bound_function_with_constructor_map()
: isolate->bound_function_without_constructor_map();
PrototypeIterator iter(isolate, bindee); PrototypeIterator iter(isolate, bindee);
Handle<Object> proto = PrototypeIterator::GetCurrent(iter); Handle<Object> proto = PrototypeIterator::GetCurrent(iter);
if (bound_function_map->prototype() != *proto) { if (bound_function_map->prototype() != *proto) {
bound_function_map = Map::TransitionToPrototype(bound_function_map, proto, bound_function_map = Map::TransitionToPrototype(bound_function_map, proto,
REGULAR_PROTOTYPE); 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); JSObject::MigrateToMap(bound_function, bound_function_map);
DCHECK_EQ(bindee->IsConstructor(), bound_function->IsConstructor());
Handle<String> length_string = isolate->factory()->length_string(); Handle<String> length_string = isolate->factory()->length_string();
// These attributes must be kept in sync with how the bootstrapper // 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