Index: src/bootstrapper.cc |
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc |
index 87e1d2012f0881b16da0af1df7f76eebd494f8f2..4d7ce52a127d647a04d004326cf8e296eb04b4ce 100644 |
--- a/src/bootstrapper.cc |
+++ b/src/bootstrapper.cc |
@@ -262,24 +262,32 @@ class Genesis BASE_EMBEDDED { |
void TransferNamedProperties(Handle<JSObject> from, Handle<JSObject> to); |
void TransferIndexedProperties(Handle<JSObject> from, Handle<JSObject> to); |
- enum PrototypePropertyMode { |
- DONT_ADD_PROTOTYPE, |
- ADD_READONLY_PROTOTYPE, |
- ADD_WRITEABLE_PROTOTYPE |
+ enum FunctionMode { |
+ // With prototype. |
+ FUNCTION_WITH_WRITEABLE_PROTOTYPE, |
+ FUNCTION_WITH_READONLY_PROTOTYPE, |
+ // Without prototype. |
+ FUNCTION_WITHOUT_PROTOTYPE, |
+ BOUND_FUNCTION |
}; |
- Handle<Map> CreateFunctionMap(PrototypePropertyMode prototype_mode); |
+ static bool IsFunctionModeWithPrototype(FunctionMode function_mode) { |
+ return (function_mode == FUNCTION_WITH_WRITEABLE_PROTOTYPE || |
+ function_mode == FUNCTION_WITH_READONLY_PROTOTYPE); |
+ } |
+ |
+ Handle<Map> CreateFunctionMap(FunctionMode function_mode); |
void SetFunctionInstanceDescriptor(Handle<Map> map, |
- PrototypePropertyMode prototypeMode); |
+ FunctionMode function_mode); |
void MakeFunctionInstancePrototypeWritable(); |
Handle<Map> CreateStrictFunctionMap( |
- PrototypePropertyMode prototype_mode, |
+ FunctionMode function_mode, |
Handle<JSFunction> empty_function); |
void SetStrictFunctionInstanceDescriptor(Handle<Map> map, |
- PrototypePropertyMode propertyMode); |
+ FunctionMode function_mode); |
static bool CompileBuiltin(Isolate* isolate, int index); |
static bool CompileExperimentalBuiltin(Isolate* isolate, int index); |
@@ -382,8 +390,8 @@ static Handle<JSFunction> InstallFunction(Handle<JSObject> target, |
void Genesis::SetFunctionInstanceDescriptor( |
- Handle<Map> map, PrototypePropertyMode prototypeMode) { |
- int size = (prototypeMode == DONT_ADD_PROTOTYPE) ? 4 : 5; |
+ Handle<Map> map, FunctionMode function_mode) { |
+ int size = IsFunctionModeWithPrototype(function_mode) ? 5 : 4; |
Map::EnsureDescriptorSlack(map, size); |
PropertyAttributes attribs = static_cast<PropertyAttributes>( |
@@ -417,8 +425,8 @@ void Genesis::SetFunctionInstanceDescriptor( |
caller, attribs); |
map->AppendDescriptor(&d); |
} |
- if (prototypeMode != DONT_ADD_PROTOTYPE) { |
- if (prototypeMode == ADD_WRITEABLE_PROTOTYPE) { |
+ if (IsFunctionModeWithPrototype(function_mode)) { |
+ if (function_mode == FUNCTION_WITH_WRITEABLE_PROTOTYPE) { |
attribs = static_cast<PropertyAttributes>(attribs & ~READ_ONLY); |
} |
Handle<AccessorInfo> prototype = |
@@ -430,10 +438,10 @@ void Genesis::SetFunctionInstanceDescriptor( |
} |
-Handle<Map> Genesis::CreateFunctionMap(PrototypePropertyMode prototype_mode) { |
+Handle<Map> Genesis::CreateFunctionMap(FunctionMode function_mode) { |
Handle<Map> map = factory()->NewMap(JS_FUNCTION_TYPE, JSFunction::kSize); |
- SetFunctionInstanceDescriptor(map, prototype_mode); |
- map->set_function_with_prototype(prototype_mode != DONT_ADD_PROTOTYPE); |
+ SetFunctionInstanceDescriptor(map, function_mode); |
+ map->set_function_with_prototype(IsFunctionModeWithPrototype(function_mode)); |
return map; |
} |
@@ -445,14 +453,15 @@ Handle<JSFunction> Genesis::CreateEmptyFunction(Isolate* isolate) { |
// Functions with this map will not have a 'prototype' property, and |
// can not be used as constructors. |
Handle<Map> function_without_prototype_map = |
- CreateFunctionMap(DONT_ADD_PROTOTYPE); |
+ CreateFunctionMap(FUNCTION_WITHOUT_PROTOTYPE); |
native_context()->set_sloppy_function_without_prototype_map( |
*function_without_prototype_map); |
// Allocate the function map. This map is temporary, used only for processing |
// of builtins. |
// Later the map is replaced with writable prototype map, allocated below. |
- Handle<Map> function_map = CreateFunctionMap(ADD_READONLY_PROTOTYPE); |
+ Handle<Map> function_map = |
+ CreateFunctionMap(FUNCTION_WITH_READONLY_PROTOTYPE); |
native_context()->set_sloppy_function_map(*function_map); |
native_context()->set_sloppy_function_with_readonly_prototype_map( |
*function_map); |
@@ -460,7 +469,7 @@ Handle<JSFunction> Genesis::CreateEmptyFunction(Isolate* isolate) { |
// The final map for functions. Writeable prototype. |
// This map is installed in MakeFunctionInstancePrototypeWritable. |
sloppy_function_map_writable_prototype_ = |
- CreateFunctionMap(ADD_WRITEABLE_PROTOTYPE); |
+ CreateFunctionMap(FUNCTION_WITH_WRITEABLE_PROTOTYPE); |
Factory* factory = isolate->factory(); |
@@ -514,7 +523,8 @@ Handle<JSFunction> Genesis::CreateEmptyFunction(Isolate* isolate) { |
sloppy_function_map_writable_prototype_->set_prototype(*empty_function); |
// Allocate the function map first and then patch the prototype later |
- Handle<Map> empty_function_map = CreateFunctionMap(DONT_ADD_PROTOTYPE); |
+ Handle<Map> empty_function_map = |
+ CreateFunctionMap(FUNCTION_WITHOUT_PROTOTYPE); |
empty_function_map->set_prototype( |
native_context()->object_function()->prototype()); |
empty_function->set_map(*empty_function_map); |
@@ -523,8 +533,8 @@ Handle<JSFunction> Genesis::CreateEmptyFunction(Isolate* isolate) { |
void Genesis::SetStrictFunctionInstanceDescriptor( |
- Handle<Map> map, PrototypePropertyMode prototypeMode) { |
- int size = (prototypeMode == DONT_ADD_PROTOTYPE) ? 4 : 5; |
+ Handle<Map> map, FunctionMode function_mode) { |
+ int size = IsFunctionModeWithPrototype(function_mode) ? 5 : 4; |
Map::EnsureDescriptorSlack(map, size); |
Handle<AccessorPair> arguments(factory()->NewAccessorPair()); |
@@ -534,9 +544,17 @@ void Genesis::SetStrictFunctionInstanceDescriptor( |
PropertyAttributes ro_attribs = |
static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY); |
- Handle<AccessorInfo> length = |
- Accessors::FunctionLengthInfo(isolate(), ro_attribs); |
- { // Add length. |
+ // Add length. |
+ if (function_mode == BOUND_FUNCTION) { |
+ Handle<String> length_string = isolate()->factory()->length_string(); |
+ FieldDescriptor d(length_string, 0, ro_attribs, Representation::Tagged()); |
+ map->AppendDescriptor(&d); |
+ } else { |
+ ASSERT(function_mode == FUNCTION_WITH_WRITEABLE_PROTOTYPE || |
+ function_mode == FUNCTION_WITH_READONLY_PROTOTYPE || |
+ function_mode == FUNCTION_WITHOUT_PROTOTYPE); |
+ Handle<AccessorInfo> length = |
+ Accessors::FunctionLengthInfo(isolate(), ro_attribs); |
CallbacksDescriptor d(Handle<Name>(Name::cast(length->name())), |
length, ro_attribs); |
map->AppendDescriptor(&d); |
@@ -557,10 +575,11 @@ void Genesis::SetStrictFunctionInstanceDescriptor( |
CallbacksDescriptor d(factory()->caller_string(), caller, rw_attribs); |
map->AppendDescriptor(&d); |
} |
- if (prototypeMode != DONT_ADD_PROTOTYPE) { |
+ if (IsFunctionModeWithPrototype(function_mode)) { |
// Add prototype. |
PropertyAttributes attribs = |
- prototypeMode == ADD_WRITEABLE_PROTOTYPE ? rw_attribs : ro_attribs; |
+ function_mode == FUNCTION_WITH_WRITEABLE_PROTOTYPE ? rw_attribs |
+ : ro_attribs; |
Handle<AccessorInfo> prototype = |
Accessors::FunctionPrototypeInfo(isolate(), attribs); |
CallbacksDescriptor d(Handle<Name>(Name::cast(prototype->name())), |
@@ -605,11 +624,11 @@ Handle<JSFunction> Genesis::GetGeneratorPoisonFunction() { |
Handle<Map> Genesis::CreateStrictFunctionMap( |
- PrototypePropertyMode prototype_mode, |
+ FunctionMode function_mode, |
Handle<JSFunction> empty_function) { |
Handle<Map> map = factory()->NewMap(JS_FUNCTION_TYPE, JSFunction::kSize); |
- SetStrictFunctionInstanceDescriptor(map, prototype_mode); |
- map->set_function_with_prototype(prototype_mode != DONT_ADD_PROTOTYPE); |
+ SetStrictFunctionInstanceDescriptor(map, function_mode); |
+ map->set_function_with_prototype(IsFunctionModeWithPrototype(function_mode)); |
map->set_prototype(*empty_function); |
return map; |
} |
@@ -618,7 +637,7 @@ Handle<Map> Genesis::CreateStrictFunctionMap( |
void Genesis::CreateStrictModeFunctionMaps(Handle<JSFunction> empty) { |
// Allocate map for the prototype-less strict mode instances. |
Handle<Map> strict_function_without_prototype_map = |
- CreateStrictFunctionMap(DONT_ADD_PROTOTYPE, empty); |
+ CreateStrictFunctionMap(FUNCTION_WITHOUT_PROTOTYPE, empty); |
native_context()->set_strict_function_without_prototype_map( |
*strict_function_without_prototype_map); |
@@ -626,18 +645,23 @@ void Genesis::CreateStrictModeFunctionMaps(Handle<JSFunction> empty) { |
// only for processing of builtins. |
// Later the map is replaced with writable prototype map, allocated below. |
Handle<Map> strict_function_map = |
- CreateStrictFunctionMap(ADD_READONLY_PROTOTYPE, empty); |
+ CreateStrictFunctionMap(FUNCTION_WITH_READONLY_PROTOTYPE, empty); |
native_context()->set_strict_function_map(*strict_function_map); |
// The final map for the strict mode functions. Writeable prototype. |
// This map is installed in MakeFunctionInstancePrototypeWritable. |
strict_function_map_writable_prototype_ = |
- CreateStrictFunctionMap(ADD_WRITEABLE_PROTOTYPE, empty); |
+ CreateStrictFunctionMap(FUNCTION_WITH_WRITEABLE_PROTOTYPE, empty); |
+ // Special map for bound functions. |
+ Handle<Map> bound_function_map = |
+ CreateStrictFunctionMap(BOUND_FUNCTION, empty); |
+ native_context()->set_bound_function_map(*bound_function_map); |
// Complete the callbacks. |
PoisonArgumentsAndCaller(strict_function_without_prototype_map); |
PoisonArgumentsAndCaller(strict_function_map); |
PoisonArgumentsAndCaller(strict_function_map_writable_prototype_); |
+ PoisonArgumentsAndCaller(bound_function_map); |
} |