| Index: src/full-codegen/mips64/full-codegen-mips64.cc
|
| diff --git a/src/full-codegen/mips64/full-codegen-mips64.cc b/src/full-codegen/mips64/full-codegen-mips64.cc
|
| index bca1afc3b6bcb320e9ba963a2cfb084c8889ef1c..49d53e602a593c7a23a23029012f3ab6a4fbd8fe 100644
|
| --- a/src/full-codegen/mips64/full-codegen-mips64.cc
|
| +++ b/src/full-codegen/mips64/full-codegen-mips64.cc
|
| @@ -806,17 +806,7 @@ void FullCodeGenerator::VisitVariableDeclaration(
|
| }
|
| break;
|
|
|
| - case VariableLocation::LOOKUP: {
|
| - Comment cmnt(masm_, "[ VariableDeclaration");
|
| - DCHECK_EQ(VAR, variable->mode());
|
| - DCHECK(!variable->binding_needs_init());
|
| - __ li(a2, Operand(variable->name()));
|
| - __ Push(a2);
|
| - __ CallRuntime(Runtime::kDeclareEvalVar);
|
| - PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
|
| - break;
|
| - }
|
| -
|
| + case VariableLocation::LOOKUP:
|
| case VariableLocation::MODULE:
|
| UNREACHABLE();
|
| }
|
| @@ -868,17 +858,7 @@ void FullCodeGenerator::VisitFunctionDeclaration(
|
| break;
|
| }
|
|
|
| - case VariableLocation::LOOKUP: {
|
| - Comment cmnt(masm_, "[ FunctionDeclaration");
|
| - __ li(a2, Operand(variable->name()));
|
| - PushOperand(a2);
|
| - // Push initial value for function declaration.
|
| - VisitForStackValue(declaration->fun());
|
| - CallRuntimeWithOperands(Runtime::kDeclareEvalFunction);
|
| - PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
|
| - break;
|
| - }
|
| -
|
| + case VariableLocation::LOOKUP:
|
| case VariableLocation::MODULE:
|
| UNREACHABLE();
|
| }
|
| @@ -1184,93 +1164,6 @@ void FullCodeGenerator::EmitSetHomeObjectAccumulator(Expression* initializer,
|
| CallStoreIC(slot, isolate()->factory()->home_object_symbol());
|
| }
|
|
|
| -
|
| -void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
|
| - TypeofMode typeof_mode,
|
| - Label* slow) {
|
| - Register current = cp;
|
| - Register next = a1;
|
| - Register temp = a2;
|
| -
|
| - int to_check = scope()->ContextChainLengthUntilOutermostSloppyEval();
|
| - for (Scope* s = scope(); to_check > 0; s = s->outer_scope()) {
|
| - if (!s->NeedsContext()) continue;
|
| - if (s->calls_sloppy_eval()) {
|
| - // Check that extension is "the hole".
|
| - __ ld(temp, ContextMemOperand(current, Context::EXTENSION_INDEX));
|
| - __ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow);
|
| - }
|
| - // Load next context in chain.
|
| - __ ld(next, ContextMemOperand(current, Context::PREVIOUS_INDEX));
|
| - // Walk the rest of the chain without clobbering cp.
|
| - current = next;
|
| - to_check--;
|
| - }
|
| -
|
| - // All extension objects were empty and it is safe to use a normal global
|
| - // load machinery.
|
| - EmitGlobalVariableLoad(proxy, typeof_mode);
|
| -}
|
| -
|
| -
|
| -MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var,
|
| - Label* slow) {
|
| - DCHECK(var->IsContextSlot());
|
| - Register context = cp;
|
| - Register next = a3;
|
| - Register temp = a4;
|
| -
|
| - for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) {
|
| - if (s->NeedsContext()) {
|
| - if (s->calls_sloppy_eval()) {
|
| - // Check that extension is "the hole".
|
| - __ ld(temp, ContextMemOperand(context, Context::EXTENSION_INDEX));
|
| - __ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow);
|
| - }
|
| - __ ld(next, ContextMemOperand(context, Context::PREVIOUS_INDEX));
|
| - // Walk the rest of the chain without clobbering cp.
|
| - context = next;
|
| - }
|
| - }
|
| - // Check that last extension is "the hole".
|
| - __ ld(temp, ContextMemOperand(context, Context::EXTENSION_INDEX));
|
| - __ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow);
|
| -
|
| - // This function is used only for loads, not stores, so it's safe to
|
| - // return an cp-based operand (the write barrier cannot be allowed to
|
| - // destroy the cp register).
|
| - return ContextMemOperand(context, var->index());
|
| -}
|
| -
|
| -
|
| -void FullCodeGenerator::EmitDynamicLookupFastCase(VariableProxy* proxy,
|
| - TypeofMode typeof_mode,
|
| - Label* slow, Label* done) {
|
| - // Generate fast-case code for variables that might be shadowed by
|
| - // eval-introduced variables. Eval is used a lot without
|
| - // introducing variables. In those cases, we do not want to
|
| - // perform a runtime call for all variables in the scope
|
| - // containing the eval.
|
| - Variable* var = proxy->var();
|
| - if (var->mode() == DYNAMIC_GLOBAL) {
|
| - EmitLoadGlobalCheckExtensions(proxy, typeof_mode, slow);
|
| - __ Branch(done);
|
| - } else if (var->mode() == DYNAMIC_LOCAL) {
|
| - Variable* local = var->local_if_not_shadowed();
|
| - __ ld(v0, ContextSlotOperandCheckExtensions(local, slow));
|
| - if (local->binding_needs_init()) {
|
| - __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
|
| - __ dsubu(at, v0, at); // Sub as compare: at == 0 on eq.
|
| - __ Branch(done, ne, at, Operand(zero_reg));
|
| - __ li(a0, Operand(var->name()));
|
| - __ push(a0);
|
| - __ CallRuntime(Runtime::kThrowReferenceError);
|
| - } else {
|
| - __ Branch(done);
|
| - }
|
| - }
|
| -}
|
| -
|
| void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy,
|
| TypeofMode typeof_mode) {
|
| // Record position before possible IC call.
|
| @@ -1278,8 +1171,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy,
|
| PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS);
|
| Variable* var = proxy->var();
|
|
|
| - // Three cases: global variables, lookup variables, and all other types of
|
| - // variables.
|
| + // Two cases: global variables and all other types of variables.
|
| switch (var->location()) {
|
| case VariableLocation::UNALLOCATED: {
|
| Comment cmnt(masm_, "[ Global variable");
|
| @@ -1313,24 +1205,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy,
|
| break;
|
| }
|
|
|
| - case VariableLocation::LOOKUP: {
|
| - Comment cmnt(masm_, "[ Lookup variable");
|
| - Label done, slow;
|
| - // Generate code for loading from variables potentially shadowed
|
| - // by eval-introduced variables.
|
| - EmitDynamicLookupFastCase(proxy, typeof_mode, &slow, &done);
|
| - __ bind(&slow);
|
| - __ Push(var->name());
|
| - Runtime::FunctionId function_id =
|
| - typeof_mode == NOT_INSIDE_TYPEOF
|
| - ? Runtime::kLoadLookupSlot
|
| - : Runtime::kLoadLookupSlotInsideTypeof;
|
| - __ CallRuntime(function_id);
|
| - __ bind(&done);
|
| - context()->Plug(v0);
|
| - break;
|
| - }
|
| -
|
| + case VariableLocation::LOOKUP:
|
| case VariableLocation::MODULE:
|
| UNREACHABLE();
|
| }
|
| @@ -2111,25 +1986,18 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op,
|
|
|
| } else {
|
| DCHECK(var->mode() != CONST || op == Token::INIT);
|
| - if (var->IsLookupSlot()) {
|
| - __ Push(var->name());
|
| - __ Push(v0);
|
| - __ CallRuntime(is_strict(language_mode())
|
| - ? Runtime::kStoreLookupSlot_Strict
|
| - : Runtime::kStoreLookupSlot_Sloppy);
|
| - } else {
|
| - // Assignment to var or initializing assignment to let/const in harmony
|
| - // mode.
|
| - DCHECK((var->IsStackAllocated() || var->IsContextSlot()));
|
| - MemOperand location = VarOperand(var, a1);
|
| - if (FLAG_debug_code && var->mode() == LET && op == Token::INIT) {
|
| - // Check for an uninitialized let binding.
|
| - __ ld(a2, location);
|
| - __ LoadRoot(a4, Heap::kTheHoleValueRootIndex);
|
| - __ Check(eq, kLetBindingReInitialization, a2, Operand(a4));
|
| - }
|
| - EmitStoreToStackLocalOrContextSlot(var, location);
|
| + DCHECK((var->IsStackAllocated() || var->IsContextSlot()));
|
| + DCHECK(!var->IsLookupSlot());
|
| + // Assignment to var or initializing assignment to let/const in harmony
|
| + // mode.
|
| + MemOperand location = VarOperand(var, a1);
|
| + if (FLAG_debug_code && var->mode() == LET && op == Token::INIT) {
|
| + // Check for an uninitialized let binding.
|
| + __ ld(a2, location);
|
| + __ LoadRoot(a4, Heap::kTheHoleValueRootIndex);
|
| + __ Check(eq, kLetBindingReInitialization, a2, Operand(a4));
|
| }
|
| + EmitStoreToStackLocalOrContextSlot(var, location);
|
| }
|
| }
|
|
|
| @@ -2360,115 +2228,6 @@ void FullCodeGenerator::EmitCall(Call* expr, ConvertReceiverMode mode) {
|
| context()->DropAndPlug(1, v0);
|
| }
|
|
|
| -void FullCodeGenerator::EmitResolvePossiblyDirectEval(Call* expr) {
|
| - int arg_count = expr->arguments()->length();
|
| - // a6: copy of the first argument or undefined if it doesn't exist.
|
| - if (arg_count > 0) {
|
| - __ ld(a6, MemOperand(sp, arg_count * kPointerSize));
|
| - } else {
|
| - __ LoadRoot(a6, Heap::kUndefinedValueRootIndex);
|
| - }
|
| -
|
| - // a5: the receiver of the enclosing function.
|
| - __ ld(a5, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
|
| -
|
| - // a4: the language mode.
|
| - __ li(a4, Operand(Smi::FromInt(language_mode())));
|
| -
|
| - // a1: the start position of the scope the calls resides in.
|
| - __ li(a1, Operand(Smi::FromInt(scope()->start_position())));
|
| -
|
| - // a0: the source position of the eval call.
|
| - __ li(a0, Operand(Smi::FromInt(expr->position())));
|
| -
|
| - // Do the runtime call.
|
| - __ Push(a6, a5, a4, a1, a0);
|
| - __ CallRuntime(Runtime::kResolvePossiblyDirectEval);
|
| -}
|
| -
|
| -
|
| -// See http://www.ecma-international.org/ecma-262/6.0/#sec-function-calls.
|
| -void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) {
|
| - VariableProxy* callee = expr->expression()->AsVariableProxy();
|
| - if (callee->var()->IsLookupSlot()) {
|
| - Label slow, done;
|
| -
|
| - SetExpressionPosition(callee);
|
| - // Generate code for loading from variables potentially shadowed by
|
| - // eval-introduced variables.
|
| - EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done);
|
| -
|
| - __ bind(&slow);
|
| - // Call the runtime to find the function to call (returned in v0)
|
| - // and the object holding it (returned in v1).
|
| - __ Push(callee->name());
|
| - __ CallRuntime(Runtime::kLoadLookupSlotForCall);
|
| - PushOperands(v0, v1); // Function, receiver.
|
| - PrepareForBailoutForId(expr->LookupId(), BailoutState::NO_REGISTERS);
|
| -
|
| - // If fast case code has been generated, emit code to push the
|
| - // function and receiver and have the slow path jump around this
|
| - // code.
|
| - if (done.is_linked()) {
|
| - Label call;
|
| - __ Branch(&call);
|
| - __ bind(&done);
|
| - // Push function.
|
| - __ push(v0);
|
| - // The receiver is implicitly the global receiver. Indicate this
|
| - // by passing the hole to the call function stub.
|
| - __ LoadRoot(a1, Heap::kUndefinedValueRootIndex);
|
| - __ push(a1);
|
| - __ bind(&call);
|
| - }
|
| - } else {
|
| - VisitForStackValue(callee);
|
| - // refEnv.WithBaseObject()
|
| - __ LoadRoot(a2, Heap::kUndefinedValueRootIndex);
|
| - PushOperand(a2); // Reserved receiver slot.
|
| - }
|
| -}
|
| -
|
| -
|
| -void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) {
|
| - // In a call to eval, we first call Runtime_ResolvePossiblyDirectEval
|
| - // to resolve the function we need to call. Then we call the resolved
|
| - // function using the given arguments.
|
| - ZoneList<Expression*>* args = expr->arguments();
|
| - int arg_count = args->length();
|
| - PushCalleeAndWithBaseObject(expr);
|
| -
|
| - // Push the arguments.
|
| - for (int i = 0; i < arg_count; i++) {
|
| - VisitForStackValue(args->at(i));
|
| - }
|
| -
|
| - // Push a copy of the function (found below the arguments) and
|
| - // resolve eval.
|
| - __ ld(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
|
| - __ push(a1);
|
| - EmitResolvePossiblyDirectEval(expr);
|
| -
|
| - // Touch up the stack with the resolved function.
|
| - __ sd(v0, MemOperand(sp, (arg_count + 1) * kPointerSize));
|
| -
|
| - PrepareForBailoutForId(expr->EvalId(), BailoutState::NO_REGISTERS);
|
| - // Record source position for debugger.
|
| - SetCallPosition(expr);
|
| - Handle<Code> code = CodeFactory::CallIC(isolate(), ConvertReceiverMode::kAny,
|
| - expr->tail_call_mode())
|
| - .code();
|
| - __ li(a3, Operand(SmiFromSlot(expr->CallFeedbackICSlot())));
|
| - __ ld(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
|
| - __ li(a0, Operand(arg_count));
|
| - __ Call(code, RelocInfo::CODE_TARGET);
|
| - OperandStackDepthDecrement(arg_count + 1);
|
| - RecordJSReturnSite(expr);
|
| - RestoreContext();
|
| - context()->DropAndPlug(1, v0);
|
| -}
|
| -
|
| -
|
| void FullCodeGenerator::VisitCallNew(CallNew* expr) {
|
| Comment cmnt(masm_, "[ CallNew");
|
| // According to ECMA-262, section 11.2.2, page 44, the function
|
| @@ -2898,17 +2657,12 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
| __ Push(a2, a1);
|
| __ CallRuntime(Runtime::kDeleteProperty_Sloppy);
|
| context()->Plug(v0);
|
| - } else if (var->IsStackAllocated() || var->IsContextSlot()) {
|
| + } else {
|
| + DCHECK(!var->IsLookupSlot());
|
| + DCHECK(var->IsStackAllocated() || var->IsContextSlot());
|
| // Result of deleting non-global, non-dynamic variables is false.
|
| // The subexpression does not have side effects.
|
| context()->Plug(is_this);
|
| - } else {
|
| - // Non-global variable. Call the runtime to try to delete from the
|
| - // context where the variable was introduced.
|
| - DCHECK(!context_register().is(a2));
|
| - __ Push(var->name());
|
| - __ CallRuntime(Runtime::kDeleteLookupSlot);
|
| - context()->Plug(v0);
|
| }
|
| } else {
|
| // Result of deleting non-property, non-variable reference is true.
|
|
|