Reviewers: Mads Ager,

Description:
Only send null or undefined as receiver for es5 natives, not generally
for builtin functions.

Please review this at http://codereview.chromium.org/7012012/

SVN Base: http://v8.googlecode.com/svn/branches/bleeding_edge/

Affected files:
  M     src/heap.cc
  M     src/ia32/builtins-ia32.cc
  M     src/objects-inl.h
  M     src/objects.h
  M     src/runtime.h
  M     src/runtime.cc
  M     src/v8natives.js


Index: src/heap.cc
===================================================================
--- src/heap.cc (revision 7871)
+++ src/heap.cc (working copy)
@@ -2377,6 +2377,7 @@
   share->set_num_literals(0);
   share->set_end_position(0);
   share->set_function_token_position(0);
+  share->set_es5_native(false);
   return result;
 }

Index: src/ia32/builtins-ia32.cc
===================================================================
--- src/ia32/builtins-ia32.cc   (revision 7871)
+++ src/ia32/builtins-ia32.cc   (working copy)
@@ -600,13 +600,9 @@
     __ j(not_equal, &shift_arguments);

     // Do not transform the receiver for natives (shared already in ebx).
-    __ mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kScriptOffset));
-    __ cmp(ebx, factory->undefined_value());
-    __ j(equal, &shift_arguments);
-    __ mov(ebx, FieldOperand(ebx, Script::kTypeOffset));
-    __ SmiUntag(ebx);
-    __ cmp(ebx, Script::TYPE_NATIVE);
-    __ j(equal, &shift_arguments);
+    __ test_b(FieldOperand(ebx, SharedFunctionInfo::kES5NativeByteOffset),
+            1 << SharedFunctionInfo::kES5NativeBitWithinByte);
+    __ j(not_zero, &shift_arguments);

     // Compute the receiver in non-strict mode.
     __ mov(ebx, Operand(esp, eax, times_4, 0));  // First argument.
@@ -767,13 +763,9 @@
   Factory* factory = masm->isolate()->factory();

   // Do not transform the receiver for natives (shared already in ecx).
-  __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kScriptOffset));
-  __ cmp(ecx, factory->undefined_value());
-  __ j(equal, &push_receiver);
-  __ mov(ecx, FieldOperand(ecx, Script::kTypeOffset));
-  __ SmiUntag(ecx);
-  __ cmp(ecx, Script::TYPE_NATIVE);
-  __ j(equal, &push_receiver);
+  __ test_b(FieldOperand(ecx, SharedFunctionInfo::kES5NativeByteOffset),
+            1 << SharedFunctionInfo::kES5NativeBitWithinByte);
+  __ j(not_zero, &push_receiver);

   // Compute the receiver in non-strict mode.
   __ test(ebx, Immediate(kSmiTagMask));
Index: src/objects-inl.h
===================================================================
--- src/objects-inl.h   (revision 7871)
+++ src/objects-inl.h   (working copy)
@@ -3218,6 +3218,18 @@
 }


+bool SharedFunctionInfo::es5_native() {
+  return BooleanBit::get(compiler_hints(), kES5Native);
+}
+
+
+void SharedFunctionInfo::set_es5_native(bool value) {
+  set_compiler_hints(BooleanBit::set(compiler_hints(),
+                                     kES5Native,
+                                     value));
+}
+
+
 ACCESSORS(CodeCache, default_cache, FixedArray, kDefaultCacheOffset)
 ACCESSORS(CodeCache, normal_type_cache, Object, kNormalTypeCacheOffset)

Index: src/objects.h
===================================================================
--- src/objects.h       (revision 7871)
+++ src/objects.h       (working copy)
@@ -4340,6 +4340,13 @@
   inline bool strict_mode();
   inline void set_strict_mode(bool value);

+  // Indicates whether the function is a native ES5 function.
+  // These needs special threatment in .call and .apply since
+  // null passed as the receiver should not be translated to the
+  // global object.
+  inline bool es5_native();
+  inline void set_es5_native(bool value);
+
   // Indicates whether or not the code in the shared function support
   // deoptimization.
   inline bool has_deoptimization_support();
