Revert "Load the global proxy from the context of the target function."

This reverts commit https://code.google.com/p/v8/source/detail?r=18458, since it exhibits a bug that breaks some tests.

TBR=verwaest@chromium.org
BUG=

Review URL: https://codereview.chromium.org/93863006

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@18461 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
rossberg@chromium.org 2014-01-07 09:55:25 +00:00
parent 4934263a77
commit 2879f2104c
32 changed files with 164 additions and 498 deletions

View File

@ -34,7 +34,6 @@
#include "deoptimizer.h"
#include "full-codegen.h"
#include "runtime.h"
#include "stub-cache.h"
namespace v8 {
namespace internal {
@ -1092,8 +1091,12 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
// Use the global receiver object from the called function as the
// receiver.
__ bind(&use_global_receiver);
__ ldr(r2, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX));
__ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalReceiverOffset));
const int kGlobalIndex =
Context::kHeaderSize + Context::GLOBAL_OBJECT_INDEX * kPointerSize;
__ ldr(r2, FieldMemOperand(cp, kGlobalIndex));
__ ldr(r2, FieldMemOperand(r2, GlobalObject::kNativeContextOffset));
__ ldr(r2, FieldMemOperand(r2, kGlobalIndex));
__ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalReceiverOffset));
__ bind(&patch_receiver);
__ add(r3, sp, Operand(r0, LSL, kPointerSizeLog2));
@ -1284,7 +1287,11 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
// Use the current global receiver object as the receiver.
__ bind(&use_global_receiver);
__ ldr(r0, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX));
const int kGlobalOffset =
Context::kHeaderSize + Context::GLOBAL_OBJECT_INDEX * kPointerSize;
__ ldr(r0, FieldMemOperand(cp, kGlobalOffset));
__ ldr(r0, FieldMemOperand(r0, GlobalObject::kNativeContextOffset));
__ ldr(r0, FieldMemOperand(r0, kGlobalOffset));
__ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset));
// Push the receiver.

View File

@ -3182,48 +3182,32 @@ void CallFunctionStub::Generate(MacroAssembler* masm) {
// r2 : cache cell for call target
Label slow, non_function;
// Check that the function is really a JavaScript function.
// r1: pushed function (to be verified)
__ JumpIfSmi(r1, &non_function);
// The receiver might implicitly be the global object. This is
// indicated by passing the hole as the receiver to the call
// function stub.
if (ReceiverMightBeImplicit() || ReceiverIsImplicit()) {
Label try_call, call, patch_current_context;
if (ReceiverMightBeImplicit()) {
// Get the receiver from the stack.
// function, receiver [, arguments]
__ ldr(r4, MemOperand(sp, argc_ * kPointerSize));
// Call as function is indicated with the hole.
__ CompareRoot(r4, Heap::kTheHoleValueRootIndex);
__ b(ne, &try_call);
}
if (ReceiverMightBeImplicit()) {
Label call;
// Get the receiver from the stack.
// function, receiver [, arguments]
__ ldr(r4, MemOperand(sp, argc_ * kPointerSize));
// Call as function is indicated with the hole.
__ CompareRoot(r4, Heap::kTheHoleValueRootIndex);
__ b(ne, &call);
// Patch the receiver on the stack with the global receiver object.
// Goto slow case if we do not have a function.
__ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE);
__ b(ne, &patch_current_context);
CallStubCompiler::FetchGlobalProxy(masm, r3, r1);
__ ldr(r3,
MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
__ ldr(r3, FieldMemOperand(r3, GlobalObject::kGlobalReceiverOffset));
__ str(r3, MemOperand(sp, argc_ * kPointerSize));
__ jmp(&call);
__ bind(&patch_current_context);
__ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
__ str(ip, MemOperand(sp, argc_ * kPointerSize));
__ jmp(&slow);
__ bind(&try_call);
// Get the map of the function object.
__ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE);
__ b(ne, &slow);
__ bind(&call);
} else {
// Get the map of the function object.
__ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE);
__ b(ne, &slow);
}
// Check that the function is really a JavaScript function.
// r1: pushed function (to be verified)
__ JumpIfSmi(r1, &non_function);
// Get the map of the function object.
__ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE);
__ b(ne, &slow);
if (RecordCallTarget()) {
GenerateRecordCallTarget(masm);
}
@ -3267,7 +3251,7 @@ void CallFunctionStub::Generate(MacroAssembler* masm) {
__ mov(r0, Operand(argc_ + 1, RelocInfo::NONE32));
__ mov(r2, Operand::Zero());
__ GetBuiltinEntry(r3, Builtins::CALL_FUNCTION_PROXY);
__ SetCallKind(r5, CALL_AS_FUNCTION);
__ SetCallKind(r5, CALL_AS_METHOD);
{
Handle<Code> adaptor =
masm->isolate()->builtins()->ArgumentsAdaptorTrampoline();

View File

@ -2815,12 +2815,12 @@ void FullCodeGenerator::VisitCall(Call* expr) {
{ PreservePositionScope scope(masm()->positions_recorder());
VisitForStackValue(callee);
}
// Push the hole as receiver.
// It will be correctly replaced in the call stub.
__ LoadRoot(r1, Heap::kTheHoleValueRootIndex);
// Load global receiver object.
__ ldr(r1, GlobalObjectOperand());
__ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
__ push(r1);
// Emit function call.
EmitCallWithStub(expr, RECEIVER_IS_IMPLICIT);
EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS);
}
#ifdef DEBUG

View File

@ -491,7 +491,7 @@ void CallICBase::GenerateMiss(MacroAssembler* masm,
// Patch the receiver on the stack.
__ bind(&global);
CallStubCompiler::FetchGlobalProxy(masm, r2, r1);
__ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalReceiverOffset));
__ str(r2, MemOperand(sp, argc * kPointerSize));
__ bind(&invoke);
}

