Revision: 14619
Author: [email protected]
Date: Fri May 10 05:59:20 2013
Log: Remove separate maps for function instances
ES3 specified that functions created via Function() would have
enumerable prototypes, unlike function literals. For this reason, V8
has always had two prototypes for functions: "function_map" for
literals, and "function_instance_map" for "function instances": those
functions created by Function().
However, since 2009 or so, both maps have been the same! Both have had
writable, non-enumerable prototypes. Moreover, ES5 changed to specify
that function instances would have non-enumerable prototypes.
This patch removes the separate maps for function instances in sloppy
and strict mode.
[email protected]
TEST=mjsunit/function-prototype
BUG=
Review URL: https://codereview.chromium.org/14829005
http://code.google.com/p/v8/source/detail?r=14619
Modified:
/branches/bleeding_edge/include/v8.h
/branches/bleeding_edge/src/bootstrapper.cc
/branches/bleeding_edge/src/contexts.h
/branches/bleeding_edge/src/runtime.cc
/branches/bleeding_edge/src/runtime.h
/branches/bleeding_edge/src/v8natives.js
/branches/bleeding_edge/test/mjsunit/function-prototype.js
=======================================
--- /branches/bleeding_edge/include/v8.h Fri May 10 05:48:53 2013
+++ /branches/bleeding_edge/include/v8.h Fri May 10 05:59:20 2013
@@ -5025,7 +5025,7 @@
static const int kJSObjectHeaderSize = 3 * kApiPointerSize;
static const int kFixedArrayHeaderSize = 2 * kApiPointerSize;
static const int kContextHeaderSize = 2 * kApiPointerSize;
- static const int kContextEmbedderDataIndex = 65;
+ static const int kContextEmbedderDataIndex = 63;
static const int kFullStringRepresentationMask = 0x07;
static const int kStringEncodingMask = 0x4;
static const int kExternalTwoByteRepresentationTag = 0x02;
=======================================
--- /branches/bleeding_edge/src/bootstrapper.cc Wed May 8 08:02:08 2013
+++ /branches/bleeding_edge/src/bootstrapper.cc Fri May 10 05:59:20 2013
@@ -281,12 +281,12 @@
Handle<Context> result_;
Handle<Context> native_context_;
- // Function instance maps. Function literal maps are created initially
with
- // a read only prototype for the processing of JS builtins. Later the
function
- // instance maps are replaced in order to make prototype writable.
- // These are the final, writable prototype, maps.
- Handle<Map> function_instance_map_writable_prototype_;
- Handle<Map> strict_mode_function_instance_map_writable_prototype_;
+ // Function maps. Function maps are created initially with a read only
+ // prototype for the processing of JS builtins. Later the function maps
are
+ // replaced in order to make prototype writable. These are the final,
writable
+ // prototype, maps.
+ Handle<Map> function_map_writable_prototype_;
+ Handle<Map> strict_mode_function_map_writable_prototype_;
Handle<JSFunction> throw_type_error_function;
BootstrapperActive active_;
@@ -437,12 +437,6 @@
// Allocate the map for function instances. Maps are allocated first and
their
// prototypes patched later, once empty function is created.
- // Please note that the prototype property for function instances must be
- // writable.
- Handle<Map> function_instance_map =
- CreateFunctionMap(ADD_WRITEABLE_PROTOTYPE);
- native_context()->set_function_instance_map(*function_instance_map);
-
// Functions with this map will not have a 'prototype' property, and
// can not be used as constructors.
Handle<Map> function_without_prototype_map =
@@ -458,8 +452,7 @@
// The final map for functions. Writeable prototype.
// This map is installed in MakeFunctionInstancePrototypeWritable.
- function_instance_map_writable_prototype_ =
- CreateFunctionMap(ADD_WRITEABLE_PROTOTYPE);
+ function_map_writable_prototype_ =
CreateFunctionMap(ADD_WRITEABLE_PROTOTYPE);
Factory* factory = isolate->factory();
Heap* heap = isolate->heap();
@@ -509,10 +502,9 @@
// Set prototypes for the function maps.
native_context()->function_map()->set_prototype(*empty_function);
-
native_context()->function_instance_map()->set_prototype(*empty_function);
native_context()->function_without_prototype_map()->
set_prototype(*empty_function);
-
function_instance_map_writable_prototype_->set_prototype(*empty_function);
+ 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);
@@ -601,12 +593,6 @@
void Genesis::CreateStrictModeFunctionMaps(Handle<JSFunction> empty) {
- // Allocate map for the strict mode function instances.
- Handle<Map> strict_mode_function_instance_map =
- CreateStrictModeFunctionMap(ADD_WRITEABLE_PROTOTYPE, empty);
- native_context()->set_strict_mode_function_instance_map(
- *strict_mode_function_instance_map);
-
// Allocate map for the prototype-less strict mode instances.
Handle<Map> strict_mode_function_without_prototype_map =
CreateStrictModeFunctionMap(DONT_ADD_PROTOTYPE, empty);
@@ -623,15 +609,13 @@
// The final map for the strict mode functions. Writeable prototype.
// This map is installed in MakeFunctionInstancePrototypeWritable.
- strict_mode_function_instance_map_writable_prototype_ =
+ strict_mode_function_map_writable_prototype_ =
CreateStrictModeFunctionMap(ADD_WRITEABLE_PROTOTYPE, empty);
// Complete the callbacks.
- PoisonArgumentsAndCaller(strict_mode_function_instance_map);
PoisonArgumentsAndCaller(strict_mode_function_without_prototype_map);
PoisonArgumentsAndCaller(strict_mode_function_map);
- PoisonArgumentsAndCaller(
- strict_mode_function_instance_map_writable_prototype_);
+ PoisonArgumentsAndCaller(strict_mode_function_map_writable_prototype_);
}
@@ -2522,14 +2506,13 @@
// The maps with writable prototype are created in CreateEmptyFunction
// and CreateStrictModeFunctionMaps respectively. Initially the maps are
// created with read-only prototype for JS builtins processing.
- ASSERT(!function_instance_map_writable_prototype_.is_null());
- ASSERT(!strict_mode_function_instance_map_writable_prototype_.is_null());
+ ASSERT(!function_map_writable_prototype_.is_null());
+ ASSERT(!strict_mode_function_map_writable_prototype_.is_null());
// Replace function instance maps to make prototype writable.
- native_context()->set_function_map(
- *function_instance_map_writable_prototype_);
+ native_context()->set_function_map(*function_map_writable_prototype_);
native_context()->set_strict_mode_function_map(
- *strict_mode_function_instance_map_writable_prototype_);
+ *strict_mode_function_map_writable_prototype_);
}
=======================================
--- /branches/bleeding_edge/src/contexts.h Tue May 7 01:46:42 2013
+++ /branches/bleeding_edge/src/contexts.h Fri May 10 05:59:20 2013
@@ -138,9 +138,6 @@
V(FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX, Map,
function_without_prototype_map) \
V(STRICT_MODE_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX, Map, \
strict_mode_function_without_prototype_map) \
- V(FUNCTION_INSTANCE_MAP_INDEX, Map, function_instance_map) \
- V(STRICT_MODE_FUNCTION_INSTANCE_MAP_INDEX, Map, \
- strict_mode_function_instance_map) \
V(REGEXP_RESULT_MAP_INDEX, Map, regexp_result_map)\
V(ARGUMENTS_BOILERPLATE_INDEX, JSObject, arguments_boilerplate) \
V(ALIASED_ARGUMENTS_BOILERPLATE_INDEX, JSObject, \
@@ -260,8 +257,6 @@
STRICT_MODE_FUNCTION_MAP_INDEX,
FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX,
STRICT_MODE_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX,
- FUNCTION_INSTANCE_MAP_INDEX,
- STRICT_MODE_FUNCTION_INSTANCE_MAP_INDEX,
INITIAL_OBJECT_PROTOTYPE_INDEX,
BOOLEAN_FUNCTION_INDEX,
NUMBER_FUNCTION_INDEX,
=======================================
--- /branches/bleeding_edge/src/runtime.cc Wed May 8 08:02:08 2013
+++ /branches/bleeding_edge/src/runtime.cc Fri May 10 05:59:20 2013
@@ -9214,26 +9214,6 @@
language_mode,
args.smi_at(4));
}
-
-
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SetNewFunctionAttributes) {
- // This utility adjusts the property attributes for newly created
Function
- // object ("new Function(...)") by changing the map.
- // All it does is changing the prototype property to enumerable
- // as specified in ECMA262, 15.3.5.2.
- HandleScope scope(isolate);
- ASSERT(args.length() == 1);
- CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0);
-
- Handle<Map> map = func->shared()->is_classic_mode()
- ? isolate->function_instance_map()
- : isolate->strict_mode_function_instance_map();
-
- ASSERT(func->map()->instance_type() == map->instance_type());
- ASSERT(func->map()->instance_size() == map->instance_size());
- func->set_map(*map);
- return *func;
-}
RUNTIME_FUNCTION(MaybeObject*, Runtime_AllocateInNewSpace) {
=======================================
--- /branches/bleeding_edge/src/runtime.h Tue May 7 07:42:17 2013
+++ /branches/bleeding_edge/src/runtime.h Fri May 10 05:59:20 2013
@@ -100,7 +100,6 @@
F(GetOptimizationStatus, 1, 1) \
F(GetOptimizationCount, 1, 1) \
F(CompileForOnStackReplacement, 1, 1) \
- F(SetNewFunctionAttributes, 1, 1) \
F(AllocateInNewSpace, 1, 1) \
F(AllocateInOldPointerSpace, 1, 1) \
F(SetNativeFlag, 1, 1) \
=======================================
--- /branches/bleeding_edge/src/v8natives.js Fri May 3 06:01:28 2013
+++ /branches/bleeding_edge/src/v8natives.js Fri May 10 05:59:20 2013
@@ -1775,13 +1775,11 @@
var body = (n > 0) ? ToString(%_Arguments(n - 1)) : '';
var source = '(function(' + p + ') {\n' + body + '\n})';
- // The call to SetNewFunctionAttributes will ensure the prototype
- // property of the resulting function is enumerable (ECMA262, 15.3.5.2).
var global_receiver = %GlobalReceiver(global);
var f = %_CallFunction(global_receiver, %CompileString(source, true));
%FunctionMarkNameShouldPrintAsAnonymous(f);
- return %SetNewFunctionAttributes(f);
+ return f;
}
=======================================
--- /branches/bleeding_edge/test/mjsunit/function-prototype.js Tue Dec 7
03:01:02 2010
+++ /branches/bleeding_edge/test/mjsunit/function-prototype.js Fri May 10
05:59:20 2013
@@ -90,9 +90,28 @@
// in GetPrototypeOf and go to a monomorphic IC load instead.
assertEquals(87, GetPrototypeOf({prototype:87}));
-// Check the prototype is not enumerable, for compatibility with
-// safari. This is deliberately incompatible with ECMA262, 15.3.5.2.
+// Check the prototype is not enumerable, as per ES5 section 15.3.5.2.
Note
+// that this is in difference to ES3, which specified that function
instances
+// would have enumerable prototypes (section 15.3.5.2 also).
var foo = new Function("return x");
var result = ""
for (var n in foo) result += n;
assertEquals(result, "");
+
+f = new Function('return 1;')
+var desc = Object.getOwnPropertyDescriptor(f, "prototype");
+assertFalse(desc.configurable);
+assertFalse(desc.enumerable);
+assertTrue(desc.writable);
+
+f = Function('return 1;')
+var desc = Object.getOwnPropertyDescriptor(f, "prototype");
+assertFalse(desc.configurable);
+assertFalse(desc.enumerable);
+assertTrue(desc.writable);
+
+f = function () { return 1; }
+var desc = Object.getOwnPropertyDescriptor(f, "prototype");
+assertFalse(desc.configurable);
+assertFalse(desc.enumerable);
+assertTrue(desc.writable);
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.