@@ -4520,6 +4527,7 @@
   static const int kCodeAgeMask = 0x7;
   static const int kOptimizationDisabled = 6;
   static const int kStrictModeFunction = 7;
+  static const int kES5Native = 8;

  private:
 #if V8_HOST_ARCH_32_BIT
@@ -4533,18 +4541,27 @@
 #endif

  public:
-  // Constants for optimizing codegen for strict mode function tests.
+  // Constants for optimizing codegen for strict mode function and
+  // es5 native tests.
   // Allows to use byte-widgh instructions.
   static const int kStrictModeBitWithinByte =
       (kStrictModeFunction + kCompilerHintsSmiTagSize) % kBitsPerByte;

+  static const int kES5NativeBitWithinByte =
+      (kES5Native + kCompilerHintsSmiTagSize) % kBitsPerByte;
+
 #if __BYTE_ORDER == __LITTLE_ENDIAN
   static const int kStrictModeByteOffset = kCompilerHintsOffset +
-    (kStrictModeFunction + kCompilerHintsSmiTagSize) / kBitsPerByte;
+      (kStrictModeFunction + kCompilerHintsSmiTagSize) / kBitsPerByte;
+  static const int kES5NativeByteOffset = kCompilerHintsOffset +
+      (kES5Native + kCompilerHintsSmiTagSize) / kBitsPerByte;
 #elif __BYTE_ORDER == __BIG_ENDIAN
   static const int kStrictModeByteOffset = kCompilerHintsOffset +
-    (kCompilerHintsSize - 1) -
-    ((kStrictModeFunction + kCompilerHintsSmiTagSize) / kBitsPerByte);
+      (kCompilerHintsSize - 1) -
+      ((kStrictModeFunction + kCompilerHintsSmiTagSize) / kBitsPerByte);
+  static const int kES5NativeByteOffset = kCompilerHintsOffset +
+      (kCompilerHintsSize - 1) -
+      ((kES5Native + kCompilerHintsSmiTagSize) / kBitsPerByte);
 #else
 #error Unknown byte ordering
 #endif
Index: src/runtime.cc
===================================================================
--- src/runtime.cc      (revision 7871)
+++ src/runtime.cc      (working copy)
@@ -4107,6 +4107,23 @@
 }


+// Set the ES5 native flag on the function.
+// This is used to decide if we should transform null and undefined
+// into the global object when doing call and apply.
+RUNTIME_FUNCTION(MaybeObject*, Runtime_SetES5Flag) {
+  NoHandleAllocation ha;
+  RUNTIME_ASSERT(args.length() == 1);
+
+  Handle<Object> object = args.at<Object>(0);
+
+  if (object->IsJSFunction()) {
+    JSFunction* func = JSFunction::cast(*object);
+    func->shared()->set_es5_native(true);
+  }
+  return isolate->heap()->undefined_value();
+}
+
+
 // Set a local property, even if it is READ_ONLY.  If the property does not
 // exist, it will be added with attributes NONE.
 RUNTIME_FUNCTION(MaybeObject*, Runtime_IgnoreAttributesAndSetProperty) {
Index: src/runtime.h
===================================================================
--- src/runtime.h       (revision 7871)
+++ src/runtime.h       (working copy)
@@ -92,6 +92,7 @@
   F(CompileForOnStackReplacement, 1, 1) \
   F(SetNewFunctionAttributes, 1, 1) \
   F(AllocateInNewSpace, 1, 1) \
+  F(SetES5Flag, 1, 1) \
   \
   /* Array join support */ \
   F(PushIfAbsent, 2, 1) \
Index: src/v8natives.js
===================================================================
--- src/v8natives.js    (revision 7871)
+++ src/v8natives.js    (working copy)
@@ -56,6 +56,7 @@
     %FunctionSetName(f, key);
     %FunctionRemovePrototype(f);
     %SetProperty(object, key, f, attributes);
+    %SetES5Flag(f);
   }
   %ToFastProperties(object);
 }


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

Reply via email to