View File

@ -3491,8 +3491,11 @@ void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) {
__ b(&result_in_receiver);
__ bind(&global_object);
CallStubCompiler::FetchGlobalProxy(masm(), receiver, function);
__ ldr(result, MemOperand(fp, StandardFrameConstants::kContextOffset));
__ ldr(result, ContextOperand(result, Context::GLOBAL_OBJECT_INDEX));
__ ldr(result,
FieldMemOperand(result, JSGlobalObject::kGlobalReceiverOffset));
if (result.is(receiver)) {
__ bind(&result_in_receiver);
} else {
@ -3990,10 +3993,7 @@ void LCodeGen::DoCallFunction(LCallFunction* instr) {
ASSERT(ToRegister(instr->result()).is(r0));
int arity = instr->arity();
CallFunctionFlags flags =
instr->hydrogen()->IsContextualCall() ?
RECEIVER_IS_IMPLICIT : NO_CALL_FUNCTION_FLAGS;
CallFunctionStub stub(arity, flags);
CallFunctionStub stub(arity, NO_CALL_FUNCTION_FLAGS);
if (instr->hydrogen()->IsTailCall()) {
if (NeedsEagerFrame()) __ mov(sp, fp);
__ Jump(stub.GetCode(isolate()), RelocInfo::CODE_TARGET);

View File

@ -2341,23 +2341,11 @@ void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) {
}
void CallStubCompiler::PatchGlobalProxy(Handle<Object> object,
Handle<JSFunction> function) {
void CallStubCompiler::PatchGlobalProxy(Handle<Object> object) {
if (object->IsGlobalObject()) {
const int argc = arguments().immediate();
const int receiver_offset = argc * kPointerSize;
__ Move(r3, handle(function->context()->global_proxy()));
__ str(r3, MemOperand(sp, receiver_offset));
}
}
void CallStubCompiler::PatchGlobalProxy(Handle<Object> object,
Register function) {
if (object->IsGlobalObject()) {
FetchGlobalProxy(masm(), r3, function);
const int argc = arguments().immediate();
const int receiver_offset = argc * kPointerSize;
__ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset));
__ str(r3, MemOperand(sp, receiver_offset));
}
}
@ -2456,7 +2444,7 @@ void CallStubCompiler::GenerateJumpFunction(Handle<Object> object,
ASSERT(function.is(r1));
// Check that the function really is a function.
GenerateFunctionCheck(function, r3, miss);
PatchGlobalProxy(object, function);
PatchGlobalProxy(object);
// Invoke the function.
__ InvokeFunction(r1, arguments(), JUMP_FUNCTION,
@ -2574,15 +2562,6 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback(
#define __ ACCESS_MASM(masm)
void CallStubCompiler::FetchGlobalProxy(MacroAssembler* masm,
Register target,
Register function) {
__ ldr(target, FieldMemOperand(function, JSFunction::kContextOffset));
__ ldr(target, ContextOperand(target, Context::GLOBAL_OBJECT_INDEX));
__ ldr(target, FieldMemOperand(target, GlobalObject::kGlobalReceiverOffset));
}
void StoreStubCompiler::GenerateStoreViaSetter(
MacroAssembler* masm,
Handle<JSFunction> setter) {

View File

@ -1669,8 +1669,6 @@ bool Genesis::InstallNatives() {
builtins->set_native_context(*native_context());
builtins->set_global_context(*native_context());
builtins->set_global_receiver(*builtins);
builtins->set_global_receiver(native_context()->global_proxy());
// Set up the 'global' properties of the builtins object. The
// 'global' property that refers to the global object is the only
@ -1684,11 +1682,6 @@ bool Genesis::InstallNatives() {
CHECK_NOT_EMPTY_HANDLE(isolate(),
JSObject::SetLocalPropertyIgnoreAttributes(
builtins, global_string, global_obj, attributes));
Handle<String> builtins_string =
factory()->InternalizeOneByteString(STATIC_ASCII_VECTOR("builtins"));
CHECK_NOT_EMPTY_HANDLE(isolate(),
JSObject::SetLocalPropertyIgnoreAttributes(
builtins, builtins_string, builtins, attributes));
// Set up the reference from the global object to the builtins object.
JSGlobalObject::cast(native_context()->global_object())->
@ -2588,8 +2581,6 @@ Genesis::Genesis(Isolate* isolate,
HookUpGlobalProxy(inner_global, global_proxy);
HookUpInnerGlobal(inner_global);
native_context()->builtins()->set_global_receiver(
native_context()->global_proxy());
if (!ConfigureGlobalObjects(global_template)) return;
} else {

View File

@ -1550,8 +1550,8 @@ class CallFunctionStub: public PlatformCodeStub {
virtual void PrintName(StringStream* stream);
// Minor key encoding in 32 bits with Bitfield <Type, shift, size>.
class FlagBits: public BitField<CallFunctionFlags, 0, 3> {};
class ArgcBits: public BitField<unsigned, 3, 32 - 3> {};
class FlagBits: public BitField<CallFunctionFlags, 0, 2> {};
class ArgcBits: public BitField<unsigned, 2, 32 - 2> {};
Major MajorKey() { return CallFunction; }
int MinorKey() {
@ -1563,10 +1563,6 @@ class CallFunctionStub: public PlatformCodeStub {
return (flags_ & RECEIVER_MIGHT_BE_IMPLICIT) != 0;
}
bool ReceiverIsImplicit() {
return (flags_ & RECEIVER_IS_IMPLICIT) != 0;
}
bool RecordCallTarget() {
return (flags_ & RECORD_CALL_TARGET) != 0;
}

View File

@ -2414,8 +2414,7 @@ class HCallNamed V8_FINAL : public HUnaryCall {
enum CallMode {
NORMAL_CALL,
TAIL_CALL,
NORMAL_CONTEXTUAL_CALL
TAIL_CALL
};
@ -2426,7 +2425,7 @@ class HCallFunction V8_FINAL : public HBinaryCall {
HCallFunction, HValue*, int, CallMode);
bool IsTailCall() const { return call_mode_ == TAIL_CALL; }
bool IsContextualCall() const { return call_mode_ == NORMAL_CONTEXTUAL_CALL; }
HValue* context() { return first(); }
HValue* function() { return second(); }

View File

@ -7618,27 +7618,6 @@ bool HOptimizedGraphBuilder::TryCallApply(Call* expr) {
}
void HOptimizedGraphBuilder::InstallGlobalReceiverInExpressionStack(
int receiver_index,
Handle<JSFunction> function) {
// TODO(dcarney): Fix deserializer to be able to hookup the global receiver
// and object during deserialization and embed the global receiver here
// directly.
// Install global receiver on stack.
HValue* function_constant = Add<HConstant>(function);
HValue* context = Add<HLoadNamedField>(
function_constant,
HObjectAccess::ForJSObjectOffset(JSFunction::kContextOffset));
HValue* global_object = Add<HLoadNamedField>(
context,
HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
HValue* global_receiver = Add<HLoadNamedField>(
global_object,
HObjectAccess::ForJSObjectOffset(GlobalObject::kGlobalReceiverOffset));
environment()->SetExpressionStackAt(receiver_index, global_receiver);
}
void HOptimizedGraphBuilder::VisitCall(Call* expr) {
ASSERT(!HasStackOverflow());
ASSERT(current_block() != NULL);
@ -7759,11 +7738,13 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) {
HValue* function = Pop();
Add<HCheckValue>(function, expr->target());
// Install global receiver on stack.
// Replace the global object with the global receiver.
HGlobalReceiver* global_receiver = Add<HGlobalReceiver>(global_object);
// Index of the receiver from the top of the expression stack.
const int receiver_index = argument_count - 1;
ASSERT(environment()->ExpressionStackAt(receiver_index)->
IsGlobalObject());
InstallGlobalReceiverInExpressionStack(receiver_index, expr->target());
environment()->SetExpressionStackAt(receiver_index, global_receiver);
if (TryInlineBuiltinFunctionCall(expr, false)) { // Nothing to drop.
if (FLAG_trace_inlining) {
@ -7780,12 +7761,9 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) {
}
if (CallStubCompiler::HasCustomCallGenerator(expr->target())) {
// We're about to install a contextual IC, which expects the global
// object as receiver rather than the global proxy.
environment()->SetExpressionStackAt(receiver_index, global_object);
// When the target has a custom call IC generator, use the IC,
// because it is likely to generate better code.
call = PreProcessCall(New<HCallGlobal>(var->name(), argument_count));
call = PreProcessCall(New<HCallNamed>(var->name(), argument_count));
} else {
call = PreProcessCall(New<HCallKnownGlobal>(
expr->target(), argument_count));
@ -7810,12 +7788,6 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) {
CHECK_ALIVE(VisitExpressions(expr->arguments()));
Add<HCheckValue>(function, expr->target());
// Install global receiver on stack.
const int receiver_index = argument_count - 1;
ASSERT(environment()->ExpressionStackAt(receiver_index)->
IsGlobalReceiver());
InstallGlobalReceiverInExpressionStack(receiver_index, expr->target());
if (TryInlineBuiltinFunctionCall(expr, true)) { // Drop the function.
if (FLAG_trace_inlining) {
PrintF("Inlining builtin ");
@ -7836,11 +7808,12 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) {
} else {
CHECK_ALIVE(VisitForValue(expr->expression()));
HValue* function = Top();
HValue* receiver = graph()->GetConstantHole();
HGlobalObject* global_object = Add<HGlobalObject>();
HGlobalReceiver* receiver = Add<HGlobalReceiver>(global_object);
Push(Add<HPushArgument>(receiver));
CHECK_ALIVE(VisitArgumentList(expr->arguments()));
call = New<HCallFunction>(
function, argument_count, NORMAL_CONTEXTUAL_CALL);
call = New<HCallFunction>(function, argument_count);
Drop(argument_count + 1);
}
}

View File

@ -2502,9 +2502,6 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
HValue* receiver,
Handle<Map> receiver_map);
void InstallGlobalReceiverInExpressionStack(int index,
Handle<JSFunction> function);
// The translation state of the currently-being-translated function.
FunctionState* function_state_;

View File

@ -32,7 +32,6 @@
#include "codegen.h"
#include "deoptimizer.h"
#include "full-codegen.h"
#include "stub-cache.h"
namespace v8 {
namespace internal {
@ -784,7 +783,12 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
// Use the global receiver object from the called function as the
// receiver.
__ bind(&use_global_receiver);
CallStubCompiler::FetchGlobalProxy(masm, ebx, edi);
const int kGlobalIndex =
Context::kHeaderSize + Context::GLOBAL_OBJECT_INDEX * kPointerSize;
__ mov(ebx, FieldOperand(esi, kGlobalIndex));
__ mov(ebx, FieldOperand(ebx, GlobalObject::kNativeContextOffset));
__ mov(ebx, FieldOperand(ebx, kGlobalIndex));
__ mov(ebx, FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset));
__ bind(&patch_receiver);
__ mov(Operand(esp, eax, times_4, 0), ebx);
@ -957,7 +961,12 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
// Use the current global receiver object as the receiver.
__ bind(&use_global_receiver);
CallStubCompiler::FetchGlobalProxy(masm, ebx, edi);
const int kGlobalOffset =
Context::kHeaderSize + Context::GLOBAL_OBJECT_INDEX * kPointerSize;
__ mov(ebx, FieldOperand(esi, kGlobalOffset));
__ mov(ebx, FieldOperand(ebx, GlobalObject::kNativeContextOffset));
__ mov(ebx, FieldOperand(ebx, kGlobalOffset));
__ mov(ebx, FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset));
// Push the receiver.
__ bind(&push_receiver);

View File

@ -2517,47 +2517,30 @@ void CallFunctionStub::Generate(MacroAssembler* masm) {
Isolate* isolate = masm->isolate();
Label slow, non_function;
// Check that the function really is a JavaScript function.
__ JumpIfSmi(edi, &non_function);
// The receiver might implicitly be the global object. This is
// indicated by passing the hole as the receiver to the call
// function stub.
if (ReceiverMightBeImplicit() || ReceiverIsImplicit()) {
Label try_call, call, patch_current_context;
if (ReceiverMightBeImplicit()) {
// Get the receiver from the stack.
// +1 ~ return address
__ mov(eax, Operand(esp, (argc_ + 1) * kPointerSize));
// Call as function is indicated with the hole.
__ cmp(eax, isolate->factory()->the_hole_value());
__ j(not_equal, &try_call, Label::kNear);
}
if (ReceiverMightBeImplicit()) {
Label receiver_ok;
// Get the receiver from the stack.
// +1 ~ return address
__ mov(eax, Operand(esp, (argc_ + 1) * kPointerSize));
// Call as function is indicated with the hole.
__ cmp(eax, isolate->factory()->the_hole_value());
__ j(not_equal, &receiver_ok, Label::kNear);
// Patch the receiver on the stack with the global receiver object.
// Goto slow case if we do not have a function.
__ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx);
__ j(not_equal, &patch_current_context);
CallStubCompiler::FetchGlobalProxy(masm, ecx, edi);
__ mov(ecx, GlobalObjectOperand());
__ mov(ecx, FieldOperand(ecx, GlobalObject::kGlobalReceiverOffset));
__ mov(Operand(esp, (argc_ + 1) * kPointerSize), ecx);
__ jmp(&call, Label::kNear);
__ bind(&patch_current_context);
__ mov(edx, isolate->factory()->undefined_value());
__ mov(Operand(esp, (argc_ + 1) * kPointerSize), edx);
__ jmp(&slow);
__ bind(&try_call);
// Goto slow case if we do not have a function.
__ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx);
__ j(not_equal, &slow);
__ bind(&call);
} else {
// Goto slow case if we do not have a function.
__ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx);
__ j(not_equal, &slow);
__ bind(&receiver_ok);
}
// Check that the function really is a JavaScript function.
__ JumpIfSmi(edi, &non_function);
// Goto slow case if we do not have a function.
__ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx);
__ j(not_equal, &slow);
if (RecordCallTarget()) {
GenerateRecordCallTarget(masm);
}

View File

@ -2769,11 +2769,11 @@ void FullCodeGenerator::VisitCall(Call* expr) {
{ PreservePositionScope scope(masm()->positions_recorder());
VisitForStackValue(callee);
}
// Push the hole as receiver.
// It will be correctly replaced in the call stub.
__ push(Immediate(isolate()->factory()->the_hole_value()));
// Load global receiver object.
__ mov(ebx, GlobalObjectOperand());
__ push(FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset));
// Emit function call.
EmitCallWithStub(expr, RECEIVER_IS_IMPLICIT);
EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS);
}
#ifdef DEBUG

View File

@ -1112,9 +1112,8 @@ void CallICBase::GenerateMiss(MacroAssembler* masm,
// Patch the receiver on the stack.
__ bind(&global);
CallStubCompiler::FetchGlobalProxy(masm, edx, edi);
__ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
__ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
__ bind(&invoke);
}

View File

@ -3675,7 +3675,10 @@ void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) {
// TODO(kmillikin): We have a hydrogen value for the global object. See
// if it's better to use it than to explicitly fetch it from the context
// here.
CallStubCompiler::FetchGlobalProxy(masm(), receiver, function);
__ mov(receiver, Operand(ebp, StandardFrameConstants::kContextOffset));
__ mov(receiver, ContextOperand(receiver, Context::GLOBAL_OBJECT_INDEX));
__ mov(receiver,
FieldOperand(receiver, JSGlobalObject::kGlobalReceiverOffset));
__ bind(&receiver_ok);
}
@ -4242,10 +4245,7 @@ void LCodeGen::DoCallFunction(LCallFunction* instr) {
ASSERT(ToRegister(instr->result()).is(eax));
int arity = instr->arity();
CallFunctionFlags flags =
instr->hydrogen()->IsContextualCall() ?
RECEIVER_IS_IMPLICIT : NO_CALL_FUNCTION_FLAGS;
CallFunctionStub stub(arity, flags);
CallFunctionStub stub(arity, NO_CALL_FUNCTION_FLAGS);
if (instr->hydrogen()->IsTailCall()) {
if (NeedsEagerFrame()) __ leave();
__ jmp(stub.GetCode(isolate()), RelocInfo::CODE_TARGET);

View File

@ -1166,7 +1166,7 @@ LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal(
LInstruction* LChunkBuilder::DoWrapReceiver(HWrapReceiver* instr) {
LOperand* receiver = UseRegister(instr->receiver());
LOperand* function = UseRegister(instr->function());
LOperand* function = UseRegisterAtStart(instr->function());
LOperand* temp = TempRegister();
LWrapReceiver* result =
new(zone()) LWrapReceiver(receiver, function, temp);

View File

@ -2468,23 +2468,11 @@ void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) {
}
void CallStubCompiler::PatchGlobalProxy(Handle<Object> object,
Handle<JSFunction> function) {
void CallStubCompiler::PatchGlobalProxy(Handle<Object> object) {
if (object->IsGlobalObject()) {
const int argc = arguments().immediate();
const int receiver_offset = (argc + 1) * kPointerSize;
__ LoadHeapObject(edx, handle(function->context()->global_proxy()));
__ mov(Operand(esp, receiver_offset), edx);
}
}
void CallStubCompiler::PatchGlobalProxy(Handle<Object> object,
Register function) {
if (object->IsGlobalObject()) {
FetchGlobalProxy(masm(), edx, function);
const int argc = arguments().immediate();
const int receiver_offset = (argc + 1) * kPointerSize;
__ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
__ mov(Operand(esp, receiver_offset), edx);
}
}
@ -2578,7 +2566,7 @@ void CallStubCompiler::GenerateJumpFunction(Handle<Object> object,
GenerateFunctionCheck(function, ebx, miss);
if (!function.is(edi)) __ mov(edi, function);
PatchGlobalProxy(object, function);
PatchGlobalProxy(object);
// Invoke the function.
__ InvokeFunction(edi, arguments(), JUMP_FUNCTION,
@ -2693,15 +2681,6 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback(
#define __ ACCESS_MASM(masm)
void CallStubCompiler::FetchGlobalProxy(MacroAssembler* masm,
Register target,
Register function) {
__ mov(target, FieldOperand(function, JSFunction::kContextOffset));
__ mov(target, ContextOperand(target, Context::GLOBAL_OBJECT_INDEX));
__ mov(target, FieldOperand(target, GlobalObject::kGlobalReceiverOffset));
}
void StoreStubCompiler::GenerateStoreViaSetter(
MacroAssembler* masm,
Handle<JSFunction> setter) {

View File

@ -9252,7 +9252,7 @@ static ObjectPair LoadContextSlotHelper(Arguments args,
// GetProperty below can cause GC.
Handle<Object> receiver_handle(
object->IsGlobalObject()
? Object::cast(isolate->heap()->the_hole_value())
? GlobalObject::cast(*object)->global_receiver()
: object->IsJSProxy() ? static_cast<Object*>(*object)
: ComputeReceiverForNonGlobal(isolate, JSObject::cast(*object)),
isolate);

View File

@ -48,6 +48,7 @@ var $Number = global.Number;
var $Function = global.Function;
var $Boolean = global.Boolean;
var $NaN = %GetRootNaN();
var builtins = this;
// ECMA-262 Section 11.9.3.
function EQUALS(y) {

View File

@ -1155,7 +1155,7 @@ void CallStubCompiler::GenerateJumpFunctionIgnoreReceiver(
void CallStubCompiler::GenerateJumpFunction(Handle<Object> object,
Handle<JSFunction> function) {
PatchGlobalProxy(object, function);
PatchGlobalProxy(object);
GenerateJumpFunctionIgnoreReceiver(function);
}
@ -1163,7 +1163,7 @@ void CallStubCompiler::GenerateJumpFunction(Handle<Object> object,
void CallStubCompiler::GenerateJumpFunction(Handle<Object> object,
Register actual_closure,
Handle<JSFunction> function) {
PatchGlobalProxy(object, function);
PatchGlobalProxy(object);
ParameterCount expected(function);
__ InvokeFunction(actual_closure, expected, arguments(),
JUMP_FUNCTION, NullCallWrapper(), call_kind());

View File

@ -912,11 +912,7 @@ class CallStubCompiler: public StubCompiler {
// Patch the global proxy over the global object if the global object is the
// receiver.
static void FetchGlobalProxy(MacroAssembler* masm,
Register target,
Register function);
void PatchGlobalProxy(Handle<Object> object, Register function);
void PatchGlobalProxy(Handle<Object> object, Handle<JSFunction> function);
void PatchGlobalProxy(Handle<Object> object);
// Returns the register containing the holder of |name|.
Register HandlerFrontendHeader(Handle<Object> object,

View File

@ -293,10 +293,8 @@ enum CallFunctionFlags {
// Receiver might implicitly be the global objects. If it is, the
// hole is passed to the call function stub.
RECEIVER_MIGHT_BE_IMPLICIT = 1 << 0,
// Receiver is implicit and the hole has been passed to the stub.
RECEIVER_IS_IMPLICIT = 1 << 1,
// The call target is cached in the instruction stream.
RECORD_CALL_TARGET = 1 << 2
RECORD_CALL_TARGET = 1 << 1
};

View File

@ -32,7 +32,6 @@
#include "codegen.h"
#include "deoptimizer.h"
#include "full-codegen.h"
#include "stub-cache.h"
namespace v8 {
namespace internal {
@ -847,7 +846,12 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
// Use the global receiver object from the called function as the
// receiver.
__ bind(&use_global_receiver);
CallStubCompiler::FetchGlobalProxy(masm, rbx, rdi);
const int kGlobalIndex =
Context::kHeaderSize + Context::GLOBAL_OBJECT_INDEX * kPointerSize;
__ movq(rbx, FieldOperand(rsi, kGlobalIndex));
__ movq(rbx, FieldOperand(rbx, GlobalObject::kNativeContextOffset));
__ movq(rbx, FieldOperand(rbx, kGlobalIndex));
__ movq(rbx, FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset));
__ bind(&patch_receiver);
__ movq(args.GetArgumentOperand(1), rbx);
@ -1027,7 +1031,13 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
// Use the current global receiver object as the receiver.
__ bind(&use_global_receiver);
CallStubCompiler::FetchGlobalProxy(masm, rbx, rdi);
const int kGlobalOffset =
Context::kHeaderSize + Context::GLOBAL_OBJECT_INDEX * kPointerSize;
__ movq(rbx, FieldOperand(rsi, kGlobalOffset));
__ movq(rbx, FieldOperand(rbx, GlobalObject::kNativeContextOffset));
__ movq(rbx, FieldOperand(rbx, kGlobalOffset));
__ movq(rbx, FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset));
// Push the receiver.
__ bind(&push_receiver);
__ push(rbx);

View File

@ -2350,46 +2350,29 @@ void CallFunctionStub::Generate(MacroAssembler* masm) {
Label slow, non_function;
StackArgumentsAccessor args(rsp, argc_);
// Check that the function really is a JavaScript function.
__ JumpIfSmi(rdi, &non_function);
// The receiver might implicitly be the global object. This is
// indicated by passing the hole as the receiver to the call
// function stub.
if (ReceiverMightBeImplicit() || ReceiverIsImplicit()) {
Label try_call, call, patch_current_context;
if (ReceiverMightBeImplicit()) {
// Get the receiver from the stack.
__ movq(rax, args.GetReceiverOperand());
// Call as function is indicated with the hole.
__ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
__ j(not_equal, &try_call, Label::kNear);
}
if (ReceiverMightBeImplicit()) {
Label call;
// Get the receiver from the stack.
__ movq(rax, args.GetReceiverOperand());
// Call as function is indicated with the hole.
__ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
__ j(not_equal, &call, Label::kNear);
// Patch the receiver on the stack with the global receiver object.
// Goto slow case if we do not have a function.
__ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx);
__ j(not_equal, &patch_current_context);
CallStubCompiler::FetchGlobalProxy(masm, rcx, rdi);
__ movq(rcx, GlobalObjectOperand());
__ movq(rcx, FieldOperand(rcx, GlobalObject::kGlobalReceiverOffset));
__ movq(args.GetReceiverOperand(), rcx);
__ jmp(&call, Label::kNear);
__ bind(&patch_current_context);
__ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex);
__ movq(args.GetReceiverOperand(), kScratchRegister);
__ jmp(&slow);
__ bind(&try_call);
// Goto slow case if we do not have a function.
__ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx);
__ j(not_equal, &slow);
__ bind(&call);
} else {
// Goto slow case if we do not have a function.
__ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx);
__ j(not_equal, &slow);
}
// Check that the function really is a JavaScript function.
__ JumpIfSmi(rdi, &non_function);
// Goto slow case if we do not have a function.
__ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx);
__ j(not_equal, &slow);
if (RecordCallTarget()) {
GenerateRecordCallTarget(masm);
}
@ -2431,7 +2414,7 @@ void CallFunctionStub::Generate(MacroAssembler* masm) {
__ PushReturnAddressFrom(rcx);
__ Set(rax, argc_ + 1);
__ Set(rbx, 0);
__ SetCallKind(rcx, CALL_AS_FUNCTION);
__ SetCallKind(rcx, CALL_AS_METHOD);
__ GetBuiltinEntry(rdx, Builtins::CALL_FUNCTION_PROXY);
{
Handle<Code> adaptor =

View File

@ -2746,11 +2746,11 @@ void FullCodeGenerator::VisitCall(Call* expr) {
{ PreservePositionScope scope(masm()->positions_recorder());
VisitForStackValue(callee);
}
// Push the hole as receiver.
// It will be correctly replaced in the call stub.
__ PushRoot(Heap::kTheHoleValueRootIndex);
// Load global receiver object.
__ movq(rbx, GlobalObjectOperand());
__ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset));
// Emit function call.
EmitCallWithStub(expr, RECEIVER_IS_IMPLICIT);
EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS);
}
#ifdef DEBUG

View File

@ -998,7 +998,7 @@ void CallICBase::GenerateMiss(MacroAssembler* masm,
// Patch the receiver on the stack.
__ bind(&global);
CallStubCompiler::FetchGlobalProxy(masm, rdx, rdi);
__ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
__ movq(args.GetReceiverOperand(), rdx);
__ bind(&invoke);
}

View File

@ -3250,7 +3250,10 @@ void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) {
// TODO(kmillikin): We have a hydrogen value for the global object. See
// if it's better to use it than to explicitly fetch it from the context
// here.
CallStubCompiler::FetchGlobalProxy(masm(), receiver, function);
__ movq(receiver, Operand(rbp, StandardFrameConstants::kContextOffset));
__ movq(receiver, ContextOperand(receiver, Context::GLOBAL_OBJECT_INDEX));
__ movq(receiver,
FieldOperand(receiver, JSGlobalObject::kGlobalReceiverOffset));
__ bind(&receiver_ok);
}
@ -3815,10 +3818,7 @@ void LCodeGen::DoCallFunction(LCallFunction* instr) {
ASSERT(ToRegister(instr->result()).is(rax));
int arity = instr->arity();
CallFunctionFlags flags =
instr->hydrogen()->IsContextualCall() ?
RECEIVER_IS_IMPLICIT : NO_CALL_FUNCTION_FLAGS;
CallFunctionStub stub(arity, flags);
CallFunctionStub stub(arity, NO_CALL_FUNCTION_FLAGS);
if (instr->hydrogen()->IsTailCall()) {
if (NeedsEagerFrame()) __ leave();
__ jmp(stub.GetCode(isolate()), RelocInfo::CODE_TARGET);

View File

@ -2378,21 +2378,10 @@ void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) {
}
void CallStubCompiler::PatchGlobalProxy(Handle<Object> object,
Handle<JSFunction> function) {
void CallStubCompiler::PatchGlobalProxy(Handle<Object> object) {
if (object->IsGlobalObject()) {
StackArgumentsAccessor args(rsp, arguments());
__ MoveHeapObject(rdx, handle(function->context()->global_proxy()));
__ movq(args.GetReceiverOperand(), rdx);
}
}
void CallStubCompiler::PatchGlobalProxy(Handle<Object> object,
Register function) {
if (object->IsGlobalObject()) {
FetchGlobalProxy(masm(), rdx, function);
StackArgumentsAccessor args(rsp, arguments().immediate());
__ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
__ movq(args.GetReceiverOperand(), rdx);
}
}
@ -2486,7 +2475,7 @@ void CallStubCompiler::GenerateJumpFunction(Handle<Object> object,
GenerateFunctionCheck(function, rbx, miss);
if (!function.is(rdi)) __ movq(rdi, function);
PatchGlobalProxy(object, function);
PatchGlobalProxy(object);
// Invoke the function.
__ InvokeFunction(rdi, arguments(), JUMP_FUNCTION,
@ -2599,15 +2588,6 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback(
#define __ ACCESS_MASM(masm)
void CallStubCompiler::FetchGlobalProxy(MacroAssembler* masm,
Register target,
Register function) {
__ movq(target, FieldOperand(function, JSFunction::kContextOffset));
__ movq(target, ContextOperand(target, Context::GLOBAL_OBJECT_INDEX));
__ movq(target, FieldOperand(target, GlobalObject::kGlobalReceiverOffset));
}
void StoreStubCompiler::GenerateStoreViaSetter(
MacroAssembler* masm,
Handle<JSFunction> setter) {

View File

@ -8704,23 +8704,12 @@ TEST(DetachGlobal) {
}
void GetThisX(const v8::FunctionCallbackInfo<v8::Value>& info) {
info.GetReturnValue().Set(
info.GetIsolate()->GetCurrentContext()->Global()->Get(v8_str("x")));
}
TEST(DetachedAccesses) {
LocalContext env1;
v8::HandleScope scope(env1->GetIsolate());
// Create second environment.
Local<ObjectTemplate> inner_global_template =
FunctionTemplate::New(env1->GetIsolate())->InstanceTemplate();
inner_global_template ->SetAccessorProperty(
v8_str("this_x"), FunctionTemplate::New(env1->GetIsolate(), GetThisX));
v8::Local<Context> env2 =
Context::New(env1->GetIsolate(), NULL, inner_global_template);
v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
Local<Value> foo = v8_str("foo");
@ -8728,21 +8717,15 @@ TEST(DetachedAccesses) {
env1->SetSecurityToken(foo);
env2->SetSecurityToken(foo);
env1->Global()->Set(v8_str("x"), v8_str("env1_x"));
{
v8::Context::Scope scope(env2);
env2->Global()->Set(v8_str("x"), v8_str("env2_x"));
CompileRun(
"function bound_x() { return x; }"
"function get_x() { return this.x; }"
"function get_x_w() { return (function() {return this.x;})(); }");
env1->Global()->Set(v8_str("bound_x"), CompileRun("bound_x"));
"var x = 'x';"
"function get_x() { return this.x; }"
"function get_x_w() { return get_x(); }"
"");
env1->Global()->Set(v8_str("get_x"), CompileRun("get_x"));
env1->Global()->Set(v8_str("get_x_w"), CompileRun("get_x_w"));
env1->Global()->Set(
v8_str("this_x"),
CompileRun("Object.getOwnPropertyDescriptor(this, 'this_x').get"));
}
Local<Object> env2_global = env2->Global();
@ -8750,14 +8733,10 @@ TEST(DetachedAccesses) {
env2->DetachGlobal();
Local<Value> result;
result = CompileRun("bound_x()");
CHECK_EQ(v8_str("env2_x"), result);
result = CompileRun("get_x()");
CHECK(result->IsUndefined());
result = CompileRun("get_x_w()");
CHECK(result->IsUndefined());
result = CompileRun("this_x()");
CHECK_EQ(v8_str("env2_x"), result);
// Reattach env2's proxy
env2 = Context::New(env1->GetIsolate(),
@ -8767,62 +8746,13 @@ TEST(DetachedAccesses) {
env2->SetSecurityToken(foo);
{
v8::Context::Scope scope(env2);
env2->Global()->Set(v8_str("x"), v8_str("env3_x"));
env2->Global()->Set(v8_str("env1"), env1->Global());
result = CompileRun(
"results = [];"
"for (var i = 0; i < 4; i++ ) {"
" results.push(env1.bound_x());"
" results.push(env1.get_x());"
" results.push(env1.get_x_w());"
" results.push(env1.this_x());"
"}"
"results");
Local<v8::Array> results = Local<v8::Array>::Cast(result);
CHECK_EQ(16, results->Length());
for (int i = 0; i < 16; i += 4) {
CHECK_EQ(v8_str("env2_x"), results->Get(i + 0));
CHECK_EQ(v8_str("env1_x"), results->Get(i + 1));
CHECK_EQ(v8_str("env3_x"), results->Get(i + 2));
CHECK_EQ(v8_str("env2_x"), results->Get(i + 3));
}
CompileRun("var x = 'x2';");
}
result = CompileRun(
"results = [];"
"for (var i = 0; i < 4; i++ ) {"
" results.push(bound_x());"
" results.push(get_x());"
" results.push(get_x_w());"
" results.push(this_x());"
"}"
"results");
Local<v8::Array> results = Local<v8::Array>::Cast(result);
CHECK_EQ(16, results->Length());
for (int i = 0; i < 16; i += 4) {
CHECK_EQ(v8_str("env2_x"), results->Get(i + 0));
CHECK_EQ(v8_str("env3_x"), results->Get(i + 1));
CHECK_EQ(v8_str("env3_x"), results->Get(i + 2));
CHECK_EQ(v8_str("env2_x"), results->Get(i + 3));
}
result = CompileRun(
"results = [];"
"for (var i = 0; i < 4; i++ ) {"
" results.push(this.bound_x());"
" results.push(this.get_x());"
" results.push(this.get_x_w());"
" results.push(this.this_x());"
"}"
"results");
results = Local<v8::Array>::Cast(result);
CHECK_EQ(16, results->Length());
for (int i = 0; i < 16; i += 4) {
CHECK_EQ(v8_str("env2_x"), results->Get(i + 0));
CHECK_EQ(v8_str("env1_x"), results->Get(i + 1));
CHECK_EQ(v8_str("env3_x"), results->Get(i + 2));
CHECK_EQ(v8_str("env2_x"), results->Get(i + 3));
}
result = CompileRun("get_x()");
CHECK(result->IsUndefined());
result = CompileRun("get_x_w()");
CHECK_EQ(v8_str("x2"), result);
}
@ -20180,10 +20110,11 @@ THREADED_TEST(ForeignFunctionReceiver) {
CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[1]")));
CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[3]")));
// TODO(1547): Make the following also return "i".
// Calling with environment record as base.
TestReceiver(i, foreign_context->Global(), "func()");
TestReceiver(o, context->Global(), "func()");
// Calling with no base.
TestReceiver(i, foreign_context->Global(), "(1,func)()");
TestReceiver(o, context->Global(), "(1,func)()");
}

View File

@ -1,103 +0,0 @@
// Copyright 2013 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.
var realms = [Realm.current(), Realm.create()];
globals = [Realm.global(0), Realm.global(1)];
Realm.shared = {}
function install(name, value) {
Realm.shared[name] = value;
for (i in realms) {
Realm.eval(realms[i], name + " = Realm.shared['" + name + "'];");
}
}
install('return_this', function() { return this; });
install('return_this_strict', function () { 'use strict'; return this; });
// test behaviour of 'with' scope
for (i in realms) {
Realm.shared.results = [];
// in the second case, 'this' is found in the with scope,
// so the receiver is 'this'
Realm.eval(realms[i]," \
with('irrelevant') { \
Realm.shared.results.push(return_this()); \
Realm.shared.results.push(return_this_strict()); \
} \
with(this) { \
Realm.shared.results.push(return_this()); \
Realm.shared.results.push(return_this_strict()); \
} \
");
assertSame(globals[0], Realm.shared.results[0]);
assertSame(undefined, Realm.shared.results[1]);
assertSame(globals[i], Realm.shared.results[2]);
assertSame(globals[i], Realm.shared.results[3]);
}
// test 'apply' and 'call'
for (i in realms) {
// 'apply' without a receiver is a contextual call
assertSame(globals[0], Realm.eval(realms[i],'return_this.apply()')) ;
assertSame(undefined, Realm.eval(realms[i],'return_this_strict.apply()'));
assertSame(globals[0], Realm.eval(realms[i],'return_this.apply(null)')) ;
assertSame(null, Realm.eval(realms[i],'return_this_strict.apply(null)'));
// 'call' without a receiver is a contextual call
assertSame(globals[0], Realm.eval(realms[i],'return_this.call()')) ;
assertSame(undefined, Realm.eval(realms[i],'return_this_strict.call()'));
assertSame(globals[0], Realm.eval(realms[i],'return_this.call(null)')) ;
assertSame(null, Realm.eval(realms[i],'return_this_strict.call(null)'));
}
// test ics
for (var i = 0; i < 4; i++) {
assertSame(globals[0], return_this());
assertSame(undefined, return_this_strict());
}
// BUG(1547)
Realm.eval(realms[0], "var name = 'o'");
Realm.eval(realms[1], "var name = 'i'");
install('f', function() { return this.name; });
install('g', function() { "use strict"; return this ? this.name : "u"; });
for (i in realms) {
result = Realm.eval(realms[i], " \
(function(){return f();})() + \
(function(){return (1,f)();})() + \
(function(){'use strict'; return f();})() + \
(function(){'use strict'; return (1,f)();})() + \
(function(){return g();})() + \
(function(){return (1,g)();})() + \
(function(){'use strict'; return g();})() + \
(function(){'use strict'; return (1,g)();})(); \
");
assertSame("oooouuuu", result);
}

View File

@ -53,7 +53,8 @@ var receiver
function TestCall(isStrict, callTrap) {
assertEquals(42, callTrap(5, 37))
assertSame(isStrict ? undefined : global_object, receiver)
// TODO(rossberg): strict mode seems to be broken on x64...
// assertSame(isStrict ? undefined : global_object, receiver)
var handler = {
get: function(r, k) {
@ -66,7 +67,8 @@ function TestCall(isStrict, callTrap) {
receiver = 333
assertEquals(42, f(11, 31))
assertSame(isStrict ? undefined : global_object, receiver)
// TODO(rossberg): strict mode seems to be broken on x64...
// assertSame(isStrict ? undefined : global_object, receiver)
receiver = 333
assertEquals(42, o.f(10, 32))
assertSame(o, receiver)
@ -744,31 +746,3 @@ function TestCalls() {
TestCalls()
*/
var realms = [Realm.create(), Realm.create()];
Realm.shared = {};
Realm.eval(realms[0], "function f() { return this; };");
Realm.eval(realms[0], "Realm.shared.f = f;");
Realm.eval(realms[0], "Realm.shared.fg = this;");
Realm.eval(realms[1], "function g() { return this; };");
Realm.eval(realms[1], "Realm.shared.g = g;");
Realm.eval(realms[1], "Realm.shared.gg = this;");
var fp = Proxy.createFunction({}, Realm.shared.f);
var gp = Proxy.createFunction({}, Realm.shared.g);
for (var i = 0; i < 10; i++) {
assertEquals(Realm.shared.fg, fp());
assertEquals(Realm.shared.gg, gp());
with (this) {
assertEquals(Realm.shared.fg, fp());
assertEquals(Realm.shared.gg, gp());
}
with ({}) {
assertEquals(Realm.shared.fg, fp());
assertEquals(Realm.shared.gg, gp());
}
}