Revision: 8110
Author:   [email protected]
Date:     Mon May 30 06:49:22 2011
Log:      Reapply change to Pass undefined to JS builtins when called with
implicit receiver.

A couple of corner cases have to be treated specially to not break
everything: eval and getter/setter definitions.

[email protected]
BUG=v8:1365
TEST=mjsunit/regress/regress-1365.js

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

Added:
 /branches/bleeding_edge/test/mjsunit/regress/regress-1365.js
Modified:
 /branches/bleeding_edge/src/arm/builtins-arm.cc
 /branches/bleeding_edge/src/arm/full-codegen-arm.cc
 /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc
 /branches/bleeding_edge/src/compiler.cc
 /branches/bleeding_edge/src/compiler.h
 /branches/bleeding_edge/src/handles.cc
 /branches/bleeding_edge/src/heap.cc
 /branches/bleeding_edge/src/hydrogen.cc
 /branches/bleeding_edge/src/ia32/builtins-ia32.cc
 /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc
 /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc
 /branches/bleeding_edge/src/mips/builtins-mips.cc
 /branches/bleeding_edge/src/objects-inl.h
 /branches/bleeding_edge/src/objects.h
 /branches/bleeding_edge/src/runtime.cc
 /branches/bleeding_edge/src/runtime.h
 /branches/bleeding_edge/src/v8natives.js
 /branches/bleeding_edge/src/x64/builtins-x64.cc
 /branches/bleeding_edge/src/x64/full-codegen-x64.cc
 /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc
 /branches/bleeding_edge/test/cctest/test-api.cc
 /branches/bleeding_edge/test/mjsunit/regress/regress-1170.js
 /branches/bleeding_edge/test/mjsunit/regress/regress-124.js
 /branches/bleeding_edge/test/mjsunit/regress/regress-485.js
 /branches/bleeding_edge/test/mozilla/mozilla.status
 /branches/bleeding_edge/test/sputnik/sputnik.status

=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/mjsunit/regress/regress-1365.js Mon May 30 06:49:22 2011
@@ -0,0 +1,65 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// See: http://code.google.com/p/v8/issues/detail?id=1365
+
+// Check that builtin methods are passed undefined as the receiver
+// when called as functions through variables.
+
+// Flags: --allow-natives-syntax
+
+// Global variable.
+var valueOf = Object.prototype.valueOf;
+var hasOwnProperty = Object.prototype.hasOwnProperty;
+
+function callGlobalValueOf() { valueOf(); }
+function callGlobalHasOwnProperty() { valueOf(); }
+
+assertEquals(Object.prototype, Object.prototype.valueOf());
+assertThrows(callGlobalValueOf);
+assertThrows(callGlobalHasOwnProperty);
+
+%OptimizeFunctionOnNextCall(Object.prototype.valueOf);
+Object.prototype.valueOf();
+
+assertEquals(Object.prototype, Object.prototype.valueOf());
+assertThrows(callGlobalValueOf);
+assertThrows(callGlobalHasOwnProperty);
+
+function CheckExceptionCallLocal() {
+  var valueOf = Object.prototype.valueOf;
+  var hasOwnProperty = Object.prototype.hasOwnProperty;
+  try { valueOf(); assertUnreachable(); } catch(e) { }
+  try { hasOwnProperty(); assertUnreachable(); } catch(e) { }
+}
+CheckExceptionCallLocal();
+
+function CheckExceptionCallParameter(f) {
+  try { f(); assertUnreachable(); } catch(e) { }
+}
+CheckExceptionCallParameter(Object.prototype.valueOf);
+CheckExceptionCallParameter(Object.prototype.hasOwnProperty);
=======================================
--- /branches/bleeding_edge/src/arm/builtins-arm.cc     Mon May 30 06:23:17 2011
+++ /branches/bleeding_edge/src/arm/builtins-arm.cc     Mon May 30 06:49:22 2011
@@ -1257,8 +1257,7 @@
     __ b(ne, &shift_arguments);

