__ Prologue(info->IsCodePreAgingActive());
frame()->SetRegisterSaveAreaSize(
StandardFrameConstants::kFixedFrameSizeFromFp);
-
- // Sloppy mode functions and builtins need to replace the receiver with the
- // global proxy when called as functions (without an explicit receiver
- // object).
- // TODO(mstarzinger/verwaest): Should this be moved back into the CallIC?
- if (info->strict_mode() == SLOPPY && !info->is_native()) {
- Label ok;
- // +2 for return address and saved frame pointer.
- int receiver_slot = info->scope()->num_parameters() + 2;
- __ ldr(r2, MemOperand(fp, receiver_slot * kPointerSize));
- __ CompareRoot(r2, Heap::kUndefinedValueRootIndex);
- __ b(ne, &ok);
- __ ldr(r2, GlobalObjectOperand());
- __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalProxyOffset));
- __ str(r2, MemOperand(fp, receiver_slot * kPointerSize));
- __ bind(&ok);
- }
-
} else {
__ StubPrologue();
frame()->SetRegisterSaveAreaSize(
__ Prologue(info->IsCodePreAgingActive());
frame()->SetRegisterSaveAreaSize(
StandardFrameConstants::kFixedFrameSizeFromFp);
-
- // Sloppy mode functions and builtins need to replace the receiver with the
- // global proxy when called as functions (without an explicit receiver
- // object).
- // TODO(mstarzinger/verwaest): Should this be moved back into the CallIC?
- if (info->strict_mode() == SLOPPY && !info->is_native()) {
- Label ok;
- // +2 for return address and saved frame pointer.
- int receiver_slot = info->scope()->num_parameters() + 2;
- __ Ldr(x10, MemOperand(fp, receiver_slot * kXRegSize));
- __ JumpIfNotRoot(x10, Heap::kUndefinedValueRootIndex, &ok);
- __ Ldr(x10, GlobalObjectMemOperand());
- __ Ldr(x10, FieldMemOperand(x10, GlobalObject::kGlobalProxyOffset));
- __ Str(x10, MemOperand(fp, receiver_slot * kXRegSize));
- __ Bind(&ok);
- }
-
} else {
__ SetStackPointer(jssp);
__ StubPrologue();
Environment env(this, scope, graph()->start());
set_environment(&env);
+ // Initialize the incoming context.
+ Node* outer_context = GetFunctionContext();
+ set_current_context(outer_context);
+
+ // Build receiver check for sloppy mode if necessary.
+ // TODO(mstarzinger/verwaest): Should this be moved back into the CallIC?
+ Node* original_receiver = env.Lookup(scope->receiver());
+ Node* patched_receiver = BuildPatchReceiverToGlobalProxy(original_receiver);
+ env.Bind(scope->receiver(), patched_receiver);
+
// Build node to initialize local function context.
Node* closure = GetFunctionClosure();
- Node* outer = GetFunctionContext();
- Node* inner = BuildLocalFunctionContext(outer, closure);
+ Node* inner_context = BuildLocalFunctionContext(outer_context, closure);
// Push top-level function scope for the function body.
- ContextScope top_context(this, scope, inner);
+ ContextScope top_context(this, scope, inner_context);
// Build the arguments object if it is used.
BuildArgumentsObject(scope->arguments());
}
+Node* AstGraphBuilder::BuildPatchReceiverToGlobalProxy(Node* receiver) {
+ // Sloppy mode functions and builtins need to replace the receiver with the
+ // global proxy when called as functions (without an explicit receiver
+ // object). Otherwise there is nothing left to do here.
+ if (info()->strict_mode() != SLOPPY || info()->is_native()) return receiver;
+
+ // There is no need to perform patching if the receiver is never used. Note
+ // that scope predicates are purely syntactical, a call to eval might still
+ // inspect the receiver value.
+ if (!info()->scope()->uses_this() && !info()->scope()->inner_uses_this() &&
+ !info()->scope()->calls_sloppy_eval()) {
+ return receiver;
+ }
+
+ IfBuilder receiver_check(this);
+ Node* undefined = jsgraph()->UndefinedConstant();
+ Node* check = NewNode(javascript()->StrictEqual(), receiver, undefined);
+ receiver_check.If(check);
+ receiver_check.Then();
+ environment()->Push(BuildLoadGlobalProxy());
+ receiver_check.Else();
+ environment()->Push(receiver);
+ receiver_check.End();
+ return environment()->Pop();
+}
+
+
Node* AstGraphBuilder::BuildLocalFunctionContext(Node* context, Node* closure) {
int heap_slots = info()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
if (heap_slots <= 0) return context;
- set_current_context(context);
// Allocate a new local context.
const Operator* op = javascript()->CreateFunctionContext();
}
+Node* AstGraphBuilder::BuildLoadGlobalProxy() {
+ Node* global = BuildLoadGlobalObject();
+ Node* proxy =
+ BuildLoadObjectField(global, JSGlobalObject::kGlobalProxyOffset);
+ return proxy;
+}
+
+
Node* AstGraphBuilder::BuildToBoolean(Node* input) {
// TODO(titzer): this should be in a JSOperatorReducer.
switch (input->opcode()) {
// other dependencies tracked by the environment might be mutated though.
//
+ // Builder to create a receiver check for sloppy mode.
+ Node* BuildPatchReceiverToGlobalProxy(Node* receiver);
+
// Builder to create a local function context.
Node* BuildLocalFunctionContext(Node* context, Node* closure);
// Builders for accessing the function context.
Node* BuildLoadBuiltinsObject();
Node* BuildLoadGlobalObject();
+ Node* BuildLoadGlobalProxy();
Node* BuildLoadClosure();
Node* BuildLoadObjectField(Node* object, int offset);
__ Prologue(info->IsCodePreAgingActive());
frame->SetRegisterSaveAreaSize(
StandardFrameConstants::kFixedFrameSizeFromFp);
-
- // Sloppy mode functions and builtins need to replace the receiver with the
- // global proxy when called as functions (without an explicit receiver
- // object).
- // TODO(mstarzinger/verwaest): Should this be moved back into the CallIC?
- if (info->strict_mode() == SLOPPY && !info->is_native()) {
- Label ok;
- // +2 for return address and saved frame pointer.
- int receiver_slot = info->scope()->num_parameters() + 2;
- __ mov(ecx, Operand(ebp, receiver_slot * kPointerSize));
- __ cmp(ecx, isolate()->factory()->undefined_value());
- __ j(not_equal, &ok, Label::kNear);
- __ mov(ecx, GlobalObjectOperand());
- __ mov(ecx, FieldOperand(ecx, GlobalObject::kGlobalProxyOffset));
- __ mov(Operand(ebp, receiver_slot * kPointerSize), ecx);
- __ bind(&ok);
- }
-
} else {
__ StubPrologue();
frame->SetRegisterSaveAreaSize(
__ Prologue(info->IsCodePreAgingActive());
frame()->SetRegisterSaveAreaSize(
StandardFrameConstants::kFixedFrameSizeFromFp);
-
- // Sloppy mode functions and builtins need to replace the receiver with the
- // global proxy when called as functions (without an explicit receiver
- // object).
- // TODO(mstarzinger/verwaest): Should this be moved back into the CallIC?
- if (info->strict_mode() == SLOPPY && !info->is_native()) {
- Label ok;
- // +2 for return address and saved frame pointer.
- int receiver_slot = info->scope()->num_parameters() + 2;
- __ lw(a2, MemOperand(fp, receiver_slot * kPointerSize));
- __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
- __ Branch(&ok, ne, a2, Operand(at));
-
- __ lw(a2, GlobalObjectOperand());
- __ lw(a2, FieldMemOperand(a2, GlobalObject::kGlobalProxyOffset));
- __ sw(a2, MemOperand(fp, receiver_slot * kPointerSize));
- __ bind(&ok);
- }
} else {
__ StubPrologue();
frame()->SetRegisterSaveAreaSize(
__ Prologue(info->IsCodePreAgingActive());
frame()->SetRegisterSaveAreaSize(
StandardFrameConstants::kFixedFrameSizeFromFp);
-
- // Sloppy mode functions and builtins need to replace the receiver with the
- // global proxy when called as functions (without an explicit receiver
- // object).
- // TODO(mstarzinger/verwaest): Should this be moved back into the CallIC?
- if (info->strict_mode() == SLOPPY && !info->is_native()) {
- Label ok;
- StackArgumentsAccessor args(rbp, info->scope()->num_parameters());
- __ movp(rcx, args.GetReceiverOperand());
- __ CompareRoot(rcx, Heap::kUndefinedValueRootIndex);
- __ j(not_equal, &ok, Label::kNear);
- __ movp(rcx, GlobalObjectOperand());
- __ movp(rcx, FieldOperand(rcx, GlobalObject::kGlobalProxyOffset));
- __ movp(args.GetReceiverOperand(), rcx);
- __ bind(&ok);
- }
-
} else {
__ StubPrologue();
frame()->SetRegisterSaveAreaSize(
outer_scope()->unresolved_.Add(unresolved_[i], zone());
}
+ // Propagate usage flags to outer scope.
+ if (uses_arguments()) outer_scope_->RecordArgumentsUsage();
+ if (uses_super()) outer_scope_->RecordSuperUsage();
+ if (uses_this()) outer_scope_->RecordThisUsage();
+
return NULL;
}