| 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);
|
| }
|
|
|
|
|
|
|