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
