diff options
Diffstat (limited to 'deps/v8/src/mips/full-codegen-mips.cc')
-rw-r--r-- | deps/v8/src/mips/full-codegen-mips.cc | 709 |
1 files changed, 358 insertions, 351 deletions
diff --git a/deps/v8/src/mips/full-codegen-mips.cc b/deps/v8/src/mips/full-codegen-mips.cc index ff280ce76..639f57fd6 100644 --- a/deps/v8/src/mips/full-codegen-mips.cc +++ b/deps/v8/src/mips/full-codegen-mips.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "v8.h" +#include "src/v8.h" #if V8_TARGET_ARCH_MIPS @@ -14,18 +14,18 @@ // places where we have to move a previous result in v0 to a0 for the // next call: mov(a0, v0). This is not needed on the other architectures. -#include "code-stubs.h" -#include "codegen.h" -#include "compiler.h" -#include "debug.h" -#include "full-codegen.h" -#include "isolate-inl.h" -#include "parser.h" -#include "scopes.h" -#include "stub-cache.h" +#include "src/code-stubs.h" +#include "src/codegen.h" +#include "src/compiler.h" +#include "src/debug.h" +#include "src/full-codegen.h" +#include "src/isolate-inl.h" +#include "src/parser.h" +#include "src/scopes.h" +#include "src/stub-cache.h" -#include "mips/code-stubs-mips.h" -#include "mips/macro-assembler-mips.h" +#include "src/mips/code-stubs-mips.h" +#include "src/mips/macro-assembler-mips.h" namespace v8 { namespace internal { @@ -50,13 +50,13 @@ class JumpPatchSite BASE_EMBEDDED { } ~JumpPatchSite() { - ASSERT(patch_site_.is_bound() == info_emitted_); + DCHECK(patch_site_.is_bound() == info_emitted_); } // When initially emitting this ensure that a jump is always generated to skip // the inlined smi code. void EmitJumpIfNotSmi(Register reg, Label* target) { - ASSERT(!patch_site_.is_bound() && !info_emitted_); + DCHECK(!patch_site_.is_bound() && !info_emitted_); Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_); __ bind(&patch_site_); __ andi(at, reg, 0); @@ -68,7 +68,7 @@ class JumpPatchSite BASE_EMBEDDED { // the inlined smi code. void EmitJumpIfSmi(Register reg, Label* target) { Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_); - ASSERT(!patch_site_.is_bound() && !info_emitted_); + DCHECK(!patch_site_.is_bound() && !info_emitted_); __ bind(&patch_site_); __ andi(at, reg, 0); // Never taken before patched. @@ -97,28 +97,6 @@ class JumpPatchSite BASE_EMBEDDED { }; -static void EmitStackCheck(MacroAssembler* masm_, - Register stack_limit_scratch, - int pointers = 0, - Register scratch = sp) { - Isolate* isolate = masm_->isolate(); - Label ok; - ASSERT(scratch.is(sp) == (pointers == 0)); - Heap::RootListIndex index; - if (pointers != 0) { - __ Subu(scratch, sp, Operand(pointers * kPointerSize)); - index = Heap::kRealStackLimitRootIndex; - } else { - index = Heap::kStackLimitRootIndex; - } - __ LoadRoot(stack_limit_scratch, index); - __ Branch(&ok, hs, scratch, Operand(stack_limit_scratch)); - PredictableCodeSizeScope predictable(masm_, 4 * Assembler::kInstrSize); - __ Call(isolate->builtins()->StackCheck(), RelocInfo::CODE_TARGET); - __ bind(&ok); -} - - // Generate code for a JS function. On entry to the function the receiver // and arguments have been pushed on the stack left to right. The actual // argument count matches the formal parameter count expected by the @@ -163,7 +141,7 @@ void FullCodeGenerator::Generate() { __ Branch(&ok, ne, a2, Operand(at)); __ lw(a2, GlobalObjectOperand()); - __ lw(a2, FieldMemOperand(a2, GlobalObject::kGlobalReceiverOffset)); + __ lw(a2, FieldMemOperand(a2, GlobalObject::kGlobalProxyOffset)); __ sw(a2, MemOperand(sp, receiver_offset)); @@ -176,16 +154,21 @@ void FullCodeGenerator::Generate() { FrameScope frame_scope(masm_, StackFrame::MANUAL); info->set_prologue_offset(masm_->pc_offset()); - __ Prologue(BUILD_FUNCTION_FRAME); + __ Prologue(info->IsCodePreAgingActive()); info->AddNoFrameRange(0, masm_->pc_offset()); { Comment cmnt(masm_, "[ Allocate locals"); int locals_count = info->scope()->num_stack_slots(); // Generators allocate locals, if any, in context slots. - ASSERT(!info->function()->is_generator() || locals_count == 0); + DCHECK(!info->function()->is_generator() || locals_count == 0); if (locals_count > 0) { if (locals_count >= 128) { - EmitStackCheck(masm_, a2, locals_count, t5); + Label ok; + __ Subu(t5, sp, Operand(locals_count * kPointerSize)); + __ LoadRoot(a2, Heap::kRealStackLimitRootIndex); + __ Branch(&ok, hs, t5, Operand(a2)); + __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION); + __ bind(&ok); } __ LoadRoot(t5, Heap::kUndefinedValueRootIndex); int kMaxPushes = FLAG_optimize_for_size ? 4 : 32; @@ -219,16 +202,19 @@ void FullCodeGenerator::Generate() { if (heap_slots > 0) { Comment cmnt(masm_, "[ Allocate context"); // Argument to NewContext is the function, which is still in a1. + bool need_write_barrier = true; if (FLAG_harmony_scoping && info->scope()->is_global_scope()) { __ push(a1); __ Push(info->scope()->GetScopeInfo()); - __ CallRuntime(Runtime::kHiddenNewGlobalContext, 2); + __ CallRuntime(Runtime::kNewGlobalContext, 2); } else if (heap_slots <= FastNewContextStub::kMaximumSlots) { FastNewContextStub stub(isolate(), heap_slots); __ CallStub(&stub); + // Result of FastNewContextStub is always in new space. + need_write_barrier = false; } else { __ push(a1); - __ CallRuntime(Runtime::kHiddenNewFunctionContext, 1); + __ CallRuntime(Runtime::kNewFunctionContext, 1); } function_in_register = false; // Context is returned in v0. It replaces the context passed to us. @@ -249,8 +235,15 @@ void FullCodeGenerator::Generate() { __ sw(a0, target); // Update the write barrier. - __ RecordWriteContextSlot( - cp, target.offset(), a0, a3, kRAHasBeenSaved, kDontSaveFPRegs); + if (need_write_barrier) { + __ RecordWriteContextSlot( + cp, target.offset(), a0, a3, kRAHasBeenSaved, kDontSaveFPRegs); + } else if (FLAG_debug_code) { + Label done; + __ JumpIfInNewSpace(cp, a0, &done); + __ Abort(kExpectedNewSpaceObject); + __ bind(&done); + } } } } @@ -308,9 +301,9 @@ void FullCodeGenerator::Generate() { // constant. if (scope()->is_function_scope() && scope()->function() != NULL) { VariableDeclaration* function = scope()->function(); - ASSERT(function->proxy()->var()->mode() == CONST || + DCHECK(function->proxy()->var()->mode() == CONST || function->proxy()->var()->mode() == CONST_LEGACY); - ASSERT(function->proxy()->var()->location() != Variable::UNALLOCATED); + DCHECK(function->proxy()->var()->location() != Variable::UNALLOCATED); VisitVariableDeclaration(function); } VisitDeclarations(scope()->declarations()); @@ -318,13 +311,20 @@ void FullCodeGenerator::Generate() { { Comment cmnt(masm_, "[ Stack check"); PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS); - EmitStackCheck(masm_, at); + Label ok; + __ LoadRoot(at, Heap::kStackLimitRootIndex); + __ Branch(&ok, hs, sp, Operand(at)); + Handle<Code> stack_check = isolate()->builtins()->StackCheck(); + PredictableCodeSizeScope predictable(masm_, + masm_->CallSize(stack_check, RelocInfo::CODE_TARGET)); + __ Call(stack_check, RelocInfo::CODE_TARGET); + __ bind(&ok); } { Comment cmnt(masm_, "[ Body"); - ASSERT(loop_depth() == 0); + DCHECK(loop_depth() == 0); VisitStatements(function()->body()); - ASSERT(loop_depth() == 0); + DCHECK(loop_depth() == 0); } } @@ -338,7 +338,7 @@ void FullCodeGenerator::Generate() { void FullCodeGenerator::ClearAccumulator() { - ASSERT(Smi::FromInt(0) == 0); + DCHECK(Smi::FromInt(0) == 0); __ mov(v0, zero_reg); } @@ -353,7 +353,7 @@ void FullCodeGenerator::EmitProfilingCounterDecrement(int delta) { void FullCodeGenerator::EmitProfilingCounterReset() { int reset_value = FLAG_interrupt_budget; - if (isolate()->IsDebuggerActive()) { + if (info_->is_debug()) { // Detect debug break requests as soon as possible. reset_value = FLAG_interrupt_budget >> 4; } @@ -373,7 +373,7 @@ void FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt, Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_); Comment cmnt(masm_, "[ Back edge bookkeeping"); Label ok; - ASSERT(back_edge_target->is_bound()); + DCHECK(back_edge_target->is_bound()); int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target); int weight = Min(kMaxBackEdgeWeight, Max(1, distance / kCodeSizeMultiplier)); @@ -452,7 +452,7 @@ void FullCodeGenerator::EmitReturnSequence() { #ifdef DEBUG // Check that the size of the code used for returning is large enough // for the debugger's requirements. - ASSERT(Assembler::kJSReturnSequenceInstructions <= + DCHECK(Assembler::kJSReturnSequenceInstructions <= masm_->InstructionsGeneratedSince(&check_exit_codesize)); #endif } @@ -460,18 +460,18 @@ void FullCodeGenerator::EmitReturnSequence() { void FullCodeGenerator::EffectContext::Plug(Variable* var) const { - ASSERT(var->IsStackAllocated() || var->IsContextSlot()); + DCHECK(var->IsStackAllocated() || var->IsContextSlot()); } void FullCodeGenerator::AccumulatorValueContext::Plug(Variable* var) const { - ASSERT(var->IsStackAllocated() || var->IsContextSlot()); + DCHECK(var->IsStackAllocated() || var->IsContextSlot()); codegen()->GetVar(result_register(), var); } void FullCodeGenerator::StackValueContext::Plug(Variable* var) const { - ASSERT(var->IsStackAllocated() || var->IsContextSlot()); + DCHECK(var->IsStackAllocated() || var->IsContextSlot()); codegen()->GetVar(result_register(), var); __ push(result_register()); } @@ -542,7 +542,7 @@ void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const { true, true_label_, false_label_); - ASSERT(!lit->IsUndetectableObject()); // There are no undetectable literals. + DCHECK(!lit->IsUndetectableObject()); // There are no undetectable literals. if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) { if (false_label_ != fall_through_) __ Branch(false_label_); } else if (lit->IsTrue() || lit->IsJSObject()) { @@ -569,7 +569,7 @@ void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const { void FullCodeGenerator::EffectContext::DropAndPlug(int count, Register reg) const { - ASSERT(count > 0); + DCHECK(count > 0); __ Drop(count); } @@ -577,7 +577,7 @@ void FullCodeGenerator::EffectContext::DropAndPlug(int count, void FullCodeGenerator::AccumulatorValueContext::DropAndPlug( int count, Register reg) const { - ASSERT(count > 0); + DCHECK(count > 0); __ Drop(count); __ Move(result_register(), reg); } @@ -585,7 +585,7 @@ void FullCodeGenerator::AccumulatorValueContext::DropAndPlug( void FullCodeGenerator::StackValueContext::DropAndPlug(int count, Register reg) const { - ASSERT(count > 0); + DCHECK(count > 0); if (count > 1) __ Drop(count - 1); __ sw(reg, MemOperand(sp, 0)); } @@ -593,7 +593,7 @@ void FullCodeGenerator::StackValueContext::DropAndPlug(int count, void FullCodeGenerator::TestContext::DropAndPlug(int count, Register reg) const { - ASSERT(count > 0); + DCHECK(count > 0); // For simplicity we always test the accumulator register. __ Drop(count); __ Move(result_register(), reg); @@ -604,7 +604,7 @@ void FullCodeGenerator::TestContext::DropAndPlug(int count, void FullCodeGenerator::EffectContext::Plug(Label* materialize_true, Label* materialize_false) const { - ASSERT(materialize_true == materialize_false); + DCHECK(materialize_true == materialize_false); __ bind(materialize_true); } @@ -640,8 +640,8 @@ void FullCodeGenerator::StackValueContext::Plug( void FullCodeGenerator::TestContext::Plug(Label* materialize_true, Label* materialize_false) const { - ASSERT(materialize_true == true_label_); - ASSERT(materialize_false == false_label_); + DCHECK(materialize_true == true_label_); + DCHECK(materialize_false == false_label_); } @@ -707,7 +707,7 @@ void FullCodeGenerator::Split(Condition cc, MemOperand FullCodeGenerator::StackOperand(Variable* var) { - ASSERT(var->IsStackAllocated()); + DCHECK(var->IsStackAllocated()); // Offset is negative because higher indexes are at lower addresses. int offset = -var->index() * kPointerSize; // Adjust by a (parameter or local) base offset. @@ -721,7 +721,7 @@ MemOperand FullCodeGenerator::StackOperand(Variable* var) { MemOperand FullCodeGenerator::VarOperand(Variable* var, Register scratch) { - ASSERT(var->IsContextSlot() || var->IsStackAllocated()); + DCHECK(var->IsContextSlot() || var->IsStackAllocated()); if (var->IsContextSlot()) { int context_chain_length = scope()->ContextChainLength(var->scope()); __ LoadContext(scratch, context_chain_length); @@ -743,10 +743,10 @@ void FullCodeGenerator::SetVar(Variable* var, Register src, Register scratch0, Register scratch1) { - ASSERT(var->IsContextSlot() || var->IsStackAllocated()); - ASSERT(!scratch0.is(src)); - ASSERT(!scratch0.is(scratch1)); - ASSERT(!scratch1.is(src)); + DCHECK(var->IsContextSlot() || var->IsStackAllocated()); + DCHECK(!scratch0.is(src)); + DCHECK(!scratch0.is(scratch1)); + DCHECK(!scratch1.is(src)); MemOperand location = VarOperand(var, scratch0); __ sw(src, location); // Emit the write barrier code if the location is in the heap. @@ -784,7 +784,7 @@ void FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr, void FullCodeGenerator::EmitDebugCheckDeclarationContext(Variable* variable) { // The variable in the declaration always resides in the current function // context. - ASSERT_EQ(0, scope()->ContextChainLength(variable->scope())); + DCHECK_EQ(0, scope()->ContextChainLength(variable->scope())); if (generate_debug_code_) { // Check that we're not inside a with or catch context. __ lw(a1, FieldMemOperand(cp, HeapObject::kMapOffset)); @@ -840,7 +840,7 @@ void FullCodeGenerator::VisitVariableDeclaration( Comment cmnt(masm_, "[ VariableDeclaration"); __ li(a2, Operand(variable->name())); // Declaration nodes are always introduced in one of four modes. - ASSERT(IsDeclaredVariableMode(mode)); + DCHECK(IsDeclaredVariableMode(mode)); PropertyAttributes attr = IsImmutableVariableMode(mode) ? READ_ONLY : NONE; __ li(a1, Operand(Smi::FromInt(attr))); @@ -852,11 +852,11 @@ void FullCodeGenerator::VisitVariableDeclaration( __ LoadRoot(a0, Heap::kTheHoleValueRootIndex); __ Push(cp, a2, a1, a0); } else { - ASSERT(Smi::FromInt(0) == 0); + DCHECK(Smi::FromInt(0) == 0); __ mov(a0, zero_reg); // Smi::FromInt(0) indicates no initial value. __ Push(cp, a2, a1, a0); } - __ CallRuntime(Runtime::kHiddenDeclareContextSlot, 4); + __ CallRuntime(Runtime::kDeclareLookupSlot, 4); break; } } @@ -871,7 +871,7 @@ void FullCodeGenerator::VisitFunctionDeclaration( case Variable::UNALLOCATED: { globals_->Add(variable->name(), zone()); Handle<SharedFunctionInfo> function = - Compiler::BuildFunctionInfo(declaration->fun(), script()); + Compiler::BuildFunctionInfo(declaration->fun(), script(), info_); // Check for stack-overflow exception. if (function.is_null()) return SetStackOverflow(); globals_->Add(function, zone()); @@ -912,7 +912,7 @@ void FullCodeGenerator::VisitFunctionDeclaration( __ Push(cp, a2, a1); // Push initial value for function declaration. VisitForStackValue(declaration->fun()); - __ CallRuntime(Runtime::kHiddenDeclareContextSlot, 4); + __ CallRuntime(Runtime::kDeclareLookupSlot, 4); break; } } @@ -921,8 +921,8 @@ void FullCodeGenerator::VisitFunctionDeclaration( void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) { Variable* variable = declaration->proxy()->var(); - ASSERT(variable->location() == Variable::CONTEXT); - ASSERT(variable->interface()->IsFrozen()); + DCHECK(variable->location() == Variable::CONTEXT); + DCHECK(variable->interface()->IsFrozen()); Comment cmnt(masm_, "[ ModuleDeclaration"); EmitDebugCheckDeclarationContext(variable); @@ -984,7 +984,7 @@ void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { __ li(a1, Operand(pairs)); __ li(a0, Operand(Smi::FromInt(DeclareGlobalsFlags()))); __ Push(cp, a1, a0); - __ CallRuntime(Runtime::kHiddenDeclareGlobals, 3); + __ CallRuntime(Runtime::kDeclareGlobals, 3); // Return value is ignored. } @@ -992,7 +992,7 @@ void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { void FullCodeGenerator::DeclareModules(Handle<FixedArray> descriptions) { // Call the runtime to declare the modules. __ Push(descriptions); - __ CallRuntime(Runtime::kHiddenDeclareModules, 1); + __ CallRuntime(Runtime::kDeclareModules, 1); // Return value is ignored. } @@ -1221,7 +1221,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { // For proxies, no filtering is done. // TODO(rossberg): What if only a prototype is a proxy? Not specified yet. - ASSERT_EQ(Smi::FromInt(0), 0); + DCHECK_EQ(Smi::FromInt(0), 0); __ Branch(&update_each, eq, a2, Operand(zero_reg)); // Convert the entry to a string or (smi) 0 if it isn't a property @@ -1272,27 +1272,8 @@ void FullCodeGenerator::VisitForOfStatement(ForOfStatement* stmt) { Iteration loop_statement(this, stmt); increment_loop_depth(); - // var iterator = iterable[@@iterator]() - VisitForAccumulatorValue(stmt->assign_iterator()); - __ mov(a0, v0); - - // As with for-in, skip the loop if the iterator is null or undefined. - __ LoadRoot(at, Heap::kUndefinedValueRootIndex); - __ Branch(loop_statement.break_label(), eq, a0, Operand(at)); - __ LoadRoot(at, Heap::kNullValueRootIndex); - __ Branch(loop_statement.break_label(), eq, a0, Operand(at)); - - // Convert the iterator to a JS object. - Label convert, done_convert; - __ JumpIfSmi(a0, &convert); - __ GetObjectType(a0, a1, a1); - __ Branch(&done_convert, ge, a1, Operand(FIRST_SPEC_OBJECT_TYPE)); - __ bind(&convert); - __ push(a0); - __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); - __ mov(a0, v0); - __ bind(&done_convert); - __ push(a0); + // var iterator = iterable[Symbol.iterator](); + VisitForEffect(stmt->assign_iterator()); // Loop entry. __ bind(loop_statement.continue_label()); @@ -1349,7 +1330,7 @@ void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info, __ LoadRoot(a1, pretenure ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex); __ Push(cp, a0, a1); - __ CallRuntime(Runtime::kHiddenNewClosure, 3); + __ CallRuntime(Runtime::kNewClosure, 3); } context()->Plug(v0); } @@ -1361,7 +1342,7 @@ void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { } -void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var, +void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy, TypeofState typeof_state, Label* slow) { Register current = cp; @@ -1406,8 +1387,13 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var, __ bind(&fast); } - __ lw(a0, GlobalObjectOperand()); - __ li(a2, Operand(var->name())); + __ lw(LoadIC::ReceiverRegister(), GlobalObjectOperand()); + __ li(LoadIC::NameRegister(), Operand(proxy->var()->name())); + if (FLAG_vector_ics) { + __ li(LoadIC::SlotRegister(), + Operand(Smi::FromInt(proxy->VariableFeedbackSlot()))); + } + ContextualMode mode = (typeof_state == INSIDE_TYPEOF) ? NOT_CONTEXTUAL : CONTEXTUAL; @@ -1417,7 +1403,7 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var, MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, Label* slow) { - ASSERT(var->IsContextSlot()); + DCHECK(var->IsContextSlot()); Register context = cp; Register next = a3; Register temp = t0; @@ -1445,7 +1431,7 @@ MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, } -void FullCodeGenerator::EmitDynamicLookupFastCase(Variable* var, +void FullCodeGenerator::EmitDynamicLookupFastCase(VariableProxy* proxy, TypeofState typeof_state, Label* slow, Label* done) { @@ -1454,8 +1440,9 @@ void FullCodeGenerator::EmitDynamicLookupFastCase(Variable* var, // 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(var, typeof_state, slow); + EmitLoadGlobalCheckExtensions(proxy, typeof_state, slow); __ Branch(done); } else if (var->mode() == DYNAMIC_LOCAL) { Variable* local = var->local_if_not_shadowed(); @@ -1471,7 +1458,7 @@ void FullCodeGenerator::EmitDynamicLookupFastCase(Variable* var, __ Branch(done, ne, at, Operand(zero_reg)); __ li(a0, Operand(var->name())); __ push(a0); - __ CallRuntime(Runtime::kHiddenThrowReferenceError, 1); + __ CallRuntime(Runtime::kThrowReferenceError, 1); } } __ Branch(done); @@ -1489,10 +1476,12 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { switch (var->location()) { case Variable::UNALLOCATED: { Comment cmnt(masm_, "[ Global variable"); - // Use inline caching. Variable name is passed in a2 and the global - // object (receiver) in a0. - __ lw(a0, GlobalObjectOperand()); - __ li(a2, Operand(var->name())); + __ lw(LoadIC::ReceiverRegister(), GlobalObjectOperand()); + __ li(LoadIC::NameRegister(), Operand(var->name())); + if (FLAG_vector_ics) { + __ li(LoadIC::SlotRegister(), + Operand(Smi::FromInt(proxy->VariableFeedbackSlot()))); + } CallLoadIC(CONTEXTUAL); context()->Plug(v0); break; @@ -1509,7 +1498,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { // always looked up dynamically, i.e. in that case // var->location() == LOOKUP. // always holds. - ASSERT(var->scope() != NULL); + DCHECK(var->scope() != NULL); // Check if the binding really needs an initialization check. The check // can be skipped in the following situation: we have a LET or CONST @@ -1532,8 +1521,8 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { skip_init_check = false; } else { // Check that we always have valid source position. - ASSERT(var->initializer_position() != RelocInfo::kNoPosition); - ASSERT(proxy->position() != RelocInfo::kNoPosition); + DCHECK(var->initializer_position() != RelocInfo::kNoPosition); + DCHECK(proxy->position() != RelocInfo::kNoPosition); skip_init_check = var->mode() != CONST_LEGACY && var->initializer_position() < proxy->position(); } @@ -1550,11 +1539,11 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { __ Branch(&done, ne, at, Operand(zero_reg)); __ li(a0, Operand(var->name())); __ push(a0); - __ CallRuntime(Runtime::kHiddenThrowReferenceError, 1); + __ CallRuntime(Runtime::kThrowReferenceError, 1); __ bind(&done); } else { // Uninitalized const bindings outside of harmony mode are unholed. - ASSERT(var->mode() == CONST_LEGACY); + DCHECK(var->mode() == CONST_LEGACY); __ LoadRoot(a0, Heap::kUndefinedValueRootIndex); __ Movz(v0, a0, at); // Conditional move: Undefined if TheHole. } @@ -1571,11 +1560,11 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { Label done, slow; // Generate code for loading from variables potentially shadowed // by eval-introduced variables. - EmitDynamicLookupFastCase(var, NOT_INSIDE_TYPEOF, &slow, &done); + EmitDynamicLookupFastCase(proxy, NOT_INSIDE_TYPEOF, &slow, &done); __ bind(&slow); __ li(a1, Operand(var->name())); __ Push(cp, a1); // Context and name. - __ CallRuntime(Runtime::kHiddenLoadContextSlot, 2); + __ CallRuntime(Runtime::kLoadLookupSlot, 2); __ bind(&done); context()->Plug(v0); } @@ -1607,7 +1596,7 @@ void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { __ li(a2, Operand(expr->pattern())); __ li(a1, Operand(expr->flags())); __ Push(t0, a3, a2, a1); - __ CallRuntime(Runtime::kHiddenMaterializeRegExpLiteral, 4); + __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); __ mov(t1, v0); __ bind(&materialized); @@ -1619,7 +1608,7 @@ void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { __ bind(&runtime_allocate); __ li(a0, Operand(Smi::FromInt(size))); __ Push(t1, a0); - __ CallRuntime(Runtime::kHiddenAllocateInNewSpace, 1); + __ CallRuntime(Runtime::kAllocateInNewSpace, 1); __ pop(t1); __ bind(&allocated); @@ -1661,10 +1650,10 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { __ li(a0, Operand(Smi::FromInt(flags))); int properties_count = constant_properties->length() / 2; if (expr->may_store_doubles() || expr->depth() > 1 || - Serializer::enabled(isolate()) || flags != ObjectLiteral::kFastElements || + masm()->serializer_enabled() || flags != ObjectLiteral::kFastElements || properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) { __ Push(a3, a2, a1, a0); - __ CallRuntime(Runtime::kHiddenCreateObjectLiteral, 4); + __ CallRuntime(Runtime::kCreateObjectLiteral, 4); } else { FastCloneShallowObjectStub stub(isolate(), properties_count); __ CallStub(&stub); @@ -1694,15 +1683,16 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { case ObjectLiteral::Property::CONSTANT: UNREACHABLE(); case ObjectLiteral::Property::MATERIALIZED_LITERAL: - ASSERT(!CompileTimeValue::IsCompileTimeValue(property->value())); + DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value())); // Fall through. case ObjectLiteral::Property::COMPUTED: if (key->value()->IsInternalizedString()) { if (property->emit_store()) { VisitForAccumulatorValue(value); - __ mov(a0, result_register()); - __ li(a2, Operand(key->value())); - __ lw(a1, MemOperand(sp)); + __ mov(StoreIC::ValueRegister(), result_register()); + DCHECK(StoreIC::ValueRegister().is(a0)); + __ li(StoreIC::NameRegister(), Operand(key->value())); + __ lw(StoreIC::ReceiverRegister(), MemOperand(sp)); CallStoreIC(key->LiteralFeedbackId()); PrepareForBailoutForId(key->id(), NO_REGISTERS); } else { @@ -1716,7 +1706,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { VisitForStackValue(key); VisitForStackValue(value); if (property->emit_store()) { - __ li(a0, Operand(Smi::FromInt(NONE))); // PropertyAttributes. + __ li(a0, Operand(Smi::FromInt(SLOPPY))); // PropertyAttributes. __ push(a0); __ CallRuntime(Runtime::kSetProperty, 4); } else { @@ -1755,11 +1745,11 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { EmitAccessor(it->second->setter); __ li(a0, Operand(Smi::FromInt(NONE))); __ push(a0); - __ CallRuntime(Runtime::kDefineOrRedefineAccessorProperty, 5); + __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5); } if (expr->has_function()) { - ASSERT(result_saved); + DCHECK(result_saved); __ lw(a0, MemOperand(sp)); __ push(a0); __ CallRuntime(Runtime::kToFastProperties, 1); @@ -1785,7 +1775,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { int length = subexprs->length(); Handle<FixedArray> constant_elements = expr->constant_elements(); - ASSERT_EQ(2, constant_elements->length()); + DCHECK_EQ(2, constant_elements->length()); ElementsKind constant_elements_kind = static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value()); bool has_fast_elements = @@ -1805,33 +1795,12 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { __ lw(a3, FieldMemOperand(a3, JSFunction::kLiteralsOffset)); __ li(a2, Operand(Smi::FromInt(expr->literal_index()))); __ li(a1, Operand(constant_elements)); - if (has_fast_elements && constant_elements_values->map() == - isolate()->heap()->fixed_cow_array_map()) { - FastCloneShallowArrayStub stub( - isolate(), - FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, - allocation_site_mode, - length); - __ CallStub(&stub); - __ IncrementCounter(isolate()->counters()->cow_arrays_created_stub(), - 1, a1, a2); - } else if (expr->depth() > 1 || Serializer::enabled(isolate()) || - length > FastCloneShallowArrayStub::kMaximumClonedLength) { + if (expr->depth() > 1 || length > JSObject::kInitialMaxFastElementArray) { __ li(a0, Operand(Smi::FromInt(flags))); __ Push(a3, a2, a1, a0); - __ CallRuntime(Runtime::kHiddenCreateArrayLiteral, 4); + __ CallRuntime(Runtime::kCreateArrayLiteral, 4); } else { - ASSERT(IsFastSmiOrObjectElementsKind(constant_elements_kind) || - FLAG_smi_only_arrays); - FastCloneShallowArrayStub::Mode mode = - FastCloneShallowArrayStub::CLONE_ANY_ELEMENTS; - - if (has_fast_elements) { - mode = FastCloneShallowArrayStub::CLONE_ELEMENTS; - } - - FastCloneShallowArrayStub stub(isolate(), mode, allocation_site_mode, - length); + FastCloneShallowArrayStub stub(isolate(), allocation_site_mode); __ CallStub(&stub); } @@ -1881,7 +1850,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { void FullCodeGenerator::VisitAssignment(Assignment* expr) { - ASSERT(expr->target()->IsValidReferenceExpression()); + DCHECK(expr->target()->IsValidReferenceExpression()); Comment cmnt(masm_, "[ Assignment"); @@ -1903,9 +1872,9 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { break; case NAMED_PROPERTY: if (expr->is_compound()) { - // We need the receiver both on the stack and in the accumulator. - VisitForAccumulatorValue(property->obj()); - __ push(result_register()); + // We need the receiver both on the stack and in the register. + VisitForStackValue(property->obj()); + __ lw(LoadIC::ReceiverRegister(), MemOperand(sp, 0)); } else { VisitForStackValue(property->obj()); } @@ -1914,9 +1883,9 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { // We need the key and receiver on both the stack and in v0 and a1. if (expr->is_compound()) { VisitForStackValue(property->obj()); - VisitForAccumulatorValue(property->key()); - __ lw(a1, MemOperand(sp, 0)); - __ push(v0); + VisitForStackValue(property->key()); + __ lw(LoadIC::ReceiverRegister(), MemOperand(sp, 1 * kPointerSize)); + __ lw(LoadIC::NameRegister(), MemOperand(sp, 0)); } else { VisitForStackValue(property->obj()); VisitForStackValue(property->key()); @@ -2012,7 +1981,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) { __ bind(&suspend); VisitForAccumulatorValue(expr->generator_object()); - ASSERT(continuation.pos() > 0 && Smi::IsValid(continuation.pos())); + DCHECK(continuation.pos() > 0 && Smi::IsValid(continuation.pos())); __ li(a1, Operand(Smi::FromInt(continuation.pos()))); __ sw(a1, FieldMemOperand(v0, JSGeneratorObject::kContinuationOffset)); __ sw(cp, FieldMemOperand(v0, JSGeneratorObject::kContextOffset)); @@ -2022,7 +1991,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) { __ Addu(a1, fp, Operand(StandardFrameConstants::kExpressionsOffset)); __ Branch(&post_runtime, eq, sp, Operand(a1)); __ push(v0); // generator object - __ CallRuntime(Runtime::kHiddenSuspendJSGeneratorObject, 1); + __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); __ bind(&post_runtime); __ pop(result_register()); @@ -2053,7 +2022,10 @@ void FullCodeGenerator::VisitYield(Yield* expr) { // [sp + 0 * kPointerSize] g Label l_catch, l_try, l_suspend, l_continuation, l_resume; - Label l_next, l_call, l_loop; + Label l_next, l_call; + Register load_receiver = LoadIC::ReceiverRegister(); + Register load_name = LoadIC::NameRegister(); + // Initial send value is undefined. __ LoadRoot(a0, Heap::kUndefinedValueRootIndex); __ Branch(&l_next); @@ -2062,9 +2034,9 @@ void FullCodeGenerator::VisitYield(Yield* expr) { __ bind(&l_catch); __ mov(a0, v0); handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos())); - __ LoadRoot(a2, Heap::kthrow_stringRootIndex); // "throw" - __ lw(a3, MemOperand(sp, 1 * kPointerSize)); // iter - __ Push(a2, a3, a0); // "throw", iter, except + __ LoadRoot(load_name, Heap::kthrow_stringRootIndex); // "throw" + __ lw(a3, MemOperand(sp, 1 * kPointerSize)); // iter + __ Push(load_name, a3, a0); // "throw", iter, except __ jmp(&l_call); // try { received = %yield result } @@ -2083,14 +2055,14 @@ void FullCodeGenerator::VisitYield(Yield* expr) { const int generator_object_depth = kPointerSize + handler_size; __ lw(a0, MemOperand(sp, generator_object_depth)); __ push(a0); // g - ASSERT(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos())); + DCHECK(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos())); __ li(a1, Operand(Smi::FromInt(l_continuation.pos()))); __ sw(a1, FieldMemOperand(a0, JSGeneratorObject::kContinuationOffset)); __ sw(cp, FieldMemOperand(a0, JSGeneratorObject::kContextOffset)); __ mov(a1, cp); __ RecordWriteField(a0, JSGeneratorObject::kContextOffset, a1, a2, kRAHasBeenSaved, kDontSaveFPRegs); - __ CallRuntime(Runtime::kHiddenSuspendJSGeneratorObject, 1); + __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); __ pop(v0); // result EmitReturnSequence(); @@ -2100,14 +2072,19 @@ void FullCodeGenerator::VisitYield(Yield* expr) { // receiver = iter; f = 'next'; arg = received; __ bind(&l_next); - __ LoadRoot(a2, Heap::knext_stringRootIndex); // "next" - __ lw(a3, MemOperand(sp, 1 * kPointerSize)); // iter - __ Push(a2, a3, a0); // "next", iter, received + + __ LoadRoot(load_name, Heap::knext_stringRootIndex); // "next" + __ lw(a3, MemOperand(sp, 1 * kPointerSize)); // iter + __ Push(load_name, a3, a0); // "next", iter, received // result = receiver[f](arg); __ bind(&l_call); - __ lw(a1, MemOperand(sp, kPointerSize)); - __ lw(a0, MemOperand(sp, 2 * kPointerSize)); + __ lw(load_receiver, MemOperand(sp, kPointerSize)); + __ lw(load_name, MemOperand(sp, 2 * kPointerSize)); + if (FLAG_vector_ics) { + __ li(LoadIC::SlotRegister(), + Operand(Smi::FromInt(expr->KeyedLoadFeedbackSlot()))); + } Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); CallIC(ic, TypeFeedbackId::None()); __ mov(a0, v0); @@ -2120,21 +2097,29 @@ void FullCodeGenerator::VisitYield(Yield* expr) { __ Drop(1); // The function is still on the stack; drop it. // if (!result.done) goto l_try; - __ bind(&l_loop); - __ mov(a0, v0); - __ push(a0); // save result - __ LoadRoot(a2, Heap::kdone_stringRootIndex); // "done" - CallLoadIC(NOT_CONTEXTUAL); // result.done in v0 + __ Move(load_receiver, v0); + + __ push(load_receiver); // save result + __ LoadRoot(load_name, Heap::kdone_stringRootIndex); // "done" + if (FLAG_vector_ics) { + __ li(LoadIC::SlotRegister(), + Operand(Smi::FromInt(expr->DoneFeedbackSlot()))); + } + CallLoadIC(NOT_CONTEXTUAL); // v0=result.done __ mov(a0, v0); Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate()); CallIC(bool_ic); __ Branch(&l_try, eq, v0, Operand(zero_reg)); // result.value - __ pop(a0); // result - __ LoadRoot(a2, Heap::kvalue_stringRootIndex); // "value" - CallLoadIC(NOT_CONTEXTUAL); // result.value in v0 - context()->DropAndPlug(2, v0); // drop iter and g + __ pop(load_receiver); // result + __ LoadRoot(load_name, Heap::kvalue_stringRootIndex); // "value" + if (FLAG_vector_ics) { + __ li(LoadIC::SlotRegister(), + Operand(Smi::FromInt(expr->ValueFeedbackSlot()))); + } + CallLoadIC(NOT_CONTEXTUAL); // v0=result.value + context()->DropAndPlug(2, v0); // drop iter and g break; } } @@ -2145,7 +2130,7 @@ void FullCodeGenerator::EmitGeneratorResume(Expression *generator, Expression *value, JSGeneratorObject::ResumeMode resume_mode) { // The value stays in a0, and is ultimately read by the resumed generator, as - // if CallRuntime(Runtime::kHiddenSuspendJSGeneratorObject) returned it. Or it + // if CallRuntime(Runtime::kSuspendJSGeneratorObject) returned it. Or it // is read to throw the value when the resumed generator is already closed. // a1 will hold the generator object until the activation has been resumed. VisitForStackValue(generator); @@ -2224,10 +2209,10 @@ void FullCodeGenerator::EmitGeneratorResume(Expression *generator, __ push(a2); __ Branch(&push_operand_holes); __ bind(&call_resume); - ASSERT(!result_register().is(a1)); + DCHECK(!result_register().is(a1)); __ Push(a1, result_register()); __ Push(Smi::FromInt(resume_mode)); - __ CallRuntime(Runtime::kHiddenResumeJSGeneratorObject, 3); + __ CallRuntime(Runtime::kResumeJSGeneratorObject, 3); // Not reached: the runtime call returns elsewhere. __ stop("not-reached"); @@ -2242,14 +2227,14 @@ void FullCodeGenerator::EmitGeneratorResume(Expression *generator, } else { // Throw the provided value. __ push(a0); - __ CallRuntime(Runtime::kHiddenThrow, 1); + __ CallRuntime(Runtime::kThrow, 1); } __ jmp(&done); // Throw error if we attempt to operate on a running generator. __ bind(&wrong_state); __ push(a1); - __ CallRuntime(Runtime::kHiddenThrowGeneratorStateError, 1); + __ CallRuntime(Runtime::kThrowGeneratorStateError, 1); __ bind(&done); context()->Plug(result_register()); @@ -2267,7 +2252,7 @@ void FullCodeGenerator::EmitCreateIteratorResult(bool done) { __ bind(&gc_required); __ Push(Smi::FromInt(map->instance_size())); - __ CallRuntime(Runtime::kHiddenAllocateInNewSpace, 1); + __ CallRuntime(Runtime::kAllocateInNewSpace, 1); __ lw(context_register(), MemOperand(fp, StandardFrameConstants::kContextOffset)); @@ -2276,7 +2261,7 @@ void FullCodeGenerator::EmitCreateIteratorResult(bool done) { __ pop(a2); __ li(a3, Operand(isolate()->factory()->ToBoolean(done))); __ li(t0, Operand(isolate()->factory()->empty_fixed_array())); - ASSERT_EQ(map->instance_size(), 5 * kPointerSize); + DCHECK_EQ(map->instance_size(), 5 * kPointerSize); __ sw(a1, FieldMemOperand(v0, HeapObject::kMapOffset)); __ sw(t0, FieldMemOperand(v0, JSObject::kPropertiesOffset)); __ sw(t0, FieldMemOperand(v0, JSObject::kElementsOffset)); @@ -2295,19 +2280,27 @@ void FullCodeGenerator::EmitCreateIteratorResult(bool done) { void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { SetSourcePosition(prop->position()); Literal* key = prop->key()->AsLiteral(); - __ mov(a0, result_register()); - __ li(a2, Operand(key->value())); - // Call load IC. It has arguments receiver and property name a0 and a2. - CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId()); + __ li(LoadIC::NameRegister(), Operand(key->value())); + if (FLAG_vector_ics) { + __ li(LoadIC::SlotRegister(), + Operand(Smi::FromInt(prop->PropertyFeedbackSlot()))); + CallLoadIC(NOT_CONTEXTUAL); + } else { + CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId()); + } } void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { SetSourcePosition(prop->position()); - __ mov(a0, result_register()); - // Call keyed load IC. It has arguments key and receiver in a0 and a1. Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); - CallIC(ic, prop->PropertyFeedbackId()); + if (FLAG_vector_ics) { + __ li(LoadIC::SlotRegister(), + Operand(Smi::FromInt(prop->PropertyFeedbackSlot()))); + CallIC(ic); + } else { + CallIC(ic, prop->PropertyFeedbackId()); + } } @@ -2385,7 +2378,7 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, __ Branch(&done, ne, v0, Operand(zero_reg)); __ Addu(scratch2, right, left); __ Branch(&stub_call, lt, scratch2, Operand(zero_reg)); - ASSERT(Smi::FromInt(0) == 0); + DCHECK(Smi::FromInt(0) == 0); __ mov(v0, zero_reg); break; } @@ -2421,7 +2414,7 @@ void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, void FullCodeGenerator::EmitAssignment(Expression* expr) { - ASSERT(expr->IsValidReferenceExpression()); + DCHECK(expr->IsValidReferenceExpression()); // Left-hand side can only be a property, a global or a (parameter or local) // slot. @@ -2444,9 +2437,10 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) { case NAMED_PROPERTY: { __ push(result_register()); // Preserve value. VisitForAccumulatorValue(prop->obj()); - __ mov(a1, result_register()); - __ pop(a0); // Restore value. - __ li(a2, Operand(prop->key()->AsLiteral()->value())); + __ mov(StoreIC::ReceiverRegister(), result_register()); + __ pop(StoreIC::ValueRegister()); // Restore value. + __ li(StoreIC::NameRegister(), + Operand(prop->key()->AsLiteral()->value())); CallStoreIC(); break; } @@ -2454,8 +2448,8 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) { __ push(result_register()); // Preserve value. VisitForStackValue(prop->obj()); VisitForAccumulatorValue(prop->key()); - __ mov(a1, result_register()); - __ Pop(a0, a2); // a0 = restored value. + __ mov(KeyedStoreIC::NameRegister(), result_register()); + __ Pop(KeyedStoreIC::ValueRegister(), KeyedStoreIC::ReceiverRegister()); Handle<Code> ic = strict_mode() == SLOPPY ? isolate()->builtins()->KeyedStoreIC_Initialize() : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); @@ -2480,32 +2474,23 @@ void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot( } -void FullCodeGenerator::EmitCallStoreContextSlot( - Handle<String> name, StrictMode strict_mode) { - __ li(a1, Operand(name)); - __ li(a0, Operand(Smi::FromInt(strict_mode))); - __ Push(v0, cp, a1, a0); // Value, context, name, strict mode. - __ CallRuntime(Runtime::kHiddenStoreContextSlot, 4); -} - - void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op) { if (var->IsUnallocated()) { // Global var, const, or let. - __ mov(a0, result_register()); - __ li(a2, Operand(var->name())); - __ lw(a1, GlobalObjectOperand()); + __ mov(StoreIC::ValueRegister(), result_register()); + __ li(StoreIC::NameRegister(), Operand(var->name())); + __ lw(StoreIC::ReceiverRegister(), GlobalObjectOperand()); CallStoreIC(); } else if (op == Token::INIT_CONST_LEGACY) { // Const initializers need a write barrier. - ASSERT(!var->IsParameter()); // No const parameters. + DCHECK(!var->IsParameter()); // No const parameters. if (var->IsLookupSlot()) { __ li(a0, Operand(var->name())); __ Push(v0, cp, a0); // Context and name. - __ CallRuntime(Runtime::kHiddenInitializeConstContextSlot, 3); + __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot, 3); } else { - ASSERT(var->IsStackAllocated() || var->IsContextSlot()); + DCHECK(var->IsStackAllocated() || var->IsContextSlot()); Label skip; MemOperand location = VarOperand(var, a1); __ lw(a2, location); @@ -2517,30 +2502,31 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op) { } else if (var->mode() == LET && op != Token::INIT_LET) { // Non-initializing assignment to let variable needs a write barrier. - if (var->IsLookupSlot()) { - EmitCallStoreContextSlot(var->name(), strict_mode()); - } else { - ASSERT(var->IsStackAllocated() || var->IsContextSlot()); - Label assign; - MemOperand location = VarOperand(var, a1); - __ lw(a3, location); - __ LoadRoot(t0, Heap::kTheHoleValueRootIndex); - __ Branch(&assign, ne, a3, Operand(t0)); - __ li(a3, Operand(var->name())); - __ push(a3); - __ CallRuntime(Runtime::kHiddenThrowReferenceError, 1); - // Perform the assignment. - __ bind(&assign); - EmitStoreToStackLocalOrContextSlot(var, location); - } + DCHECK(!var->IsLookupSlot()); + DCHECK(var->IsStackAllocated() || var->IsContextSlot()); + Label assign; + MemOperand location = VarOperand(var, a1); + __ lw(a3, location); + __ LoadRoot(t0, Heap::kTheHoleValueRootIndex); + __ Branch(&assign, ne, a3, Operand(t0)); + __ li(a3, Operand(var->name())); + __ push(a3); + __ CallRuntime(Runtime::kThrowReferenceError, 1); + // Perform the assignment. + __ bind(&assign); + EmitStoreToStackLocalOrContextSlot(var, location); } else if (!var->is_const_mode() || op == Token::INIT_CONST) { - // Assignment to var or initializing assignment to let/const - // in harmony mode. if (var->IsLookupSlot()) { - EmitCallStoreContextSlot(var->name(), strict_mode()); + // Assignment to var. + __ li(a1, Operand(var->name())); + __ li(a0, Operand(Smi::FromInt(strict_mode()))); + __ Push(v0, cp, a1, a0); // Value, context, name, strict mode. + __ CallRuntime(Runtime::kStoreLookupSlot, 4); } else { - ASSERT((var->IsStackAllocated() || var->IsContextSlot())); + // Assignment to var or initializing assignment to let/const in harmony + // mode. + DCHECK((var->IsStackAllocated() || var->IsContextSlot())); MemOperand location = VarOperand(var, a1); if (generate_debug_code_ && op == Token::INIT_LET) { // Check for an uninitialized let binding. @@ -2558,15 +2544,14 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op) { void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { // Assignment to a property, using a named store IC. Property* prop = expr->target()->AsProperty(); - ASSERT(prop != NULL); - ASSERT(prop->key()->AsLiteral() != NULL); + DCHECK(prop != NULL); + DCHECK(prop->key()->IsLiteral()); // Record source code position before IC call. SetSourcePosition(expr->position()); - __ mov(a0, result_register()); // Load the value. - __ li(a2, Operand(prop->key()->AsLiteral()->value())); - __ pop(a1); - + __ mov(StoreIC::ValueRegister(), result_register()); + __ li(StoreIC::NameRegister(), Operand(prop->key()->AsLiteral()->value())); + __ pop(StoreIC::ReceiverRegister()); CallStoreIC(expr->AssignmentFeedbackId()); PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); @@ -2584,8 +2569,9 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { // - a0 is the value, // - a1 is the key, // - a2 is the receiver. - __ mov(a0, result_register()); - __ Pop(a2, a1); // a1 = key. + __ mov(KeyedStoreIC::ValueRegister(), result_register()); + __ Pop(KeyedStoreIC::ReceiverRegister(), KeyedStoreIC::NameRegister()); + DCHECK(KeyedStoreIC::ValueRegister().is(a0)); Handle<Code> ic = strict_mode() == SLOPPY ? isolate()->builtins()->KeyedStoreIC_Initialize() @@ -2603,13 +2589,15 @@ void FullCodeGenerator::VisitProperty(Property* expr) { if (key->IsPropertyName()) { VisitForAccumulatorValue(expr->obj()); + __ Move(LoadIC::ReceiverRegister(), v0); EmitNamedPropertyLoad(expr); PrepareForBailoutForId(expr->LoadId(), TOS_REG); context()->Plug(v0); } else { VisitForStackValue(expr->obj()); VisitForAccumulatorValue(expr->key()); - __ pop(a1); + __ Move(LoadIC::NameRegister(), v0); + __ pop(LoadIC::ReceiverRegister()); EmitKeyedPropertyLoad(expr); context()->Plug(v0); } @@ -2642,8 +2630,8 @@ void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) { __ Push(isolate()->factory()->undefined_value()); } else { // Load the function from the receiver. - ASSERT(callee->IsProperty()); - __ lw(v0, MemOperand(sp, 0)); + DCHECK(callee->IsProperty()); + __ lw(LoadIC::ReceiverRegister(), MemOperand(sp, 0)); EmitNamedPropertyLoad(callee->AsProperty()); PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); // Push the target function under the receiver. @@ -2665,8 +2653,9 @@ void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr, Expression* callee = expr->expression(); // Load the function from the receiver. - ASSERT(callee->IsProperty()); - __ lw(a1, MemOperand(sp, 0)); + DCHECK(callee->IsProperty()); + __ lw(LoadIC::ReceiverRegister(), MemOperand(sp, 0)); + __ Move(LoadIC::NameRegister(), v0); EmitKeyedPropertyLoad(callee->AsProperty()); PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); @@ -2726,7 +2715,7 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) { // Do the runtime call. __ Push(t2, t1, t0, a1); - __ CallRuntime(Runtime::kHiddenResolvePossiblyDirectEval, 5); + __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5); } @@ -2789,16 +2778,16 @@ void FullCodeGenerator::VisitCall(Call* expr) { { PreservePositionScope scope(masm()->positions_recorder()); // Generate code for loading from variables potentially shadowed // by eval-introduced variables. - EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); + EmitDynamicLookupFastCase(proxy, 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). - ASSERT(!context_register().is(a2)); + DCHECK(!context_register().is(a2)); __ li(a2, Operand(proxy->name())); __ Push(context_register(), a2); - __ CallRuntime(Runtime::kHiddenLoadContextSlot, 2); + __ CallRuntime(Runtime::kLoadLookupSlot, 2); __ Push(v0, v1); // Function, receiver. // If fast case code has been generated, emit code to push the @@ -2831,7 +2820,7 @@ void FullCodeGenerator::VisitCall(Call* expr) { EmitKeyedCallWithLoadIC(expr, property->key()); } } else { - ASSERT(call_type == Call::OTHER_CALL); + DCHECK(call_type == Call::OTHER_CALL); // Call to an arbitrary expression not handled specially above. { PreservePositionScope scope(masm()->positions_recorder()); VisitForStackValue(callee); @@ -2844,7 +2833,7 @@ void FullCodeGenerator::VisitCall(Call* expr) { #ifdef DEBUG // RecordJSReturnSite should have been called. - ASSERT(expr->return_is_recorded_); + DCHECK(expr->return_is_recorded_); #endif } @@ -2878,7 +2867,7 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) { // Record call targets in unoptimized code. if (FLAG_pretenuring_call_new) { EnsureSlotContainsAllocationSite(expr->AllocationSiteFeedbackSlot()); - ASSERT(expr->AllocationSiteFeedbackSlot() == + DCHECK(expr->AllocationSiteFeedbackSlot() == expr->CallNewFeedbackSlot() + 1); } @@ -2894,7 +2883,7 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) { void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { ZoneList<Expression*>* args = expr->arguments(); - ASSERT(args->length() == 1); + DCHECK(args->length() == 1); VisitForAccumulatorValue(args->at(0)); @@ -2915,7 +2904,7 @@ void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { void FullCodeGenerator::EmitIsNonNegativeSmi(CallRuntime* expr) { ZoneList<Expression*>* args = expr->arguments(); - ASSERT(args->length() == 1); + DCHECK(args->length() == 1); VisitForAccumulatorValue(args->at(0)); @@ -2936,7 +2925,7 @@ void FullCodeGenerator::EmitIsNonNegativeSmi(CallRuntime* expr) { void FullCodeGenerator::EmitIsObject(CallRuntime* expr) { ZoneList<Expression*>* args = expr->arguments(); - ASSERT(args->length() == 1); + DCHECK(args->length() == 1); VisitForAccumulatorValue(args->at(0)); @@ -2967,7 +2956,7 @@ void FullCodeGenerator::EmitIsObject(CallRuntime* expr) { void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) { ZoneList<Expression*>* args = expr->arguments(); - ASSERT(args->length() == 1); + DCHECK(args->length() == 1); VisitForAccumulatorValue(args->at(0)); @@ -2990,7 +2979,7 @@ void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) { void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) { ZoneList<Expression*>* args = expr->arguments(); - ASSERT(args->length() == 1); + DCHECK(args->length() == 1); VisitForAccumulatorValue(args->at(0)); @@ -3015,7 +3004,7 @@ void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) { void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( CallRuntime* expr) { ZoneList<Expression*>* args = expr->arguments(); - ASSERT(args->length() == 1); + DCHECK(args->length() == 1); VisitForAccumulatorValue(args->at(0)); @@ -3060,7 +3049,7 @@ void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( __ Addu(t0, t0, Operand(DescriptorArray::kFirstOffset - kHeapObjectTag)); // Calculate the end of the descriptor array. __ mov(a2, t0); - __ sll(t1, a3, kPointerSizeLog2 - kSmiTagSize); + __ sll(t1, a3, kPointerSizeLog2); __ Addu(a2, a2, t1); // Loop through all the keys in the descriptor array. If one of these is the @@ -3102,7 +3091,7 @@ void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) { ZoneList<Expression*>* args = expr->arguments(); - ASSERT(args->length() == 1); + DCHECK(args->length() == 1); VisitForAccumulatorValue(args->at(0)); @@ -3125,7 +3114,7 @@ void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) { void FullCodeGenerator::EmitIsMinusZero(CallRuntime* expr) { ZoneList<Expression*>* args = expr->arguments(); - ASSERT(args->length() == 1); + DCHECK(args->length() == 1); VisitForAccumulatorValue(args->at(0)); @@ -3155,7 +3144,7 @@ void FullCodeGenerator::EmitIsMinusZero(CallRuntime* expr) { void FullCodeGenerator::EmitIsArray(CallRuntime* expr) { ZoneList<Expression*>* args = expr->arguments(); - ASSERT(args->length() == 1); + DCHECK(args->length() == 1); VisitForAccumulatorValue(args->at(0)); @@ -3178,7 +3167,7 @@ void FullCodeGenerator::EmitIsArray(CallRuntime* expr) { void FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) { ZoneList<Expression*>* args = expr->arguments(); - ASSERT(args->length() == 1); + DCHECK(args->length() == 1); VisitForAccumulatorValue(args->at(0)); @@ -3199,7 +3188,7 @@ void FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) { void FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) { - ASSERT(expr->arguments()->length() == 0); + DCHECK(expr->arguments()->length() == 0); Label materialize_true, materialize_false; Label* if_true = NULL; @@ -3231,7 +3220,7 @@ void FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) { void FullCodeGenerator::EmitObjectEquals(CallRuntime* expr) { ZoneList<Expression*>* args = expr->arguments(); - ASSERT(args->length() == 2); + DCHECK(args->length() == 2); // Load the two objects into registers and perform the comparison. VisitForStackValue(args->at(0)); @@ -3254,7 +3243,7 @@ void FullCodeGenerator::EmitObjectEquals(CallRuntime* expr) { void FullCodeGenerator::EmitArguments(CallRuntime* expr) { ZoneList<Expression*>* args = expr->arguments(); - ASSERT(args->length() == 1); + DCHECK(args->length() == 1); // ArgumentsAccessStub expects the key in a1 and the formal // parameter count in a0. @@ -3268,7 +3257,7 @@ void FullCodeGenerator::EmitArguments(CallRuntime* expr) { void FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) { - ASSERT(expr->arguments()->length() == 0); + DCHECK(expr->arguments()->length() == 0); Label exit; // Get the number of formal parameters. __ li(v0, Operand(Smi::FromInt(info_->scope()->num_parameters()))); @@ -3290,7 +3279,7 @@ void FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) { void FullCodeGenerator::EmitClassOf(CallRuntime* expr) { ZoneList<Expression*>* args = expr->arguments(); - ASSERT(args->length() == 1); + DCHECK(args->length() == 1); Label done, null, function, non_function_constructor; VisitForAccumulatorValue(args->at(0)); @@ -3352,7 +3341,7 @@ void FullCodeGenerator::EmitSubString(CallRuntime* expr) { // Load the arguments on the stack and call the stub. SubStringStub stub(isolate()); ZoneList<Expression*>* args = expr->arguments(); - ASSERT(args->length() == 3); + DCHECK(args->length() == 3); VisitForStackValue(args->at(0)); VisitForStackValue(args->at(1)); VisitForStackValue(args->at(2)); @@ -3365,7 +3354,7 @@ void FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) { // Load the arguments on the stack and call the stub. RegExpExecStub stub(isolate()); ZoneList<Expression*>* args = expr->arguments(); - ASSERT(args->length() == 4); + DCHECK(args->length() == 4); VisitForStackValue(args->at(0)); VisitForStackValue(args->at(1)); VisitForStackValue(args->at(2)); @@ -3377,7 +3366,7 @@ void FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) { void FullCodeGenerator::EmitValueOf(CallRuntime* expr) { ZoneList<Expression*>* args = expr->arguments(); - ASSERT(args->length() == 1); + DCHECK(args->length() == 1); VisitForAccumulatorValue(args->at(0)); // Load the object. @@ -3397,8 +3386,8 @@ void FullCodeGenerator::EmitValueOf(CallRuntime* expr) { void FullCodeGenerator::EmitDateField(CallRuntime* expr) { ZoneList<Expression*>* args = expr->arguments(); - ASSERT(args->length() == 2); - ASSERT_NE(NULL, args->at(1)->AsLiteral()); + DCHECK(args->length() == 2); + DCHECK_NE(NULL, args->at(1)->AsLiteral()); Smi* index = Smi::cast(*(args->at(1)->AsLiteral()->value())); VisitForAccumulatorValue(args->at(0)); // Load the object. @@ -3436,7 +3425,7 @@ void FullCodeGenerator::EmitDateField(CallRuntime* expr) { } __ bind(¬_date_object); - __ CallRuntime(Runtime::kHiddenThrowNotDateError, 0); + __ CallRuntime(Runtime::kThrowNotDateError, 0); __ bind(&done); context()->Plug(v0); } @@ -3444,7 +3433,7 @@ void FullCodeGenerator::EmitDateField(CallRuntime* expr) { void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) { ZoneList<Expression*>* args = expr->arguments(); - ASSERT_EQ(3, args->length()); + DCHECK_EQ(3, args->length()); Register string = v0; Register index = a1; @@ -3481,7 +3470,7 @@ void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) { void FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) { ZoneList<Expression*>* args = expr->arguments(); - ASSERT_EQ(3, args->length()); + DCHECK_EQ(3, args->length()); Register string = v0; Register index = a1; @@ -3519,7 +3508,7 @@ void FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) { void FullCodeGenerator::EmitMathPow(CallRuntime* expr) { // Load the arguments on the stack and call the runtime function. ZoneList<Expression*>* args = expr->arguments(); - ASSERT(args->length() == 2); + DCHECK(args->length() == 2); VisitForStackValue(args->at(0)); VisitForStackValue(args->at(1)); MathPowStub stub(isolate(), MathPowStub::ON_STACK); @@ -3530,7 +3519,7 @@ void FullCodeGenerator::EmitMathPow(CallRuntime* expr) { void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) { ZoneList<Expression*>* args = expr->arguments(); - ASSERT(args->length() == 2); + DCHECK(args->length() == 2); VisitForStackValue(args->at(0)); // Load the object. VisitForAccumulatorValue(args->at(1)); // Load the value. @@ -3559,7 +3548,7 @@ void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) { void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) { ZoneList<Expression*>* args = expr->arguments(); - ASSERT_EQ(args->length(), 1); + DCHECK_EQ(args->length(), 1); // Load the argument into a0 and call the stub. VisitForAccumulatorValue(args->at(0)); @@ -3573,7 +3562,7 @@ void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) { void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) { ZoneList<Expression*>* args = expr->arguments(); - ASSERT(args->length() == 1); + DCHECK(args->length() == 1); VisitForAccumulatorValue(args->at(0)); @@ -3592,7 +3581,7 @@ void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) { void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) { ZoneList<Expression*>* args = expr->arguments(); - ASSERT(args->length() == 2); + DCHECK(args->length() == 2); VisitForStackValue(args->at(0)); VisitForAccumulatorValue(args->at(1)); @@ -3639,7 +3628,7 @@ void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) { void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) { ZoneList<Expression*>* args = expr->arguments(); - ASSERT(args->length() == 2); + DCHECK(args->length() == 2); VisitForStackValue(args->at(0)); VisitForAccumulatorValue(args->at(1)); @@ -3688,7 +3677,7 @@ void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) { void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) { ZoneList<Expression*>* args = expr->arguments(); - ASSERT_EQ(2, args->length()); + DCHECK_EQ(2, args->length()); VisitForStackValue(args->at(0)); VisitForAccumulatorValue(args->at(1)); @@ -3702,7 +3691,7 @@ void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) { void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) { ZoneList<Expression*>* args = expr->arguments(); - ASSERT_EQ(2, args->length()); + DCHECK_EQ(2, args->length()); VisitForStackValue(args->at(0)); VisitForStackValue(args->at(1)); @@ -3715,7 +3704,7 @@ void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) { void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) { ZoneList<Expression*>* args = expr->arguments(); - ASSERT(args->length() >= 2); + DCHECK(args->length() >= 2); int arg_count = args->length() - 2; // 2 ~ receiver and function. for (int i = 0; i < arg_count + 1; i++) { @@ -3748,7 +3737,7 @@ void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) { void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) { RegExpConstructResultStub stub(isolate()); ZoneList<Expression*>* args = expr->arguments(); - ASSERT(args->length() == 3); + DCHECK(args->length() == 3); VisitForStackValue(args->at(0)); VisitForStackValue(args->at(1)); VisitForAccumulatorValue(args->at(2)); @@ -3762,9 +3751,9 @@ void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) { void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) { ZoneList<Expression*>* args = expr->arguments(); - ASSERT_EQ(2, args->length()); + DCHECK_EQ(2, args->length()); - ASSERT_NE(NULL, args->at(0)->AsLiteral()); + DCHECK_NE(NULL, args->at(0)->AsLiteral()); int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->value()))->value(); Handle<FixedArray> jsfunction_result_caches( @@ -3807,7 +3796,7 @@ void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) { __ bind(¬_found); // Call runtime to perform the lookup. __ Push(cache, key); - __ CallRuntime(Runtime::kHiddenGetFromCache, 2); + __ CallRuntime(Runtime::kGetFromCache, 2); __ bind(&done); context()->Plug(v0); @@ -3837,7 +3826,7 @@ void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) { void FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) { ZoneList<Expression*>* args = expr->arguments(); - ASSERT(args->length() == 1); + DCHECK(args->length() == 1); VisitForAccumulatorValue(args->at(0)); __ AssertString(v0); @@ -3855,7 +3844,7 @@ void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) { empty_separator_loop, one_char_separator_loop, one_char_separator_loop_entry, long_separator_loop; ZoneList<Expression*>* args = expr->arguments(); - ASSERT(args->length() == 2); + DCHECK(args->length() == 2); VisitForStackValue(args->at(1)); VisitForAccumulatorValue(args->at(0)); @@ -4016,7 +4005,7 @@ void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) { __ CopyBytes(string, result_pos, string_length, scratch1); // End while (element < elements_end). __ Branch(&empty_separator_loop, lt, element, Operand(elements_end)); - ASSERT(result.is(v0)); + DCHECK(result.is(v0)); __ Branch(&done); // One-character separator case. @@ -4048,7 +4037,7 @@ void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) { __ CopyBytes(string, result_pos, string_length, scratch1); // End while (element < elements_end). __ Branch(&one_char_separator_loop, lt, element, Operand(elements_end)); - ASSERT(result.is(v0)); + DCHECK(result.is(v0)); __ Branch(&done); // Long separator case (separator is more than one character). Entry is at the @@ -4077,7 +4066,7 @@ void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) { __ CopyBytes(string, result_pos, string_length, scratch1); // End while (element < elements_end). __ Branch(&long_separator_loop, lt, element, Operand(elements_end)); - ASSERT(result.is(v0)); + DCHECK(result.is(v0)); __ Branch(&done); __ bind(&bailout); @@ -4087,6 +4076,17 @@ void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) { } +void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) { + DCHECK(expr->arguments()->length() == 0); + ExternalReference debug_is_active = + ExternalReference::debug_is_active_address(isolate()); + __ li(at, Operand(debug_is_active)); + __ lb(v0, MemOperand(at)); + __ SmiTag(v0); + context()->Plug(v0); +} + + void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { if (expr->function() != NULL && expr->function()->intrinsic_type == Runtime::INLINE) { @@ -4101,12 +4101,20 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { if (expr->is_jsruntime()) { // Push the builtins object as the receiver. - __ lw(a0, GlobalObjectOperand()); - __ lw(a0, FieldMemOperand(a0, GlobalObject::kBuiltinsOffset)); - __ push(a0); + Register receiver = LoadIC::ReceiverRegister(); + __ lw(receiver, GlobalObjectOperand()); + __ lw(receiver, FieldMemOperand(receiver, GlobalObject::kBuiltinsOffset)); + __ push(receiver); + // Load the function from the receiver. - __ li(a2, Operand(expr->name())); - CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId()); + __ li(LoadIC::NameRegister(), Operand(expr->name())); + if (FLAG_vector_ics) { + __ li(LoadIC::SlotRegister(), + Operand(Smi::FromInt(expr->CallRuntimeFeedbackSlot()))); + CallLoadIC(NOT_CONTEXTUAL); + } else { + CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId()); + } // Push the target function under the receiver. __ lw(at, MemOperand(sp, 0)); @@ -4160,7 +4168,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { Variable* var = proxy->var(); // Delete of an unqualified identifier is disallowed in strict mode // but "delete this" is allowed. - ASSERT(strict_mode() == SLOPPY || var->is_this()); + DCHECK(strict_mode() == SLOPPY || var->is_this()); if (var->IsUnallocated()) { __ lw(a2, GlobalObjectOperand()); __ li(a1, Operand(var->name())); @@ -4175,10 +4183,10 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { } else { // Non-global variable. Call the runtime to try to delete from the // context where the variable was introduced. - ASSERT(!context_register().is(a2)); + DCHECK(!context_register().is(a2)); __ li(a2, Operand(var->name())); __ Push(context_register(), a2); - __ CallRuntime(Runtime::kHiddenDeleteContextSlot, 2); + __ CallRuntime(Runtime::kDeleteLookupSlot, 2); context()->Plug(v0); } } else { @@ -4216,7 +4224,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { // for control and plugging the control flow into the context, // because we need to prepare a pair of extra administrative AST ids // for the optimizing compiler. - ASSERT(context()->IsAccumulatorValue() || context()->IsStackValue()); + DCHECK(context()->IsAccumulatorValue() || context()->IsStackValue()); Label materialize_true, materialize_false, done; VisitForControl(expr->expression(), &materialize_false, @@ -4253,7 +4261,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { - ASSERT(expr->expression()->IsValidReferenceExpression()); + DCHECK(expr->expression()->IsValidReferenceExpression()); Comment cmnt(masm_, "[ CountOperation"); SetSourcePosition(expr->position()); @@ -4272,7 +4280,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { // Evaluate expression and get value. if (assign_type == VARIABLE) { - ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); + DCHECK(expr->expression()->AsVariableProxy()->var() != NULL); AccumulatorValueContext context(this); EmitVariableLoad(expr->expression()->AsVariableProxy()); } else { @@ -4282,15 +4290,15 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { __ push(at); } if (assign_type == NAMED_PROPERTY) { - // Put the object both on the stack and in the accumulator. - VisitForAccumulatorValue(prop->obj()); - __ push(v0); + // Put the object both on the stack and in the register. + VisitForStackValue(prop->obj()); + __ lw(LoadIC::ReceiverRegister(), MemOperand(sp, 0)); EmitNamedPropertyLoad(prop); } else { VisitForStackValue(prop->obj()); - VisitForAccumulatorValue(prop->key()); - __ lw(a1, MemOperand(sp, 0)); - __ push(v0); + VisitForStackValue(prop->key()); + __ lw(LoadIC::ReceiverRegister(), MemOperand(sp, 1 * kPointerSize)); + __ lw(LoadIC::NameRegister(), MemOperand(sp, 0)); EmitKeyedPropertyLoad(prop); } } @@ -4401,9 +4409,10 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { } break; case NAMED_PROPERTY: { - __ mov(a0, result_register()); // Value. - __ li(a2, Operand(prop->key()->AsLiteral()->value())); // Name. - __ pop(a1); // Receiver. + __ mov(StoreIC::ValueRegister(), result_register()); + __ li(StoreIC::NameRegister(), + Operand(prop->key()->AsLiteral()->value())); + __ pop(StoreIC::ReceiverRegister()); CallStoreIC(expr->CountStoreFeedbackId()); PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); if (expr->is_postfix()) { @@ -4416,8 +4425,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { break; } case KEYED_PROPERTY: { - __ mov(a0, result_register()); // Value. - __ Pop(a2, a1); // a1 = key, a2 = receiver. + __ mov(KeyedStoreIC::ValueRegister(), result_register()); + __ Pop(KeyedStoreIC::ReceiverRegister(), KeyedStoreIC::NameRegister()); Handle<Code> ic = strict_mode() == SLOPPY ? isolate()->builtins()->KeyedStoreIC_Initialize() : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); @@ -4437,13 +4446,17 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { - ASSERT(!context()->IsEffect()); - ASSERT(!context()->IsTest()); + DCHECK(!context()->IsEffect()); + DCHECK(!context()->IsTest()); VariableProxy* proxy = expr->AsVariableProxy(); if (proxy != NULL && proxy->var()->IsUnallocated()) { Comment cmnt(masm_, "[ Global variable"); - __ lw(a0, GlobalObjectOperand()); - __ li(a2, Operand(proxy->name())); + __ lw(LoadIC::ReceiverRegister(), GlobalObjectOperand()); + __ li(LoadIC::NameRegister(), Operand(proxy->name())); + if (FLAG_vector_ics) { + __ li(LoadIC::SlotRegister(), + Operand(Smi::FromInt(proxy->VariableFeedbackSlot()))); + } // Use a regular load, not a contextual load, to avoid a reference // error. CallLoadIC(NOT_CONTEXTUAL); @@ -4455,12 +4468,12 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { // Generate code for loading from variables potentially shadowed // by eval-introduced variables. - EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done); + EmitDynamicLookupFastCase(proxy, INSIDE_TYPEOF, &slow, &done); __ bind(&slow); __ li(a0, Operand(proxy->name())); __ Push(cp, a0); - __ CallRuntime(Runtime::kHiddenLoadContextSlotNoReferenceError, 2); + __ CallRuntime(Runtime::kLoadLookupSlotNoReferenceError, 2); PrepareForBailout(expr, TOS_REG); __ bind(&done); @@ -4510,10 +4523,6 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr, __ Branch(if_true, eq, v0, Operand(at)); __ LoadRoot(at, Heap::kFalseValueRootIndex); Split(eq, v0, Operand(at), if_true, if_false, fall_through); - } else if (FLAG_harmony_typeof && - String::Equals(check, factory->null_string())) { - __ LoadRoot(at, Heap::kNullValueRootIndex); - Split(eq, v0, Operand(at), if_true, if_false, fall_through); } else if (String::Equals(check, factory->undefined_string())) { __ LoadRoot(at, Heap::kUndefinedValueRootIndex); __ Branch(if_true, eq, v0, Operand(at)); @@ -4532,10 +4541,8 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr, if_true, if_false, fall_through); } else if (String::Equals(check, factory->object_string())) { __ JumpIfSmi(v0, if_false); - if (!FLAG_harmony_typeof) { - __ LoadRoot(at, Heap::kNullValueRootIndex); - __ Branch(if_true, eq, v0, Operand(at)); - } + __ LoadRoot(at, Heap::kNullValueRootIndex); + __ Branch(if_true, eq, v0, Operand(at)); // Check for JS objects => true. __ GetObjectType(v0, v0, a1); __ Branch(if_false, lt, a1, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); @@ -4666,7 +4673,7 @@ Register FullCodeGenerator::context_register() { void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { - ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset); + DCHECK_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset); __ sw(value, MemOperand(fp, frame_offset)); } @@ -4691,7 +4698,7 @@ void FullCodeGenerator::PushFunctionArgumentForContextAllocation() { // code. Fetch it from the context. __ lw(at, ContextOperand(cp, Context::CLOSURE_INDEX)); } else { - ASSERT(declaration_scope->is_function_scope()); + DCHECK(declaration_scope->is_function_scope()); __ lw(at, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); } __ push(at); @@ -4702,12 +4709,12 @@ void FullCodeGenerator::PushFunctionArgumentForContextAllocation() { // Non-local control flow support. void FullCodeGenerator::EnterFinallyBlock() { - ASSERT(!result_register().is(a1)); + DCHECK(!result_register().is(a1)); // Store result register while executing finally block. __ push(result_register()); // Cook return address in link register to stack (smi encoded Code* delta). __ Subu(a1, ra, Operand(masm_->CodeObject())); - ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); + DCHECK_EQ(1, kSmiTagSize + kSmiShiftSize); STATIC_ASSERT(0 == kSmiTag); __ Addu(a1, a1, Operand(a1)); // Convert to smi. @@ -4737,7 +4744,7 @@ void FullCodeGenerator::EnterFinallyBlock() { void FullCodeGenerator::ExitFinallyBlock() { - ASSERT(!result_register().is(a1)); + DCHECK(!result_register().is(a1)); // Restore pending message from stack. __ pop(a1); ExternalReference pending_message_script = @@ -4763,7 +4770,7 @@ void FullCodeGenerator::ExitFinallyBlock() { // Uncook return address and return. __ pop(result_register()); - ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); + DCHECK_EQ(1, kSmiTagSize + kSmiShiftSize); __ sra(a1, a1, 1); // Un-smi-tag value. __ Addu(at, a1, Operand(masm_->CodeObject())); __ Jump(at); @@ -4851,16 +4858,16 @@ BackEdgeTable::BackEdgeState BackEdgeTable::GetBackEdgeState( Address branch_address = pc - 6 * kInstrSize; Address pc_immediate_load_address = pc - 4 * kInstrSize; - ASSERT(Assembler::IsBeq(Assembler::instr_at(pc - 5 * kInstrSize))); + DCHECK(Assembler::IsBeq(Assembler::instr_at(pc - 5 * kInstrSize))); if (!Assembler::IsAddImmediate(Assembler::instr_at(branch_address))) { - ASSERT(reinterpret_cast<uint32_t>( + DCHECK(reinterpret_cast<uint32_t>( Assembler::target_address_at(pc_immediate_load_address)) == reinterpret_cast<uint32_t>( isolate->builtins()->InterruptCheck()->entry())); return INTERRUPT; } - ASSERT(Assembler::IsAddImmediate(Assembler::instr_at(branch_address))); + DCHECK(Assembler::IsAddImmediate(Assembler::instr_at(branch_address))); if (reinterpret_cast<uint32_t>( Assembler::target_address_at(pc_immediate_load_address)) == @@ -4869,7 +4876,7 @@ BackEdgeTable::BackEdgeState BackEdgeTable::GetBackEdgeState( return ON_STACK_REPLACEMENT; } - ASSERT(reinterpret_cast<uint32_t>( + DCHECK(reinterpret_cast<uint32_t>( Assembler::target_address_at(pc_immediate_load_address)) == reinterpret_cast<uint32_t>( isolate->builtins()->OsrAfterStackCheck()->entry())); |