// Do not transform the receiver for native (Compilerhints already in r3).
-    __ tst(r3, Operand(1 << (SharedFunctionInfo::kES5Native +
-                             kSmiTagSize)));
+    __ tst(r3, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize)));
     __ b(ne, &shift_arguments);

     // Compute the receiver in non-strict mode.
@@ -1443,8 +1442,7 @@
   __ b(ne, &push_receiver);

   // Do not transform the receiver for strict mode functions.
-  __ tst(r2, Operand(1 << (SharedFunctionInfo::kES5Native +
-                           kSmiTagSize)));
+  __ tst(r2, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize)));
   __ b(ne, &push_receiver);

   // Compute the receiver in non-strict mode.
=======================================
--- /branches/bleeding_edge/src/arm/full-codegen-arm.cc Mon May 30 06:23:17 2011 +++ /branches/bleeding_edge/src/arm/full-codegen-arm.cc Mon May 30 06:49:22 2011
@@ -139,11 +139,11 @@
   }
 #endif

-  // Strict mode functions need to replace the receiver with undefined
-  // when called as functions (without an explicit receiver
-  // object). r5 is zero for method calls and non-zero for function
-  // calls.
-  if (info->is_strict_mode()) {
+  // Strict mode functions and builtins need to replace the receiver
+  // with undefined when called as functions (without an explicit
+  // receiver object). r5 is zero for method calls and non-zero for
+  // function calls.
+  if (info->is_strict_mode() || info->is_native()) {
     Label ok;
     __ cmp(r5, Operand(0));
     __ b(eq, &ok);
=======================================
--- /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Mon May 30 06:23:17 2011 +++ /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Mon May 30 06:49:22 2011
@@ -146,11 +146,11 @@
   // fp: Caller's frame pointer.
   // lr: Caller's pc.

-  // Strict mode functions need to replace the receiver with undefined
-  // when called as functions (without an explicit receiver
-  // object). r5 is zero for method calls and non-zero for function
-  // calls.
-  if (info_->is_strict_mode()) {
+  // Strict mode functions and builtins need to replace the receiver
+  // with undefined when called as functions (without an explicit
+  // receiver object). r5 is zero for method calls and non-zero for
+  // function calls.
+  if (info_->is_strict_mode() || info_->is_native()) {
     Label ok;
     __ cmp(r5, Operand(0));
     __ b(eq, &ok);
=======================================
--- /branches/bleeding_edge/src/compiler.cc     Thu May 26 04:22:29 2011
+++ /branches/bleeding_edge/src/compiler.cc     Mon May 30 06:49:22 2011
@@ -508,7 +508,10 @@
     info.MarkAsGlobal();
     info.SetExtension(extension);
     info.SetPreParseData(pre_data);
-    if (natives == NATIVES_CODE) info.MarkAsAllowingNativesSyntax();
+    if (natives == NATIVES_CODE) {
+      info.MarkAsAllowingNativesSyntax();
+      info.MarkAsNative();
+    }
     result = MakeFunctionInfo(&info);
     if (extension == NULL && !result.is_null()) {
       compilation_cache->PutScript(source, result);
@@ -677,6 +680,7 @@
   info.SetFunction(literal);
   info.SetScope(literal->scope());
   if (literal->scope()->is_strict_mode()) info.MarkAsStrictMode();
+  if (script->type()->value() == Script::TYPE_NATIVE) info.MarkAsNative();

   LiveEditFunctionTracker live_edit_tracker(info.isolate(), literal);
   // Determine if the function can be lazily compiled. This is necessary to
=======================================
--- /branches/bleeding_edge/src/compiler.h      Thu May 26 04:22:29 2011
+++ /branches/bleeding_edge/src/compiler.h      Mon May 30 06:49:22 2011
@@ -89,6 +89,12 @@
   bool allows_natives_syntax() const {
     return IsNativesSyntaxAllowed::decode(flags_);
   }
+  void MarkAsNative() {
+    flags_ |= IsNative::encode(true);
+  }
+  bool is_native() const {
+    return IsNative::decode(flags_);
+  }
   void SetFunction(FunctionLiteral* literal) {
     ASSERT(function_ == NULL);
     function_ = literal;
@@ -167,8 +173,9 @@

   void Initialize(Mode mode) {
     mode_ = V8::UseCrankshaft() ? mode : NONOPT;
-    if (!shared_info_.is_null() && shared_info_->strict_mode()) {
-      MarkAsStrictMode();
+    if (!shared_info_.is_null()) {
+      if (shared_info_->strict_mode()) MarkAsStrictMode();
+      if (shared_info_->native()) MarkAsNative();
     }
   }

@@ -191,6 +198,9 @@
   class IsStrictMode: public BitField<bool, 4, 1> {};
   // Native syntax (%-stuff) allowed?
   class IsNativesSyntaxAllowed: public BitField<bool, 5, 1> {};
+  // Is this a function from our natives.
+  class IsNative: public BitField<bool, 6, 1> {};
+

   unsigned flags_;

=======================================
--- /branches/bleeding_edge/src/handles.cc      Thu May 26 04:22:29 2011
+++ /branches/bleeding_edge/src/handles.cc      Mon May 30 06:49:22 2011
@@ -1,4 +1,4 @@
-// Copyright 2009 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
=======================================
--- /branches/bleeding_edge/src/heap.cc Thu May 26 04:22:29 2011
+++ /branches/bleeding_edge/src/heap.cc Mon May 30 06:49:22 2011
@@ -2388,7 +2388,7 @@
   share->set_num_literals(0);
   share->set_end_position(0);
   share->set_function_token_position(0);
-  share->set_es5_native(false);
+  share->set_native(false);
   return result;
 }

=======================================
--- /branches/bleeding_edge/src/hydrogen.cc     Mon May 30 04:31:41 2011
+++ /branches/bleeding_edge/src/hydrogen.cc     Mon May 30 06:49:22 2011
@@ -5959,10 +5959,11 @@
       inner->SetValueAt(i, push);
     }
   }
-  // If the function we are inlining is a strict mode function, pass
-  // undefined as the receiver for function calls (instead of the
-  // global receiver).
-  if (function->strict_mode() && call_kind == CALL_AS_FUNCTION) {
+  // If the function we are inlining is a strict mode function or a
+  // builtin function, pass undefined as the receiver for function
+  // calls (instead of the global receiver).
+  if ((target->shared()->native() || function->strict_mode()) &&
+      call_kind == CALL_AS_FUNCTION) {
     inner->SetValueAt(0, undefined);
   }
   inner->SetValueAt(arity + 1, outer->LookupContext());
=======================================
--- /branches/bleeding_edge/src/ia32/builtins-ia32.cc Mon May 30 06:23:17 2011 +++ /branches/bleeding_edge/src/ia32/builtins-ia32.cc Mon May 30 06:49:22 2011
@@ -615,8 +615,8 @@
     __ j(not_equal, &shift_arguments);

     // Do not transform the receiver for natives (shared already in ebx).
-    __ test_b(FieldOperand(ebx, SharedFunctionInfo::kES5NativeByteOffset),
-              1 << SharedFunctionInfo::kES5NativeBitWithinByte);
+    __ test_b(FieldOperand(ebx, SharedFunctionInfo::kNativeByteOffset),
+              1 << SharedFunctionInfo::kNativeBitWithinByte);
     __ j(not_equal, &shift_arguments);

     // Compute the receiver in non-strict mode.
@@ -780,8 +780,8 @@
   Factory* factory = masm->isolate()->factory();

   // Do not transform the receiver for natives (shared already in ecx).
-  __ test_b(FieldOperand(ecx, SharedFunctionInfo::kES5NativeByteOffset),
-            1 << SharedFunctionInfo::kES5NativeBitWithinByte);
+  __ test_b(FieldOperand(ecx, SharedFunctionInfo::kNativeByteOffset),
+            1 << SharedFunctionInfo::kNativeBitWithinByte);
   __ j(not_equal, &push_receiver);

   // Compute the receiver in non-strict mode.
=======================================
--- /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Mon May 30 06:23:17 2011 +++ /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Mon May 30 06:49:22 2011
@@ -131,11 +131,11 @@
   }
 #endif

-  // Strict mode functions need to replace the receiver with undefined
-  // when called as functions (without an explicit receiver
-  // object). ecx is zero for method calls and non-zero for function
-  // calls.
-  if (info->is_strict_mode()) {
+  // Strict mode functions and builtins need to replace the receiver
+  // with undefined when called as functions (without an explicit
+  // receiver object). ecx is zero for method calls and non-zero for
+  // function calls.
+  if (info->is_strict_mode() || info->is_native()) {
     Label ok;
     __ test(ecx, Operand(ecx));
     __ j(zero, &ok, Label::kNear);
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Mon May 30 06:23:17 2011 +++ /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Mon May 30 06:49:22 2011
@@ -128,11 +128,11 @@
   }
 #endif

-  // Strict mode functions need to replace the receiver with undefined
-  // when called as functions (without an explicit receiver
-  // object). ecx is zero for method calls and non-zero for function
-  // calls.
-  if (info_->is_strict_mode()) {
+  // Strict mode functions and builtins need to replace the receiver
+  // with undefined when called as functions (without an explicit
+  // receiver object). ecx is zero for method calls and non-zero for
+  // function calls.
+  if (info_->is_strict_mode() || info_->is_native()) {
     Label ok;
     __ test(ecx, Operand(ecx));
     __ j(zero, &ok, Label::kNear);
=======================================
--- /branches/bleeding_edge/src/mips/builtins-mips.cc Thu May 26 04:22:29 2011 +++ /branches/bleeding_edge/src/mips/builtins-mips.cc Mon May 30 06:49:22 2011
@@ -1214,8 +1214,7 @@
     __ Branch(&shift_arguments, ne, t0, Operand(zero_reg));

// Do not transform the receiver for native (Compilerhints already in a3).
-    __ And(t0, a3, Operand(1 << (SharedFunctionInfo::kES5Native +
-                                 kSmiTagSize)));
+ __ And(t0, a3, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize)));
     __ Branch(&shift_arguments, ne, t0, Operand(zero_reg));

     // Compute the receiver in non-strict mode.
@@ -1401,8 +1400,7 @@
   __ Branch(&push_receiver, ne, t0, Operand(zero_reg));

// Do not transform the receiver for native (Compilerhints already in a2).
-  __ And(t0, a2, Operand(1 << (SharedFunctionInfo::kES5Native +
-                               kSmiTagSize)));
+ __ And(t0, a2, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize)));
   __ Branch(&push_receiver, ne, t0, Operand(zero_reg));

   // Compute the receiver in non-strict mode.
=======================================
--- /branches/bleeding_edge/src/objects-inl.h   Thu May 26 04:22:29 2011
+++ /branches/bleeding_edge/src/objects-inl.h   Mon May 30 06:49:22 2011
@@ -3309,14 +3309,14 @@
 }


-bool SharedFunctionInfo::es5_native() {
-  return BooleanBit::get(compiler_hints(), kES5Native);
+bool SharedFunctionInfo::native() {
+  return BooleanBit::get(compiler_hints(), kNative);
 }


-void SharedFunctionInfo::set_es5_native(bool value) {
+void SharedFunctionInfo::set_native(bool value) {
   set_compiler_hints(BooleanBit::set(compiler_hints(),
-                                     kES5Native,
+                                     kNative,
                                      value));
 }

=======================================
--- /branches/bleeding_edge/src/objects.h       Thu May 26 04:22:29 2011
+++ /branches/bleeding_edge/src/objects.h       Mon May 30 06:49:22 2011
@@ -4406,12 +4406,12 @@
   inline bool strict_mode();
   inline void set_strict_mode(bool value);

-  // Indicates whether the function is a native ES5 function.
+  // Indicates whether the function is a native 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);
+  inline bool native();
+  inline void set_native(bool value);

   // Indicates whether or not the code in the shared function support
   // deoptimization.
@@ -4598,7 +4598,7 @@
   static const int kCodeAgeMask = 0x7;
   static const int kOptimizationDisabled = 6;
   static const int kStrictModeFunction = 7;
-  static const int kES5Native = 8;
+  static const int kNative = 8;

  private:
 #if V8_HOST_ARCH_32_BIT
@@ -4613,26 +4613,26 @@

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

-  static const int kES5NativeBitWithinByte =
-      (kES5Native + kCompilerHintsSmiTagSize) % kBitsPerByte;
+  static const int kNativeBitWithinByte =
+      (kNative + kCompilerHintsSmiTagSize) % kBitsPerByte;

 #if __BYTE_ORDER == __LITTLE_ENDIAN
   static const int kStrictModeByteOffset = kCompilerHintsOffset +
       (kStrictModeFunction + kCompilerHintsSmiTagSize) / kBitsPerByte;
-  static const int kES5NativeByteOffset = kCompilerHintsOffset +
-      (kES5Native + kCompilerHintsSmiTagSize) / kBitsPerByte;
+  static const int kNativeByteOffset = kCompilerHintsOffset +
+      (kNative + kCompilerHintsSmiTagSize) / kBitsPerByte;
 #elif __BYTE_ORDER == __BIG_ENDIAN
   static const int kStrictModeByteOffset = kCompilerHintsOffset +
       (kCompilerHintsSize - 1) -
       ((kStrictModeFunction + kCompilerHintsSmiTagSize) / kBitsPerByte);
-  static const int kES5NativeByteOffset = kCompilerHintsOffset +
+  static const int kNativeByteOffset = kCompilerHintsOffset +
       (kCompilerHintsSize - 1) -
-      ((kES5Native + kCompilerHintsSmiTagSize) / kBitsPerByte);
+      ((kNative + kCompilerHintsSmiTagSize) / kBitsPerByte);
 #else
 #error Unknown byte ordering
 #endif
=======================================
--- /branches/bleeding_edge/src/runtime.cc      Mon May 30 02:23:17 2011
+++ /branches/bleeding_edge/src/runtime.cc      Mon May 30 06:49:22 2011
@@ -4117,10 +4117,10 @@
 }


-// Set the ES5 native flag on the function.
+// Set the 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) {
+RUNTIME_FUNCTION(MaybeObject*, Runtime_SetNativeFlag) {
   NoHandleAllocation ha;
   RUNTIME_ASSERT(args.length() == 1);

@@ -4128,7 +4128,7 @@

   if (object->IsJSFunction()) {
     JSFunction* func = JSFunction::cast(*object);
-    func->shared()->set_es5_native(true);
+    func->shared()->set_native(true);
   }
   return isolate->heap()->undefined_value();
 }
=======================================
--- /branches/bleeding_edge/src/runtime.h       Thu May 26 06:58:48 2011
+++ /branches/bleeding_edge/src/runtime.h       Mon May 30 06:49:22 2011
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -92,7 +92,7 @@
   F(CompileForOnStackReplacement, 1, 1) \
   F(SetNewFunctionAttributes, 1, 1) \
   F(AllocateInNewSpace, 1, 1) \
-  F(SetES5Flag, 1, 1) \
+  F(SetNativeFlag, 1, 1) \
   \
   /* Array join support */ \
   F(PushIfAbsent, 2, 1) \
=======================================
--- /branches/bleeding_edge/src/v8natives.js    Thu May 26 04:22:29 2011
+++ /branches/bleeding_edge/src/v8natives.js    Mon May 30 06:49:22 2011
@@ -56,7 +56,7 @@
     %FunctionSetName(f, key);
     %FunctionRemovePrototype(f);
     %SetProperty(object, key, f, attributes);
-    %SetES5Flag(f);
+    %SetNativeFlag(f);
   }
   %ToFastProperties(object);
 }
@@ -132,10 +132,19 @@
 function GlobalEval(x) {
   if (!IS_STRING(x)) return x;

+  var receiver = this;
   var global_receiver = %GlobalReceiver(global);
-  var this_is_global_receiver = (this === global_receiver);
+
+  if (receiver == null && !IS_UNDETECTABLE(receiver)) {
+    receiver = global_receiver;
+  }
+
+  var this_is_global_receiver = (receiver === global_receiver);
   var global_is_detached = (global === global_receiver);

+  // For consistency with JSC we require the global object passed to
+  // eval to be the global object from which 'eval' originated. This
+  // is not mandated by the spec.
   if (!this_is_global_receiver || global_is_detached) {
     throw new $EvalError('The "this" object passed to eval must ' +
'be the global object from which eval originated');
@@ -144,7 +153,7 @@
   var f = %CompileString(x);
   if (!IS_FUNCTION(f)) return f;

-  return %_CallFunction(this, f);
+  return %_CallFunction(receiver, f);
 }


@@ -246,8 +255,9 @@

 // Extensions for providing property getters and setters.
 function ObjectDefineGetter(name, fun) {
-  if (this == null && !IS_UNDETECTABLE(this)) {
- throw new $TypeError('Object.prototype.__defineGetter__: this is Null');
+  var receiver = this;
+  if (receiver == null && !IS_UNDETECTABLE(receiver)) {
+    receiver = %GlobalReceiver(global);
   }
   if (!IS_FUNCTION(fun)) {
throw new $TypeError('Object.prototype.__defineGetter__: Expecting function');
@@ -256,21 +266,23 @@
   desc.setGet(fun);
   desc.setEnumerable(true);
   desc.setConfigurable(true);
-  DefineOwnProperty(ToObject(this), ToString(name), desc, false);
+  DefineOwnProperty(ToObject(receiver), ToString(name), desc, false);
 }


 function ObjectLookupGetter(name) {
-  if (this == null && !IS_UNDETECTABLE(this)) {
- throw new $TypeError('Object.prototype.__lookupGetter__: this is Null');
-  }
-  return %LookupAccessor(ToObject(this), ToString(name), GETTER);
+  var receiver = this;
+  if (receiver == null && !IS_UNDETECTABLE(receiver)) {
+    receiver = %GlobalReceiver(global);
+  }
+  return %LookupAccessor(ToObject(receiver), ToString(name), GETTER);
 }


 function ObjectDefineSetter(name, fun) {
-  if (this == null && !IS_UNDETECTABLE(this)) {
- throw new $TypeError('Object.prototype.__defineSetter__: this is Null');
+  var receiver = this;
+  if (receiver == null && !IS_UNDETECTABLE(receiver)) {
+    receiver = %GlobalReceiver(global);
   }
   if (!IS_FUNCTION(fun)) {
     throw new $TypeError(
@@ -280,15 +292,16 @@
   desc.setSet(fun);
   desc.setEnumerable(true);
   desc.setConfigurable(true);
-  DefineOwnProperty(ToObject(this), ToString(name), desc, false);
+  DefineOwnProperty(ToObject(receiver), ToString(name), desc, false);
 }


 function ObjectLookupSetter(name) {
-  if (this == null && !IS_UNDETECTABLE(this)) {
- throw new $TypeError('Object.prototype.__lookupSetter__: this is Null');
-  }
-  return %LookupAccessor(ToObject(this), ToString(name), SETTER);
+  var receiver = this;
+  if (receiver == null && !IS_UNDETECTABLE(receiver)) {
+    receiver = %GlobalReceiver(global);
+  }
+  return %LookupAccessor(ToObject(receiver), ToString(name), SETTER);
 }


=======================================
--- /branches/bleeding_edge/src/x64/builtins-x64.cc     Mon May 30 06:23:17 2011
+++ /branches/bleeding_edge/src/x64/builtins-x64.cc     Mon May 30 06:49:22 2011
@@ -675,8 +675,8 @@

     // Do not transform the receiver for natives.
     // SharedFunctionInfo is already loaded into rbx.
-    __ testb(FieldOperand(rbx, SharedFunctionInfo::kES5NativeByteOffset),
-             Immediate(1 << SharedFunctionInfo::kES5NativeBitWithinByte));
+    __ testb(FieldOperand(rbx, SharedFunctionInfo::kNativeByteOffset),
+             Immediate(1 << SharedFunctionInfo::kNativeBitWithinByte));
     __ j(not_zero, &shift_arguments);

     // Compute the receiver in non-strict mode.
@@ -847,8 +847,8 @@
   __ j(not_equal, &push_receiver);

   // Do not transform the receiver for natives.
-  __ testb(FieldOperand(rdx, SharedFunctionInfo::kES5NativeByteOffset),
-           Immediate(1 << SharedFunctionInfo::kES5NativeBitWithinByte));
+  __ testb(FieldOperand(rdx, SharedFunctionInfo::kNativeByteOffset),
+           Immediate(1 << SharedFunctionInfo::kNativeBitWithinByte));
   __ j(not_zero, &push_receiver);

   // Compute the receiver in non-strict mode.
=======================================
--- /branches/bleeding_edge/src/x64/full-codegen-x64.cc Mon May 30 06:23:17 2011 +++ /branches/bleeding_edge/src/x64/full-codegen-x64.cc Mon May 30 06:49:22 2011
@@ -131,11 +131,11 @@
   }
 #endif

-  // Strict mode functions need to replace the receiver with undefined
-  // when called as functions (without an explicit receiver
-  // object). rcx is zero for method calls and non-zero for function
-  // calls.
-  if (info->is_strict_mode()) {
+  // Strict mode functions and builtins need to replace the receiver
+  // with undefined when called as functions (without an explicit
+  // receiver object). rcx is zero for method calls and non-zero for
+  // function calls.
+  if (info->is_strict_mode() || info->is_native()) {
     Label ok;
     __ testq(rcx, rcx);
     __ j(zero, &ok, Label::kNear);
=======================================
--- /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Mon May 30 06:23:17 2011 +++ /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Mon May 30 06:49:22 2011
@@ -144,7 +144,7 @@
   // when called as functions (without an explicit receiver
   // object). rcx is zero for method calls and non-zero for function
   // calls.
-  if (info_->is_strict_mode()) {
+  if (info_->is_strict_mode() || info_->is_native()) {
     Label ok;
     __ testq(rcx, rcx);
     __ j(zero, &ok, Label::kNear);
=======================================
--- /branches/bleeding_edge/test/cctest/test-api.cc     Thu May 26 04:22:29 2011
+++ /branches/bleeding_edge/test/cctest/test-api.cc     Mon May 30 06:49:22 2011
@@ -6664,7 +6664,7 @@
   context->Global()->Set(v8_str("__proto__"), o);

   Local<Value> value =
-      Script::Compile(v8_str("propertyIsEnumerable(0)"))->Run();
+      Script::Compile(v8_str("this.propertyIsEnumerable(0)"))->Run();
   CHECK(value->IsBoolean());
   CHECK(!value->BooleanValue());

=======================================
--- /branches/bleeding_edge/test/mjsunit/regress/regress-1170.js Thu May 26 04:22:29 2011 +++ /branches/bleeding_edge/test/mjsunit/regress/regress-1170.js Mon May 30 06:49:22 2011
@@ -30,18 +30,18 @@
 __proto__.__defineSetter__("a", function(v) { setter_value = v; });
 eval("var a = 1");
 assertEquals(1, setter_value);
-assertFalse(hasOwnProperty("a"));
+assertFalse(this.hasOwnProperty("a"));

 eval("with({}) { eval('var a = 2') }");
 assertEquals(2, setter_value);
-assertFalse(hasOwnProperty("a"));
+assertFalse(this.hasOwnProperty("a"));

 // Function declarations are treated specially to match Safari. We do
 // not call setters for them.
 eval("function a() {}");
-assertTrue(hasOwnProperty("a"));
-
-__proto__.__defineSetter__("b", function(v) {   assertUnreachable(); });
+assertTrue(this.hasOwnProperty("a"));
+
+__proto__.__defineSetter__("b", function(v) { assertUnreachable(); });
 try {
   eval("const b = 23");
   assertUnreachable();
@@ -61,6 +61,5 @@
   assertUnreachable();
 } catch(e) {
   assertEquals(42, e);
-  assertFalse(hasOwnProperty("c"));
-}
-
+  assertFalse(this.hasOwnProperty("c"));
+}
=======================================
--- /branches/bleeding_edge/test/mjsunit/regress/regress-124.js Thu May 26 04:22:29 2011 +++ /branches/bleeding_edge/test/mjsunit/regress/regress-124.js Mon May 30 06:49:22 2011
@@ -26,13 +26,13 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

 assertEquals("[object global]", this.toString());
-assertEquals("[object global]", toString());
+assertEquals("[object Undefined]", toString());

 assertEquals("[object global]", eval("this.toString()"));
-assertEquals("[object global]", eval("toString()"));
+assertEquals("[object Undefined]", eval("toString()"));

 assertEquals("[object global]", eval("var f; this.toString()"));
-assertEquals("[object global]", eval("var f; toString()"));
+assertEquals("[object Undefined]", eval("var f; toString()"));


 function F(f) {
@@ -45,7 +45,7 @@
   assertEquals("[object global]", eval("var f; this.toString()"));
   assertEquals("[object global]", eval("var f; toString()"));

-  assertEquals("[object global]", eval("f()"));
+  assertEquals("[object Undefined]", eval("f()"));

   // Receiver should be the arguments object here.
   assertEquals("[object Arguments]", eval("arguments[0]()"));
=======================================
--- /branches/bleeding_edge/test/mjsunit/regress/regress-485.js Thu May 26 04:22:29 2011 +++ /branches/bleeding_edge/test/mjsunit/regress/regress-485.js Mon May 30 06:49:22 2011
@@ -34,11 +34,6 @@
 var global2 = (function(){return this;})();
assertEquals(global, global2, "direct call to local function returns global");

-var builtin = Object.prototype.valueOf; // Builtin function that returns this.
-
-assertEquals(global, builtin(), "Direct call to builtin");
-
-
 // Builtin that depends on value of this to compute result.
 var builtin2 = Object.prototype.toString;

=======================================
--- /branches/bleeding_edge/test/mozilla/mozilla.status Thu May 26 04:22:29 2011 +++ /branches/bleeding_edge/test/mozilla/mozilla.status Mon May 30 06:49:22 2011
@@ -206,6 +206,10 @@
 # This section is for tests that fail in both V8 and JSC.  Thus they
 # have been determined to be incompatible between Mozilla and V8/JSC.

+# Fail because it calls builtins as functions and do not expect the
+# builtin to have undefined as the receiver.
+ecma/String/15.5.4.6-2: FAIL_OK
+
 # Fail because of toLowerCase and toUpperCase conversion.
 ecma/String/15.5.4.11-2: FAIL_OK
 ecma/String/15.5.4.11-5: FAIL_OK
=======================================
--- /branches/bleeding_edge/test/sputnik/sputnik.status Thu May 26 04:22:29 2011 +++ /branches/bleeding_edge/test/sputnik/sputnik.status Mon May 30 06:49:22 2011
@@ -175,6 +175,23 @@
 S9.9_A1: FAIL_OK
 S9.9_A2: FAIL_OK

+# Calls builtins without an explicit receiver which means that
+# undefined is passed to the builtin. The tests expect the global
+# object to be passed which was true in ES3 but not in ES5.
+S11.1.1_A2: FAIL_OK
+S15.5.4.4_A1_T3: FAIL_OK
+S15.5.4.5_A1_T3: FAIL_OK
+S15.5.4.6_A1_T3: FAIL_OK
+S15.5.4.7_A1_T3: FAIL_OK
+S15.5.4.8_A1_T3: FAIL_OK
+S15.5.4.9_A1_T3: FAIL_OK
+S15.5.4.10_A1_T3: FAIL_OK
+S15.5.4.11_A1_T3: FAIL_OK
+S15.5.4.12_A1_T3: FAIL_OK
+S15.5.4.13_A1_T3: FAIL_OK
+S15.5.4.14_A1_T3: FAIL_OK
+S15.5.4.15_A1_T3: FAIL_OK
+
 ##################### SKIPPED TESTS #####################

 # These tests take a looong time to run in debug mode.

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

Reply via email to