Revision: 7168
Author: [email protected]
Date: Mon Mar 14 10:46:37 2011
Log: Strict mode ThrowTypeError functions for
- function.caller
- function.arguments

Review URL: http://codereview.chromium.org/6691003/
http://code.google.com/p/v8/source/detail?r=7168

Modified:
 /branches/bleeding_edge/src/arm/codegen-arm.cc
 /branches/bleeding_edge/src/arm/full-codegen-arm.cc
 /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc
 /branches/bleeding_edge/src/bootstrapper.cc
 /branches/bleeding_edge/src/builtins.cc
 /branches/bleeding_edge/src/builtins.h
 /branches/bleeding_edge/src/contexts.h
 /branches/bleeding_edge/src/factory.cc
 /branches/bleeding_edge/src/factory.h
 /branches/bleeding_edge/src/handles.cc
 /branches/bleeding_edge/src/handles.h
 /branches/bleeding_edge/src/ia32/codegen-ia32.cc
 /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc
 /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc
 /branches/bleeding_edge/src/messages.js
 /branches/bleeding_edge/src/objects.cc
 /branches/bleeding_edge/src/runtime.cc
 /branches/bleeding_edge/src/x64/codegen-x64.cc
 /branches/bleeding_edge/src/x64/full-codegen-x64.cc
 /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc
 /branches/bleeding_edge/test/mjsunit/strict-mode.js

