Revision: 7879
Author: [email protected]
Date: Fri May 13 00:26:44 2011
Log: Only send null or undefined as receiver for es5 natives, not
generally
for builtin functions.
Review URL: http://codereview.chromium.org/7012012
http://code.google.com/p/v8/source/detail?r=7879
Modified:
/branches/bleeding_edge/src/arm/builtins-arm.cc
/branches/bleeding_edge/src/heap.cc
/branches/bleeding_edge/src/ia32/builtins-ia32.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/test/cctest/test-api.cc
/branches/bleeding_edge/test/mjsunit/regress/regress-1369.js
=======================================
--- /branches/bleeding_edge/src/arm/builtins-arm.cc Wed May 4 22:21:30 2011
+++ /branches/bleeding_edge/src/arm/builtins-arm.cc Fri May 13 00:26:44 2011
@@ -1243,15 +1243,10 @@
kSmiTagSize)));
__ b(ne, &shift_arguments);
- // Do not transform the receiver for native (shared already in r2).
- __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kScriptOffset));
- __ LoadRoot(r3, Heap::kUndefinedValueRootIndex);
- __ cmp(r2, r3);
- __ b(eq, &shift_arguments);
- __ ldr(r2, FieldMemOperand(r2, Script::kTypeOffset));
- __ mov(r2, Operand(r2, ASR, kSmiTagSize));
- __ cmp(r2, Operand(Script::TYPE_NATIVE));
- __ b(eq, &shift_arguments);
+ // Do not transform the receiver for native (Compilerhints already in
r3).
+ __ tst(r3, Operand(1 << (SharedFunctionInfo::kES5Native +
+ kSmiTagSize)));
+ __ b(ne, &shift_arguments);
// Compute the receiver in non-strict mode.
__ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2));
@@ -1262,7 +1257,7 @@
__ tst(r2, Operand(kSmiTagMask));
__ b(eq, &convert_to_object);
- // Heap::kUndefinedValueRootIndex is already in r3.
+ __ LoadRoot(r3, Heap::kUndefinedValueRootIndex);
__ cmp(r2, r3);
__ b(eq, &use_global_receiver);
__ LoadRoot(r3, Heap::kNullValueRootIndex);
@@ -1431,15 +1426,10 @@
kSmiTagSize)));
__ b(ne, &push_receiver);
- // Do not transform the receiver for native (shared already in r1).
- __ ldr(r1, FieldMemOperand(r1, SharedFunctionInfo::kScriptOffset));
- __ LoadRoot(r2, Heap::kUndefinedValueRootIndex);
- __ cmp(r1, r2);
- __ b(eq, &push_receiver);
- __ ldr(r1, FieldMemOperand(r1, Script::kTypeOffset));
- __ mov(r1, Operand(r1, ASR, kSmiTagSize));
- __ cmp(r1, Operand(Script::TYPE_NATIVE));
- __ b(eq, &push_receiver);
+ // Do not transform the receiver for strict mode functions.
+ __ tst(r2, Operand(1 << (SharedFunctionInfo::kES5Native +
+ kSmiTagSize)));
+ __ b(ne, &push_receiver);
// Compute the receiver in non-strict mode.
__ tst(r0, Operand(kSmiTagMask));
@@ -1447,8 +1437,8 @@
__ LoadRoot(r1, Heap::kNullValueRootIndex);
__ cmp(r0, r1);
__ b(eq, &use_global_receiver);
- // Heap::kUndefinedValueRootIndex is already in r2.
- __ cmp(r0, r2);
+ __ LoadRoot(r1, Heap::kUndefinedValueRootIndex);
+ __ cmp(r0, r1);
__ b(eq, &use_global_receiver);
// Check if the receiver is already a JavaScript object.
=======================================
--- /branches/bleeding_edge/src/heap.cc Thu May 12 06:13:00 2011
+++ /branches/bleeding_edge/src/heap.cc Fri May 13 00:26:44 2011
@@ -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;
}
=======================================
--- /branches/bleeding_edge/src/ia32/builtins-ia32.cc Wed May 11 06:26:07
2011
+++ /branches/bleeding_edge/src/ia32/builtins-ia32.cc Fri May 13 00:26:44
2011
@@ -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_equal, &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_equal, &push_receiver);
// Compute the receiver in non-strict mode.
__ test(ebx, Immediate(kSmiTagMask));
=======================================
--- /branches/bleeding_edge/src/objects-inl.h Thu May 12 06:13:00 2011
+++ /branches/bleeding_edge/src/objects-inl.h Fri May 13 00:26:44 2011
@@ -3216,6 +3216,18 @@
kStrictModeFunction,
value));
}
+
+
+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)
=======================================
--- /branches/bleeding_edge/src/objects.h Thu May 12 06:13:00 2011
+++ /branches/bleeding_edge/src/objects.h Fri May 13 00:26:44 2011
@@ -4349,6 +4349,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();
@@ -4529,6 +4536,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
@@ -4542,18 +4550,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
=======================================
--- /branches/bleeding_edge/src/runtime.cc Thu May 12 05:48:10 2011
+++ /branches/bleeding_edge/src/runtime.cc Fri May 13 00:26:44 2011
@@ -4105,6 +4105,23 @@
attributes,
strict_mode);
}
+
+
+// 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
=======================================
--- /branches/bleeding_edge/src/runtime.h Mon May 9 01:58:57 2011
+++ /branches/bleeding_edge/src/runtime.h Fri May 13 00:26:44 2011
@@ -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) \
=======================================
--- /branches/bleeding_edge/src/v8natives.js Thu May 12 09:19:03 2011
+++ /branches/bleeding_edge/src/v8natives.js Fri May 13 00:26:44 2011
@@ -56,6 +56,7 @@
%FunctionSetName(f, key);
%FunctionRemovePrototype(f);
%SetProperty(object, key, f, attributes);
+ %SetES5Flag(f);
}
%ToFastProperties(object);
}
=======================================
--- /branches/bleeding_edge/src/x64/builtins-x64.cc Tue May 10 02:03:42 2011
+++ /branches/bleeding_edge/src/x64/builtins-x64.cc Fri May 13 00:26:44 2011
@@ -660,12 +660,9 @@
// Do not transform the receiver for natives.
// SharedFunctionInfo is already loaded into rbx.
- __ movq(rbx, FieldOperand(rbx, SharedFunctionInfo::kScriptOffset));
- __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex);
- __ j(equal, &shift_arguments);
- __ SmiCompare(FieldOperand(rbx, Script::kTypeOffset),
- Smi::FromInt(Script::TYPE_NATIVE));
- __ j(equal, &shift_arguments);
+ __ testb(FieldOperand(rbx, SharedFunctionInfo::kES5NativeByteOffset),
+ Immediate(1 << SharedFunctionInfo::kES5NativeBitWithinByte));
+ __ j(not_zero, &shift_arguments);
// Compute the receiver in non-strict mode.
__ movq(rbx, Operand(rsp, rax, times_pointer_size, 0));
@@ -832,13 +829,9 @@
__ j(not_equal, &push_receiver);
// Do not transform the receiver for natives.
- // SharedFunctionInfo is already loaded into rdx.
- __ movq(rdx, FieldOperand(rdx, SharedFunctionInfo::kScriptOffset));
- __ CompareRoot(rdx, Heap::kUndefinedValueRootIndex);
- __ j(equal, &push_receiver);
- __ SmiCompare(FieldOperand(rdx, Script::kTypeOffset),
- Smi::FromInt(Script::TYPE_NATIVE));
- __ j(equal, &push_receiver);
+ __ testb(FieldOperand(rdx, SharedFunctionInfo::kES5NativeByteOffset),
+ Immediate(1 << SharedFunctionInfo::kES5NativeBitWithinByte));
+ __ j(not_zero, &push_receiver);
// Compute the receiver in non-strict mode.
__ JumpIfSmi(rbx, &call_to_object);
=======================================
--- /branches/bleeding_edge/test/cctest/test-api.cc Wed May 11 04:53:43 2011
+++ /branches/bleeding_edge/test/cctest/test-api.cc Fri May 13 00:26:44 2011
@@ -14452,5 +14452,4 @@
context->Global()->Set(v8_str("f"), function);
TryCatch try_catch;
CompileRun("f.call(2)");
- CHECK(try_catch.HasCaught());
-}
+}
=======================================
--- /branches/bleeding_edge/test/mjsunit/regress/regress-1369.js Fri May 6
07:14:16 2011
+++ /branches/bleeding_edge/test/mjsunit/regress/regress-1369.js Fri May 13
00:26:44 2011
@@ -27,5 +27,5 @@
// Flags: --expose-gc
-assertThrows('gc.call(1)');
-assertThrows('gc.call("asdf")');
+assertDoesNotThrow('gc.call(1)');
+assertDoesNotThrow('gc.call("asdf")');
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev