Chromium Code Reviews| Index: src/bootstrapper.cc |
| =================================================================== |
| --- src/bootstrapper.cc (revision 4462) |
| +++ src/bootstrapper.cc (working copy) |
| @@ -248,9 +248,13 @@ |
| 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 |
| + }; |
| Handle<DescriptorArray> ComputeFunctionInstanceDescriptor( |
| - bool make_prototype_read_only, |
| - bool make_prototype_enumerable = false); |
| + PrototypePropertyMode prototypeMode); |
| void MakeFunctionInstancePrototypeWritable(); |
| static bool CompileBuiltin(int index); |
| @@ -330,7 +334,8 @@ |
| bool is_ecma_native) { |
| Handle<String> symbol = Factory::LookupAsciiSymbol(name); |
| Handle<Code> call_code = Handle<Code>(Builtins::builtin(call)); |
| - Handle<JSFunction> function = |
| + Handle<JSFunction> function = prototype.is_null() ? |
| + Factory::NewFunctionWithoutPrototype(symbol, call_code) : |
| Factory::NewFunctionWithPrototype(symbol, |
| type, |
| instance_size, |
| @@ -346,23 +351,23 @@ |
| Handle<DescriptorArray> Genesis::ComputeFunctionInstanceDescriptor( |
| - bool make_prototype_read_only, |
| - bool make_prototype_enumerable) { |
| + PrototypePropertyMode prototypeMode) { |
| Handle<DescriptorArray> result = Factory::empty_descriptor_array(); |
| - // Add prototype. |
| - PropertyAttributes attributes = static_cast<PropertyAttributes>( |
| - (make_prototype_enumerable ? 0 : DONT_ENUM) |
| - | DONT_DELETE |
| - | (make_prototype_read_only ? READ_ONLY : 0)); |
| - result = |
| - Factory::CopyAppendProxyDescriptor( |
| - result, |
| - Factory::prototype_symbol(), |
| - Factory::NewProxy(&Accessors::FunctionPrototype), |
| - attributes); |
| + if (prototypeMode != DONT_ADD_PROTOTYPE) { |
| + PropertyAttributes attributes = static_cast<PropertyAttributes>( |
| + DONT_ENUM | |
| + DONT_DELETE | |
| + (prototypeMode == ADD_READONLY_PROTOTYPE ? READ_ONLY : 0)); |
| + result = |
| + Factory::CopyAppendProxyDescriptor( |
| + result, |
| + Factory::prototype_symbol(), |
| + Factory::NewProxy(&Accessors::FunctionPrototype), |
| + attributes); |
| + } |
| - attributes = |
| + PropertyAttributes attributes = |
| static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY); |
| // Add length. |
| result = |
| @@ -407,14 +412,26 @@ |
| // Please note that the prototype property for function instances must be |
| // writable. |
| Handle<DescriptorArray> function_map_descriptors = |
| - ComputeFunctionInstanceDescriptor(false, false); |
| + ComputeFunctionInstanceDescriptor(ADD_WRITEABLE_PROTOTYPE); |
| fm->set_instance_descriptors(*function_map_descriptors); |
| + fm->set_function_with_prototype(true); |
| + // Functions with this map will not have a 'prototype' property, and |
| + // can not be used as constructors. |
| + fm = Factory::NewMap(JS_FUNCTION_TYPE, JSFunction::kSize); |
| + global_context()->set_function_without_prototype_map(*fm); |
| + function_map_descriptors = |
| + ComputeFunctionInstanceDescriptor(DONT_ADD_PROTOTYPE); |
| + fm->set_instance_descriptors(*function_map_descriptors); |
| + fm->set_function_with_prototype(false); |
| + |
| // Allocate the function map first and then patch the prototype later |
| fm = Factory::NewMap(JS_FUNCTION_TYPE, JSFunction::kSize); |
| global_context()->set_function_map(*fm); |
| - function_map_descriptors = ComputeFunctionInstanceDescriptor(true); |
| + function_map_descriptors = |
| + ComputeFunctionInstanceDescriptor(ADD_READONLY_PROTOTYPE); |
| fm->set_instance_descriptors(*function_map_descriptors); |
| + fm->set_function_with_prototype(true); |
| Handle<String> object_name = Handle<String>(Heap::Object_symbol()); |
| @@ -458,6 +475,11 @@ |
| global_context()->function_map()->set_prototype(*empty_function); |
| global_context()->function_instance_map()->set_prototype(*empty_function); |
| + // Allocate a distinct prototype for this function map, so it will not add |
|
Mads Ager (chromium)
2010/04/28 10:40:04
Make the comment a bit more explicit? How about:
dgozman
2010/04/28 11:16:59
Done.
|
| + // 'prototype' property in the proto chain. |
| + global_context()->function_without_prototype_map()->set_prototype( |
| + *Factory::NewJSObject(Top::object_function(), TENURED)); |
| + |
| // Allocate the function map first and then patch the prototype later |
| Handle<Map> empty_fm = Factory::CopyMapDropDescriptors(fm); |
| empty_fm->set_instance_descriptors(*function_map_descriptors); |
| @@ -1215,12 +1237,12 @@ |
| // Install the call and the apply functions. |
| Handle<JSFunction> call = |
| InstallFunction(proto, "call", JS_OBJECT_TYPE, JSObject::kHeaderSize, |
| - Factory::NewJSObject(Top::object_function(), TENURED), |
| + Handle<JSObject>::null(), |
| Builtins::FunctionCall, |
| false); |
| Handle<JSFunction> apply = |
| InstallFunction(proto, "apply", JS_OBJECT_TYPE, JSObject::kHeaderSize, |
| - Factory::NewJSObject(Top::object_function(), TENURED), |
| + Handle<JSObject>::null(), |
| Builtins::FunctionApply, |
| false); |
| @@ -1236,6 +1258,23 @@ |
| // Set the lengths for the functions to satisfy ECMA-262. |
| call->shared()->set_length(1); |
| apply->shared()->set_length(2); |
| + |
| + // Install the call, apply, toString and constructor properties |
| + // for the functions without prototype. |
| + Handle<JSObject> wp_proto = Handle<JSObject>( |
| + JSObject::cast(Top::function_without_prototype_map()->prototype())); |
| + |
| + Handle<String> call_symbol = Factory::LookupAsciiSymbol("call"); |
| + SetProperty(wp_proto, call_symbol, call, DONT_ENUM); |
| + |
| + Handle<String> apply_symbol = Factory::LookupAsciiSymbol("apply"); |
| + SetProperty(wp_proto, apply_symbol, apply, DONT_ENUM); |
| + |
| + Handle<Object> to_string = GetProperty(proto, "toString"); |
| + Handle<String> to_string_symbol = Factory::LookupAsciiSymbol("toString"); |
| + SetProperty(wp_proto, to_string_symbol, to_string, DONT_ENUM); |
| + |
| + SetProperty(wp_proto, Factory::constructor_symbol(), function, DONT_ENUM); |
| } |
| // Create a constructor for RegExp results (a variant of Array that |
| @@ -1655,9 +1694,10 @@ |
| HandleScope scope; |
| Handle<DescriptorArray> function_map_descriptors = |
| - ComputeFunctionInstanceDescriptor(false); |
| + ComputeFunctionInstanceDescriptor(ADD_WRITEABLE_PROTOTYPE); |
| Handle<Map> fm = Factory::CopyMapDropDescriptors(Top::function_map()); |
| fm->set_instance_descriptors(*function_map_descriptors); |
| + fm->set_function_with_prototype(true); |
| Top::context()->global_context()->set_function_map(*fm); |
| } |