=======================================
--- /branches/bleeding_edge/src/arm/codegen-arm.cc      Mon Mar  7 11:23:46 2011
+++ /branches/bleeding_edge/src/arm/codegen-arm.cc      Mon Mar 14 10:46:37 2011
@@ -3112,9 +3112,10 @@
     bool pretenure) {
   // Use the fast case closure allocation code that allocates in new
   // space for nested functions that don't need literals cloning.
-  if (scope()->is_function_scope() &&
+  if (!pretenure &&
+      scope()->is_function_scope() &&
       function_info->num_literals() == 0 &&
-      !pretenure) {
+ !function_info->strict_mode()) { // Strict mode functions use slow path.
     FastNewClosureStub stub;
     frame_->EmitPush(Operand(function_info));
     frame_->SpillAll();
=======================================
--- /branches/bleeding_edge/src/arm/full-codegen-arm.cc Wed Mar 9 04:06:54 2011 +++ /branches/bleeding_edge/src/arm/full-codegen-arm.cc Mon Mar 14 10:46:37 2011
@@ -1084,9 +1084,10 @@
   // doesn't just get a copy of the existing unoptimized code.
   if (!FLAG_always_opt &&
       !FLAG_prepare_always_opt &&
+      !pretenure &&
       scope()->is_function_scope() &&
       info->num_literals() == 0 &&
-      !pretenure) {
+      !info->strict_mode()) {  // Strict mode functions use slow path.
     FastNewClosureStub stub;
     __ mov(r0, Operand(info));
     __ push(r0);
=======================================
--- /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Mon Mar 14 09:54:51 2011 +++ /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Mon Mar 14 10:46:37 2011
@@ -3717,7 +3717,8 @@
   // space for nested functions that don't need literals cloning.
   Handle<SharedFunctionInfo> shared_info = instr->shared_info();
   bool pretenure = instr->hydrogen()->pretenure();
-  if (shared_info->num_literals() == 0 && !pretenure) {
+  if (!pretenure && shared_info->num_literals() == 0 &&
+ !shared_info->strict_mode()) { // Strict mode functions use slow path.
     FastNewClosureStub stub;
     __ mov(r1, Operand(shared_info));
     __ push(r1);
=======================================
--- /branches/bleeding_edge/src/bootstrapper.cc Thu Mar  3 03:49:03 2011
+++ /branches/bleeding_edge/src/bootstrapper.cc Mon Mar 14 10:46:37 2011
@@ -207,6 +207,10 @@
   void CreateRoots();
   // Creates the empty function.  Used for creating a context from scratch.
   Handle<JSFunction> CreateEmptyFunction();
+  void CreateThrowTypeErrorCallbacks(
+      Handle<FixedArray> callbacks,
+      Builtins::Name builtin);
+  void CreateThrowTypeError(Handle<JSFunction> empty);
   // Creates the global objects using the global and the template passed in
   // through the API.  We call this regardless of whether we are building a
// context from scratch or using a deserialized one from the partial snapshot
@@ -263,6 +267,10 @@
   Handle<DescriptorArray> ComputeFunctionInstanceDescriptor(
       PrototypePropertyMode prototypeMode);
   void MakeFunctionInstancePrototypeWritable();
+  Handle<DescriptorArray> ComputeStrictFunctionDescriptor(
+      PrototypePropertyMode propertyMode,
+      Handle<FixedArray> arguments,
+      Handle<FixedArray> caller);

   static bool CompileBuiltin(int index);
static bool CompileNative(Vector<const char> name, Handle<String> source);
@@ -497,6 +505,113 @@
   empty_function->set_map(*empty_fm);
   return empty_function;
 }
+
+
+Handle<DescriptorArray> Genesis::ComputeStrictFunctionDescriptor(
+    PrototypePropertyMode prototypeMode,
+    Handle<FixedArray> arguments,
+    Handle<FixedArray> caller) {
+  Handle<DescriptorArray> descriptors =
+ Factory::NewDescriptorArray(prototypeMode == DONT_ADD_PROTOTYPE ? 4 : 5);
+  PropertyAttributes attributes = static_cast<PropertyAttributes>(
+      DONT_ENUM | DONT_DELETE | READ_ONLY);
+
+  {  // length
+    Handle<Proxy> proxy = Factory::NewProxy(&Accessors::FunctionLength);
+    CallbacksDescriptor d(*Factory::length_symbol(), *proxy, attributes);
+    descriptors->Set(0, &d);
+  }
+  {  // name
+    Handle<Proxy> proxy = Factory::NewProxy(&Accessors::FunctionName);
+    CallbacksDescriptor d(*Factory::name_symbol(), *proxy, attributes);
+    descriptors->Set(1, &d);
+  }
+  {  // arguments
+ CallbacksDescriptor d(*Factory::arguments_symbol(), *arguments, attributes);
+    descriptors->Set(2, &d);
+  }
+  {  // caller
+    CallbacksDescriptor d(*Factory::caller_symbol(), *caller, attributes);
+    descriptors->Set(3, &d);
+  }
+
+  // prototype
+  if (prototypeMode != DONT_ADD_PROTOTYPE) {
+    if (prototypeMode == ADD_WRITEABLE_PROTOTYPE) {
+ attributes = static_cast<PropertyAttributes>(attributes & ~READ_ONLY);
+    }
+    CallbacksDescriptor d(
+        *Factory::prototype_symbol(),
+        *Factory::NewProxy(&Accessors::FunctionPrototype),
+        attributes);
+    descriptors->Set(4, &d);
+  }
+
+  descriptors->Sort();
+  return descriptors;
+}
+
+
+void Genesis::CreateThrowTypeErrorCallbacks(
+    Handle<FixedArray> callbacks,
+    Builtins::Name builtin) {
+  // Create the ThrowTypeError function.
+  Handle<String> name = Factory::LookupAsciiSymbol("ThrowTypeError");
+ Handle<JSFunction> pill = Factory::NewFunctionWithoutPrototypeStrict(name);
+  Handle<Code> code = Handle<Code>(Builtins::builtin(builtin));
+  pill->set_map(global_context()->function_map_strict());
+  pill->set_code(*code);
+  pill->shared()->set_code(*code);
+  pill->shared()->DontAdaptArguments();
+
+  // Install the poison pills into the calbacks array.
+  callbacks->set(0, *pill);
+  callbacks->set(1, *pill);
+
+  PreventExtensions(pill);
+}
+
+
+// ECMAScript 5th Edition, 13.2.3
+void Genesis::CreateThrowTypeError(Handle<JSFunction> empty) {
+  // Create the pill callbacks arrays. The get/set callacks are installed
+  // after the maps get created below.
+  Handle<FixedArray> arguments = Factory::NewFixedArray(2, TENURED);
+  Handle<FixedArray> caller = Factory::NewFixedArray(2, TENURED);
+
+  {  // Allocate map for the strict mode function instances.
+    Handle<Map> map = Factory::NewMap(JS_FUNCTION_TYPE, JSFunction::kSize);
+    global_context()->set_function_instance_map_strict(*map);
+    Handle<DescriptorArray> descriptors = ComputeStrictFunctionDescriptor(
+        ADD_WRITEABLE_PROTOTYPE, arguments, caller);
+    map->set_instance_descriptors(*descriptors);
+    map->set_function_with_prototype(true);
+    map->set_prototype(*empty);
+  }
+
+  {  // Allocate map for the prototype-less strict mode instances.
+    Handle<Map> map = Factory::NewMap(JS_FUNCTION_TYPE, JSFunction::kSize);
+    global_context()->set_function_without_prototype_map_strict(*map);
+    Handle<DescriptorArray> descriptors = ComputeStrictFunctionDescriptor(
+        DONT_ADD_PROTOTYPE, arguments, caller);
+    map->set_instance_descriptors(*descriptors);
+    map->set_function_with_prototype(false);
+    map->set_prototype(*empty);
+  }
+
+  {  // Allocate map for the strict mode functions.
+    Handle<Map> map = Factory::NewMap(JS_FUNCTION_TYPE, JSFunction::kSize);
+    global_context()->set_function_map_strict(*map);
+    Handle<DescriptorArray> descriptors = ComputeStrictFunctionDescriptor(
+        ADD_READONLY_PROTOTYPE, arguments, caller);
+    map->set_instance_descriptors(*descriptors);
+    map->set_function_with_prototype(true);
+    map->set_prototype(*empty);
+  }
+
+ CreateThrowTypeErrorCallbacks(arguments, Builtins::StrictFunctionArguments);
+  CreateThrowTypeErrorCallbacks(caller, Builtins::StrictFunctionCaller);
+}


 static void AddToWeakGlobalContextList(Context* context) {
@@ -1858,6 +1973,7 @@
     // We get here if there was no context snapshot.
     CreateRoots();
     Handle<JSFunction> empty_function = CreateEmptyFunction();
+    CreateThrowTypeError(empty_function);
     Handle<GlobalObject> inner_global;
     Handle<JSGlobalProxy> global_proxy =
         CreateNewGlobals(global_template, global_object, &inner_global);
=======================================
--- /branches/bleeding_edge/src/builtins.cc     Tue Mar  1 20:53:43 2011
+++ /branches/bleeding_edge/src/builtins.cc     Mon Mar 14 10:46:37 2011
@@ -956,6 +956,24 @@

   return result_array;
 }
+
+
+// -----------------------------------------------------------------------------
+// Strict mode poison pills
+
+
+BUILTIN(StrictFunctionCaller) {
+  HandleScope scope;
+  return Top::Throw(*Factory::NewTypeError("strict_function_caller",
+ HandleVector<Object>(NULL, 0)));
+}
+
+
+BUILTIN(StrictFunctionArguments) {
+  HandleScope scope;
+  return Top::Throw(*Factory::NewTypeError("strict_function_arguments",
+ HandleVector<Object>(NULL, 0)));
+}


// -----------------------------------------------------------------------------
=======================================
--- /branches/bleeding_edge/src/builtins.h      Tue Mar  1 20:53:43 2011
+++ /branches/bleeding_edge/src/builtins.h      Mon Mar 14 10:46:37 2011
@@ -58,7 +58,10 @@
   V(FastHandleApiCall, NO_EXTRA_ARGUMENTS)                          \
   V(HandleApiCallConstruct, NEEDS_CALLED_FUNCTION)                  \
   V(HandleApiCallAsFunction, NO_EXTRA_ARGUMENTS)                    \
-  V(HandleApiCallAsConstructor, NO_EXTRA_ARGUMENTS)
+  V(HandleApiCallAsConstructor, NO_EXTRA_ARGUMENTS)                 \
+                                                                    \
+  V(StrictFunctionCaller, NO_EXTRA_ARGUMENTS)                       \
+  V(StrictFunctionArguments, NO_EXTRA_ARGUMENTS)


 // Define list of builtins implemented in assembly.
=======================================
--- /branches/bleeding_edge/src/contexts.h      Tue Dec  7 03:31:57 2010
+++ /branches/bleeding_edge/src/contexts.h      Mon Mar 14 10:46:37 2011
@@ -78,8 +78,12 @@
   V(INSTANTIATE_FUN_INDEX, JSFunction, instantiate_fun) \
   V(CONFIGURE_INSTANCE_FUN_INDEX, JSFunction, configure_instance_fun) \
   V(FUNCTION_MAP_INDEX, Map, function_map) \
+  V(FUNCTION_MAP_INDEX_STRICT, Map, function_map_strict) \
V(FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX, Map, function_without_prototype_map) \
+  V(FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX_STRICT, Map, \
+    function_without_prototype_map_strict) \
   V(FUNCTION_INSTANCE_MAP_INDEX, Map, function_instance_map) \
+ V(FUNCTION_INSTANCE_MAP_INDEX_STRICT, Map, function_instance_map_strict) \
   V(JS_ARRAY_MAP_INDEX, Map, js_array_map)\
   V(REGEXP_RESULT_MAP_INDEX, Map, regexp_result_map)\
   V(ARGUMENTS_BOILERPLATE_INDEX, JSObject, arguments_boilerplate) \
@@ -185,8 +189,11 @@
     JS_ARRAY_MAP_INDEX,
     REGEXP_RESULT_MAP_INDEX,
     FUNCTION_MAP_INDEX,
+    FUNCTION_MAP_INDEX_STRICT,
     FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX,
+    FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX_STRICT,
     FUNCTION_INSTANCE_MAP_INDEX,
+    FUNCTION_INSTANCE_MAP_INDEX_STRICT,
     INITIAL_OBJECT_PROTOTYPE_INDEX,
     BOOLEAN_FUNCTION_INDEX,
     NUMBER_FUNCTION_INDEX,
=======================================
--- /branches/bleeding_edge/src/factory.cc      Wed Mar  9 07:01:16 2011
+++ /branches/bleeding_edge/src/factory.cc      Mon Mar 14 10:46:37 2011
@@ -351,7 +351,12 @@
     Handle<Context> context,
     PretenureFlag pretenure) {
   Handle<JSFunction> result = BaseNewFunctionFromSharedFunctionInfo(
-      function_info, Top::function_map(), pretenure);
+      function_info,
+      function_info->strict_mode()
+          ? Top::function_map_strict()
+          : Top::function_map(),
+      pretenure);
+
   result->set_context(*context);
   int number_of_literals = function_info->num_literals();
   Handle<FixedArray> literals =
@@ -825,6 +830,24 @@
   return fun;
 }

+
+Handle<JSFunction> Factory::NewFunctionWithoutPrototypeStrictHelper(
+    Handle<String> name) {
+  Handle<SharedFunctionInfo> function_share = NewSharedFunctionInfo(name);
+  CALL_HEAP_FUNCTION(Heap::AllocateFunction(
+                         *Top::function_without_prototype_map_strict(),
+                         *function_share,
+                         *the_hole_value()),
+                     JSFunction);
+}
+
+
+Handle<JSFunction> Factory::NewFunctionWithoutPrototypeStrict(
+    Handle<String> name) {
+  Handle<JSFunction> fun = NewFunctionWithoutPrototypeStrictHelper(name);
+  fun->set_context(Top::context()->global_context());
+  return fun;
+}

 Handle<Object> Factory::ToObject(Handle<Object> object) {
   CALL_HEAP_FUNCTION(object->ToObject(), Object);
=======================================
--- /branches/bleeding_edge/src/factory.h       Wed Mar  9 07:01:16 2011
+++ /branches/bleeding_edge/src/factory.h       Mon Mar 14 10:46:37 2011
@@ -232,6 +232,8 @@
                                         Handle<Object> prototype);

static Handle<JSFunction> NewFunctionWithoutPrototype(Handle<String> name);
+  static Handle<JSFunction> NewFunctionWithoutPrototypeStrict(
+      Handle<String> name);

static Handle<JSFunction> NewFunction(Handle<Object> super, bool is_global);

@@ -408,6 +410,8 @@

   static Handle<JSFunction> NewFunctionWithoutPrototypeHelper(
       Handle<String> name);
+  static Handle<JSFunction> NewFunctionWithoutPrototypeStrictHelper(
+      Handle<String> name);

   static Handle<DescriptorArray> CopyAppendCallbackDescriptors(
       Handle<DescriptorArray> array,
=======================================
--- /branches/bleeding_edge/src/handles.cc      Wed Mar  9 07:01:16 2011
+++ /branches/bleeding_edge/src/handles.cc      Mon Mar 14 10:46:37 2011
@@ -360,6 +360,11 @@
   const bool skip_hidden_prototypes = false;
CALL_HEAP_FUNCTION(obj->SetPrototype(*value, skip_hidden_prototypes), Object);
 }
+
+
+Handle<Object> PreventExtensions(Handle<JSObject> object) {
+  CALL_HEAP_FUNCTION(object->PreventExtensions(), Object);
+}


 Handle<Object> GetHiddenProperties(Handle<JSObject> obj,
=======================================
--- /branches/bleeding_edge/src/handles.h       Tue Mar  8 03:14:25 2011
+++ /branches/bleeding_edge/src/handles.h       Mon Mar 14 10:46:37 2011
@@ -370,6 +370,7 @@
 Handle<Object> SetPrototype(Handle<JSFunction> function,
                             Handle<Object> prototype);

+Handle<Object> PreventExtensions(Handle<JSObject> object);

 // Does lazy compilation of the given function. Returns true on success and
 // false if the compilation resulted in a stack overflow.
=======================================
--- /branches/bleeding_edge/src/ia32/codegen-ia32.cc Mon Mar 7 11:23:46 2011 +++ /branches/bleeding_edge/src/ia32/codegen-ia32.cc Mon Mar 14 10:46:37 2011
@@ -4916,9 +4916,10 @@

   // Use the fast case closure allocation code that allocates in new
   // space for nested functions that don't need literals cloning.
-  if (scope()->is_function_scope() &&
+  if (!pretenure &&
+      scope()->is_function_scope() &&
       function_info->num_literals() == 0 &&
-      !pretenure) {
+ !function_info->strict_mode()) { // Strict mode functions use slow path.
     FastNewClosureStub stub;
     frame()->EmitPush(Immediate(function_info));
     return frame()->CallStub(&stub, 1);
=======================================
--- /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Wed Mar 9 04:06:54 2011 +++ /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Mon Mar 14 10:46:37 2011
@@ -1017,9 +1017,10 @@
   // doesn't just get a copy of the existing unoptimized code.
   if (!FLAG_always_opt &&
       !FLAG_prepare_always_opt &&
+      !pretenure &&
       scope()->is_function_scope() &&
       info->num_literals() == 0 &&
-      !pretenure) {
+ !info->strict_mode()) { // Strict mode functions go through slow path.
     FastNewClosureStub stub;
     __ push(Immediate(info));
     __ CallStub(&stub);
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Mon Mar 14 09:54:51 2011 +++ /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Mon Mar 14 10:46:37 2011
@@ -3693,7 +3693,8 @@
   // space for nested functions that don't need literals cloning.
   Handle<SharedFunctionInfo> shared_info = instr->shared_info();
   bool pretenure = instr->hydrogen()->pretenure();
-  if (shared_info->num_literals() == 0 && !pretenure) {
+  if (!pretenure && shared_info->num_literals() == 0 &&
+      !shared_info->strict_mode()) {
     FastNewClosureStub stub;
     __ push(Immediate(shared_info));
     CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, false);
=======================================
--- /branches/bleeding_edge/src/messages.js     Tue Mar  1 20:53:43 2011
+++ /branches/bleeding_edge/src/messages.js     Mon Mar 14 10:46:37 2011
@@ -230,6 +230,8 @@
strict_function: ["In strict mode code, functions can only be declared at top level or immediately within another function." ], strict_read_only_property: ["Cannot assign to read only property '", "%0", "' of ", "%1"], strict_cannot_assign: ["Cannot assign to read only '", "%0", "' in strict mode"], + strict_function_caller: ["Cannot access property 'caller' of a strict mode function"], + strict_function_arguments: ["Cannot access property 'arguments' of a strict mode function"],
     };
   }
   var message_type = %MessageGetType(message);
=======================================
--- /branches/bleeding_edge/src/objects.cc      Thu Mar 10 04:05:31 2011
+++ /branches/bleeding_edge/src/objects.cc      Mon Mar 14 10:46:37 2011
@@ -5536,12 +5536,21 @@


 Object* JSFunction::RemovePrototype() {
- if (map() == context()->global_context()->function_without_prototype_map()) {
+  Map* no_prototype_map = shared()->strict_mode()
+ ? context()->global_context()->function_without_prototype_map_strict()
+      : context()->global_context()->function_without_prototype_map();
+
+  if (map() == no_prototype_map) {
     // Be idempotent.
     return this;
   }
-  ASSERT(map() == context()->global_context()->function_map());
-  set_map(context()->global_context()->function_without_prototype_map());
+
+  ASSERT(!shared()->strict_mode() ||
+         map() == context()->global_context()->function_map_strict());
+  ASSERT(shared()->strict_mode() ||
+         map() == context()->global_context()->function_map());
+
+  set_map(no_prototype_map);
   set_prototype_or_initial_map(Heap::the_hole_value());
   return this;
 }
=======================================
--- /branches/bleeding_edge/src/runtime.cc      Wed Mar  9 07:01:16 2011
+++ /branches/bleeding_edge/src/runtime.cc      Mon Mar 14 10:46:37 2011
@@ -8037,11 +8037,14 @@
   HandleScope scope;
   ASSERT(args.length() == 1);
   CONVERT_ARG_CHECKED(JSFunction, func, 0);
-  ASSERT(func->map()->instance_type() ==
-         Top::function_instance_map()->instance_type());
-  ASSERT(func->map()->instance_size() ==
-         Top::function_instance_map()->instance_size());
-  func->set_map(*Top::function_instance_map());
+
+  Handle<Map> map = func->shared()->strict_mode()
+                        ? Top::function_instance_map_strict()
+                        : Top::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;
 }

=======================================
--- /branches/bleeding_edge/src/x64/codegen-x64.cc      Thu Mar 10 02:14:24 2011
+++ /branches/bleeding_edge/src/x64/codegen-x64.cc      Mon Mar 14 10:46:37 2011
@@ -4261,9 +4261,10 @@

   // Use the fast case closure allocation code that allocates in new
   // space for nested functions that don't need literals cloning.
-  if (scope()->is_function_scope() &&
+  if (!pretenure &&
+      scope()->is_function_scope() &&
       function_info->num_literals() == 0 &&
-      !pretenure) {
+ !function_info->strict_mode()) { // Strict mode functions use slow path.
     FastNewClosureStub stub;
     frame_->Push(function_info);
     Result answer = frame_->CallStub(&stub, 1);
=======================================
--- /branches/bleeding_edge/src/x64/full-codegen-x64.cc Wed Mar 9 04:06:54 2011 +++ /branches/bleeding_edge/src/x64/full-codegen-x64.cc Mon Mar 14 10:46:37 2011
@@ -1039,9 +1039,10 @@
   // doesn't just get a copy of the existing unoptimized code.
   if (!FLAG_always_opt &&
       !FLAG_prepare_always_opt &&
+      !pretenure &&
       scope()->is_function_scope() &&
       info->num_literals() == 0 &&
-      !pretenure) {
+      !info->strict_mode()) {  // Strict mode functions use slow path.
     FastNewClosureStub stub;
     __ Push(info);
     __ CallStub(&stub);
=======================================
--- /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Mon Mar 14 09:54:51 2011 +++ /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Mon Mar 14 10:46:37 2011
@@ -3496,7 +3496,8 @@
   // space for nested functions that don't need literals cloning.
   Handle<SharedFunctionInfo> shared_info = instr->shared_info();
   bool pretenure = instr->hydrogen()->pretenure();
-  if (shared_info->num_literals() == 0 && !pretenure) {
+  if (!pretenure && shared_info->num_literals() == 0 &&
+      !shared_info->strict_mode()) {
     FastNewClosureStub stub;
     __ Push(shared_info);
     CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
=======================================
--- /branches/bleeding_edge/test/mjsunit/strict-mode.js Mon Mar 7 11:23:46 2011 +++ /branches/bleeding_edge/test/mjsunit/strict-mode.js Mon Mar 14 10:46:37 2011
@@ -976,3 +976,47 @@
   assertEquals(["c", "d", "a", "b"], strict("a", "b"));
   assertEquals(["c", "d", "c", "d"], nonstrict("a", "b"));
 })();
+
+
+(function TestStrictFunctionPills() {
+  function strict() {
+    "use strict";
+  }
+  assertThrows(function() { strict.caller; }, TypeError);
+  assertThrows(function() { strict.arguments; }, TypeError);
+
+  var another = new Function("'use strict'");
+  assertThrows(function() { another.caller; }, TypeError);
+  assertThrows(function() { another.arguments; }, TypeError);
+
+  var third = (function() { "use strict"; return function() {}; })();
+  assertThrows(function() { third.caller; }, TypeError);
+  assertThrows(function() { third.arguments; }, TypeError);
+
+  function CheckPill(pill) {
+    assertEquals("function", typeof pill);
+    assertInstanceof(pill, Function);
+    assertThrows(function() { pill.property = "value"; }, TypeError);
+    assertThrows(pill, TypeError);
+    assertEquals(pill.prototype, (function(){}).prototype);
+    var d = Object.getOwnPropertyDescriptor(pill, "prototype");
+    assertFalse(d.writable);
+    assertFalse(d.configurable);
+    assertFalse(d.enumerable);
+  }
+
+  function CheckPillDescriptor(func, name) {
+    var descriptor = Object.getOwnPropertyDescriptor(func, name);
+    CheckPill(descriptor.get)
+    CheckPill(descriptor.set);
+    assertFalse(descriptor.enumerable);
+    assertFalse(descriptor.configurable);
+  }
+
+  CheckPillDescriptor(strict, "caller");
+  CheckPillDescriptor(strict, "arguments");
+  CheckPillDescriptor(another, "caller");
+  CheckPillDescriptor(another, "arguments");
+  CheckPillDescriptor(third, "caller");
+  CheckPillDescriptor(third, "arguments");
+})();

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to