diff options
Diffstat (limited to 'deps/v8/src/mips/full-codegen-mips.cc')
-rw-r--r-- | deps/v8/src/mips/full-codegen-mips.cc | 270 |
1 files changed, 98 insertions, 172 deletions
diff --git a/deps/v8/src/mips/full-codegen-mips.cc b/deps/v8/src/mips/full-codegen-mips.cc index bfa24252b9..f9f8c404c2 100644 --- a/deps/v8/src/mips/full-codegen-mips.cc +++ b/deps/v8/src/mips/full-codegen-mips.cc @@ -139,7 +139,7 @@ void FullCodeGenerator::Generate() { handler_table_ = isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED); profiling_counter_ = isolate()->factory()->NewJSGlobalPropertyCell( - Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget))); + Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate())); SetFunctionPosition(function()); Comment cmnt(masm_, "[ function compiled by full code generator"); @@ -172,12 +172,13 @@ void FullCodeGenerator::Generate() { int locals_count = info->scope()->num_stack_slots(); + info->set_prologue_offset(masm_->pc_offset()); + // The following three instructions must remain together and unmodified for + // code aging to work properly. __ Push(ra, fp, cp, a1); - if (locals_count > 0) { - // Load undefined value here, so the value is ready for the loop - // below. - __ LoadRoot(at, Heap::kUndefinedValueRootIndex); - } + // Load undefined value here, so the value is ready for the loop + // below. + __ LoadRoot(at, Heap::kUndefinedValueRootIndex); // Adjust fp to point to caller's fp. __ Addu(fp, sp, Operand(2 * kPointerSize)); @@ -345,45 +346,34 @@ void FullCodeGenerator::EmitProfilingCounterReset() { } -void FullCodeGenerator::EmitStackCheck(IterationStatement* stmt, - Label* back_edge_target) { +void FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt, + Label* back_edge_target) { // The generated code is used in Deoptimizer::PatchStackCheckCodeAt so we need // to make sure it is constant. Branch may emit a skip-or-jump sequence // instead of the normal Branch. It seems that the "skip" part of that // sequence is about as long as this Branch would be so it is safe to ignore // that. Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_); - Comment cmnt(masm_, "[ Stack check"); + Comment cmnt(masm_, "[ Back edge bookkeeping"); Label ok; - if (FLAG_count_based_interrupts) { - int weight = 1; - if (FLAG_weighted_back_edges) { - ASSERT(back_edge_target->is_bound()); - int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target); - weight = Min(kMaxBackEdgeWeight, - Max(1, distance / kBackEdgeDistanceUnit)); - } - EmitProfilingCounterDecrement(weight); - __ slt(at, a3, zero_reg); - __ beq(at, zero_reg, &ok); - // CallStub will emit a li t9 first, so it is safe to use the delay slot. - InterruptStub stub; - __ CallStub(&stub); - } else { - __ LoadRoot(t0, Heap::kStackLimitRootIndex); - __ sltu(at, sp, t0); - __ beq(at, zero_reg, &ok); - // CallStub will emit a li t9 first, so it is safe to use the delay slot. - StackCheckStub stub; - __ CallStub(&stub); + int weight = 1; + if (FLAG_weighted_back_edges) { + ASSERT(back_edge_target->is_bound()); + int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target); + weight = Min(kMaxBackEdgeWeight, + Max(1, distance / kBackEdgeDistanceUnit)); } + EmitProfilingCounterDecrement(weight); + __ slt(at, a3, zero_reg); + __ beq(at, zero_reg, &ok); + // CallStub will emit a li t9 first, so it is safe to use the delay slot. + InterruptStub stub; + __ CallStub(&stub); // Record a mapping of this PC offset to the OSR id. This is used to find // the AST id from the unoptimized code in order to use it as a key into // the deoptimization input data found in the optimized code. - RecordStackCheck(stmt->OsrEntryId()); - if (FLAG_count_based_interrupts) { - EmitProfilingCounterReset(); - } + RecordBackEdge(stmt->OsrEntryId()); + EmitProfilingCounterReset(); __ bind(&ok); PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); @@ -929,34 +919,33 @@ void FullCodeGenerator::VisitFunctionDeclaration( void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) { - VariableProxy* proxy = declaration->proxy(); - Variable* variable = proxy->var(); - Handle<JSModule> instance = declaration->module()->interface()->Instance(); - ASSERT(!instance.is_null()); + Variable* variable = declaration->proxy()->var(); + ASSERT(variable->location() == Variable::CONTEXT); + ASSERT(variable->interface()->IsFrozen()); - switch (variable->location()) { - case Variable::UNALLOCATED: { - Comment cmnt(masm_, "[ ModuleDeclaration"); - globals_->Add(variable->name(), zone()); - globals_->Add(instance, zone()); - Visit(declaration->module()); - break; - } + Comment cmnt(masm_, "[ ModuleDeclaration"); + EmitDebugCheckDeclarationContext(variable); - case Variable::CONTEXT: { - Comment cmnt(masm_, "[ ModuleDeclaration"); - EmitDebugCheckDeclarationContext(variable); - __ li(a1, Operand(instance)); - __ sw(a1, ContextOperand(cp, variable->index())); - Visit(declaration->module()); - break; - } + // Load instance object. + __ LoadContext(a1, scope_->ContextChainLength(scope_->GlobalScope())); + __ lw(a1, ContextOperand(a1, variable->interface()->Index())); + __ lw(a1, ContextOperand(a1, Context::EXTENSION_INDEX)); - case Variable::PARAMETER: - case Variable::LOCAL: - case Variable::LOOKUP: - UNREACHABLE(); - } + // Assign it. + __ sw(a1, ContextOperand(cp, variable->index())); + // We know that we have written a module, which is not a smi. + __ RecordWriteContextSlot(cp, + Context::SlotOffset(variable->index()), + a1, + a3, + kRAHasBeenSaved, + kDontSaveFPRegs, + EMIT_REMEMBERED_SET, + OMIT_SMI_CHECK); + PrepareForBailoutForId(declaration->proxy()->id(), NO_REGISTERS); + + // Traverse into body. + Visit(declaration->module()); } @@ -999,6 +988,14 @@ void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { } +void FullCodeGenerator::DeclareModules(Handle<FixedArray> descriptions) { + // Call the runtime to declare the modules. + __ Push(descriptions); + __ CallRuntime(Runtime::kDeclareModules, 1); + // Return value is ignored. +} + + void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { Comment cmnt(masm_, "[ SwitchStatement"); Breakable nested_statement(this, stmt); @@ -1152,7 +1149,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { __ EnumLength(a1, v0); __ Branch(&no_descriptors, eq, a1, Operand(Smi::FromInt(0))); - __ LoadInstanceDescriptors(v0, a2, t0); + __ LoadInstanceDescriptors(v0, a2); __ lw(a2, FieldMemOperand(a2, DescriptorArray::kEnumCacheOffset)); __ lw(a2, FieldMemOperand(a2, DescriptorArray::kEnumCacheBridgeCacheOffset)); @@ -1251,7 +1248,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { __ Addu(a0, a0, Operand(Smi::FromInt(1))); __ push(a0); - EmitStackCheck(stmt, &loop); + EmitBackEdgeBookkeeping(stmt, &loop); __ Branch(&loop); // Remove the pointers stored on the stack. @@ -1399,9 +1396,9 @@ void FullCodeGenerator::EmitDynamicLookupFastCase(Variable* var, } else if (var->mode() == DYNAMIC_LOCAL) { Variable* local = var->local_if_not_shadowed(); __ lw(v0, ContextSlotOperandCheckExtensions(local, slow)); - if (local->mode() == CONST || - local->mode() == CONST_HARMONY || - local->mode() == LET) { + if (local->mode() == LET || + local->mode() == CONST || + local->mode() == CONST_HARMONY) { __ LoadRoot(at, Heap::kTheHoleValueRootIndex); __ subu(at, v0, at); // Sub as compare: at == 0 on eq. if (local->mode() == CONST) { @@ -2208,44 +2205,17 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { ASSERT(prop != NULL); ASSERT(prop->key()->AsLiteral() != NULL); - // If the assignment starts a block of assignments to the same object, - // change to slow case to avoid the quadratic behavior of repeatedly - // adding fast properties. - if (expr->starts_initialization_block()) { - __ push(result_register()); - __ lw(t0, MemOperand(sp, kPointerSize)); // Receiver is now under value. - __ push(t0); - __ CallRuntime(Runtime::kToSlowProperties, 1); - __ pop(result_register()); - } - // Record source code position before IC call. SetSourcePosition(expr->position()); __ mov(a0, result_register()); // Load the value. __ li(a2, Operand(prop->key()->AsLiteral()->handle())); - // Load receiver to a1. Leave a copy in the stack if needed for turning the - // receiver into fast case. - if (expr->ends_initialization_block()) { - __ lw(a1, MemOperand(sp)); - } else { - __ pop(a1); - } + __ pop(a1); Handle<Code> ic = is_classic_mode() ? isolate()->builtins()->StoreIC_Initialize() : isolate()->builtins()->StoreIC_Initialize_Strict(); CallIC(ic, RelocInfo::CODE_TARGET, expr->AssignmentFeedbackId()); - // If the assignment ends an initialization block, revert to fast case. - if (expr->ends_initialization_block()) { - __ push(v0); // Result of assignment, saved even if not needed. - // Receiver is under the result value. - __ lw(t0, MemOperand(sp, kPointerSize)); - __ push(t0); - __ CallRuntime(Runtime::kToFastProperties, 1); - __ pop(v0); - __ Drop(1); - } PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); context()->Plug(v0); } @@ -2254,18 +2224,6 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { // Assignment to a property, using a keyed store IC. - // If the assignment starts a block of assignments to the same object, - // change to slow case to avoid the quadratic behavior of repeatedly - // adding fast properties. - if (expr->starts_initialization_block()) { - __ push(result_register()); - // Receiver is now under the key and value. - __ lw(t0, MemOperand(sp, 2 * kPointerSize)); - __ push(t0); - __ CallRuntime(Runtime::kToSlowProperties, 1); - __ pop(result_register()); - } - // Record source code position before IC call. SetSourcePosition(expr->position()); // Call keyed store IC. @@ -2275,29 +2233,13 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { // - a2 is the receiver. __ mov(a0, result_register()); __ pop(a1); // Key. - // Load receiver to a2. Leave a copy in the stack if needed for turning the - // receiver into fast case. - if (expr->ends_initialization_block()) { - __ lw(a2, MemOperand(sp)); - } else { - __ pop(a2); - } + __ pop(a2); Handle<Code> ic = is_classic_mode() ? isolate()->builtins()->KeyedStoreIC_Initialize() : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); CallIC(ic, RelocInfo::CODE_TARGET, expr->AssignmentFeedbackId()); - // If the assignment ends an initialization block, revert to fast case. - if (expr->ends_initialization_block()) { - __ push(v0); // Result of assignment, saved even if not needed. - // Receiver is under the result value. - __ lw(t0, MemOperand(sp, kPointerSize)); - __ push(t0); - __ CallRuntime(Runtime::kToFastProperties, 1); - __ pop(v0); - __ Drop(1); - } PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); context()->Plug(v0); } @@ -2457,7 +2399,7 @@ void FullCodeGenerator::VisitCall(Call* expr) { VariableProxy* proxy = callee->AsVariableProxy(); Property* property = callee->AsProperty(); - if (proxy != NULL && proxy->var()->is_possibly_eval()) { + if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) { // In a call to eval, we first call %ResolvePossiblyDirectEval to // resolve the function we need to call and the receiver of the // call. Then we call the resolved function using the given @@ -2745,7 +2687,7 @@ void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( context()->PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false, &fall_through); - if (generate_debug_code_) __ AbortIfSmi(v0); + __ AssertNotSmi(v0); __ lw(a1, FieldMemOperand(v0, HeapObject::kMapOffset)); __ lbu(t0, FieldMemOperand(a1, Map::kBitField2Offset)); @@ -2759,27 +2701,31 @@ void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( __ Branch(if_false, eq, a2, Operand(t0)); // Look for valueOf symbol in the descriptor array, and indicate false if - // found. The type is not checked, so if it is a transition it is a false - // negative. - __ LoadInstanceDescriptors(a1, t0, a3); - __ lw(a3, FieldMemOperand(t0, FixedArray::kLengthOffset)); - // t0: descriptor array - // a3: length of descriptor array - // Calculate the end of the descriptor array. + // found. Since we omit an enumeration index check, if it is added via a + // transition that shares its descriptor array, this is a false positive. + Label entry, loop, done; + + // Skip loop if no descriptors are valid. + __ NumberOfOwnDescriptors(a3, a1); + __ Branch(&done, eq, a3, Operand(zero_reg)); + + __ LoadInstanceDescriptors(a1, t0); + // t0: descriptor array. + // a3: valid entries in the descriptor array. STATIC_ASSERT(kSmiTag == 0); STATIC_ASSERT(kSmiTagSize == 1); STATIC_ASSERT(kPointerSize == 4); - __ Addu(a2, t0, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); + __ li(at, Operand(DescriptorArray::kDescriptorSize)); + __ Mul(a3, a3, at); + // Calculate location of the first key name. + __ Addu(t0, t0, Operand(DescriptorArray::kFirstOffset - kHeapObjectTag)); + // Calculate the end of the descriptor array. + __ mov(a2, t0); __ sll(t1, a3, kPointerSizeLog2 - kSmiTagSize); __ Addu(a2, a2, t1); - // Calculate location of the first key name. - __ Addu(t0, - t0, - Operand(DescriptorArray::kFirstOffset - kHeapObjectTag)); // Loop through all the keys in the descriptor array. If one of these is the // symbol valueOf the result is false. - Label entry, loop; // The use of t2 to store the valueOf symbol asumes that it is not otherwise // used in the loop below. __ LoadRoot(t2, Heap::kvalue_of_symbolRootIndex); @@ -2791,7 +2737,8 @@ void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( __ bind(&entry); __ Branch(&loop, ne, t0, Operand(a2)); - // If a valueOf property is not found on the object check that it's + __ bind(&done); + // If a valueOf property is not found on the object check that its // prototype is the un-modified String prototype. If not result is false. __ lw(a2, FieldMemOperand(a1, Map::kPrototypeOffset)); __ JumpIfSmi(a2, if_false); @@ -3621,7 +3568,7 @@ void FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) { ASSERT(args->length() == 1); VisitForAccumulatorValue(args->at(0)); - __ AbortIfNotString(v0); + __ AssertString(v0); __ lw(v0, FieldMemOperand(v0, String::kHashFieldOffset)); __ IndexFromHash(v0, v0); @@ -3706,7 +3653,7 @@ void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) { __ lw(scratch1, FieldMemOperand(string, HeapObject::kMapOffset)); __ lbu(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset)); __ JumpIfInstanceTypeIsNotSequentialAscii(scratch1, scratch2, &bailout); - __ lw(scratch1, FieldMemOperand(string, SeqAsciiString::kLengthOffset)); + __ lw(scratch1, FieldMemOperand(string, SeqOneByteString::kLengthOffset)); __ AdduAndCheckForOverflow(string_length, string_length, scratch1, scratch3); __ BranchOnOverflow(&bailout, scratch3); __ Branch(&loop, lt, element, Operand(elements_end)); @@ -3733,7 +3680,7 @@ void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) { // Add (separator length times array_length) - separator length to the // string_length to get the length of the result string. array_length is not // smi but the other values are, so the result is a smi. - __ lw(scratch1, FieldMemOperand(separator, SeqAsciiString::kLengthOffset)); + __ lw(scratch1, FieldMemOperand(separator, SeqOneByteString::kLengthOffset)); __ Subu(string_length, string_length, Operand(scratch1)); __ Mult(array_length, scratch1); // Check for smi overflow. No overflow if higher 33 bits of 64-bit result are @@ -3773,10 +3720,10 @@ void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) { array_length = no_reg; __ Addu(result_pos, result, - Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); + Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); // Check the length of the separator. - __ lw(scratch1, FieldMemOperand(separator, SeqAsciiString::kLengthOffset)); + __ lw(scratch1, FieldMemOperand(separator, SeqOneByteString::kLengthOffset)); __ li(at, Operand(Smi::FromInt(1))); __ Branch(&one_char_separator, eq, scratch1, Operand(at)); __ Branch(&long_separator, gt, scratch1, Operand(at)); @@ -3793,7 +3740,7 @@ void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) { __ Addu(element, element, kPointerSize); __ lw(string_length, FieldMemOperand(string, String::kLengthOffset)); __ SmiUntag(string_length); - __ Addu(string, string, SeqAsciiString::kHeaderSize - kHeapObjectTag); + __ Addu(string, string, SeqOneByteString::kHeaderSize - kHeapObjectTag); __ CopyBytes(string, result_pos, string_length, scratch1); // End while (element < elements_end). __ Branch(&empty_separator_loop, lt, element, Operand(elements_end)); @@ -3803,7 +3750,7 @@ void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) { // One-character separator case. __ bind(&one_char_separator); // Replace separator with its ASCII character value. - __ lbu(separator, FieldMemOperand(separator, SeqAsciiString::kHeaderSize)); + __ lbu(separator, FieldMemOperand(separator, SeqOneByteString::kHeaderSize)); // Jump into the loop after the code that copies the separator, so the first // element is not preceded by a separator. __ jmp(&one_char_separator_loop_entry); @@ -3825,7 +3772,7 @@ void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) { __ Addu(element, element, kPointerSize); __ lw(string_length, FieldMemOperand(string, String::kLengthOffset)); __ SmiUntag(string_length); - __ Addu(string, string, SeqAsciiString::kHeaderSize - kHeapObjectTag); + __ Addu(string, string, SeqOneByteString::kHeaderSize - kHeapObjectTag); __ CopyBytes(string, result_pos, string_length, scratch1); // End while (element < elements_end). __ Branch(&one_char_separator_loop, lt, element, Operand(elements_end)); @@ -3846,7 +3793,7 @@ void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) { __ SmiUntag(string_length); __ Addu(string, separator, - Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); + Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); __ CopyBytes(string, result_pos, string_length, scratch1); __ bind(&long_separator); @@ -3854,7 +3801,7 @@ void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) { __ Addu(element, element, kPointerSize); __ lw(string_length, FieldMemOperand(string, String::kLengthOffset)); __ SmiUntag(string_length); - __ Addu(string, string, SeqAsciiString::kHeaderSize - kHeapObjectTag); + __ Addu(string, string, SeqOneByteString::kHeaderSize - kHeapObjectTag); __ CopyBytes(string, result_pos, string_length, scratch1); // End while (element < elements_end). __ Branch(&long_separator_loop, lt, element, Operand(elements_end)); @@ -4150,9 +4097,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { JumpPatchSite patch_site(masm_); int count_value = expr->op() == Token::INC ? 1 : -1; - __ li(a1, Operand(Smi::FromInt(count_value))); - if (ShouldInlineSmiCase(expr->op())) { + __ li(a1, Operand(Smi::FromInt(count_value))); __ AdduAndCheckForOverflow(v0, a0, a1, t0); __ BranchOnOverflow(&stub_call, t0); // Do stub on overflow. @@ -4161,6 +4107,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { patch_site.EmitJumpIfSmi(v0, &done); __ bind(&stub_call); } + __ mov(a1, a0); + __ li(a0, Operand(Smi::FromInt(count_value))); // Record position before stub call. SetSourcePosition(expr->position()); @@ -4383,29 +4331,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { default: { VisitForAccumulatorValue(expr->right()); - Condition cc = eq; - switch (op) { - case Token::EQ_STRICT: - case Token::EQ: - cc = eq; - break; - case Token::LT: - cc = lt; - break; - case Token::GT: - cc = gt; - break; - case Token::LTE: - cc = le; - break; - case Token::GTE: - cc = ge; - break; - case Token::IN: - case Token::INSTANCEOF: - default: - UNREACHABLE(); - } + Condition cc = CompareIC::ComputeCondition(op); __ mov(a0, result_register()); __ pop(a1); |