diff options
Diffstat (limited to 'deps/v8/src/full-codegen/ppc/full-codegen-ppc.cc')
-rw-r--r-- | deps/v8/src/full-codegen/ppc/full-codegen-ppc.cc | 362 |
1 files changed, 106 insertions, 256 deletions
diff --git a/deps/v8/src/full-codegen/ppc/full-codegen-ppc.cc b/deps/v8/src/full-codegen/ppc/full-codegen-ppc.cc index daf3dbc099..301ccf53cc 100644 --- a/deps/v8/src/full-codegen/ppc/full-codegen-ppc.cc +++ b/deps/v8/src/full-codegen/ppc/full-codegen-ppc.cc @@ -299,41 +299,34 @@ void FullCodeGenerator::Generate() { __ CallRuntime(Runtime::kTraceEnter); } - // Visit the declarations and body unless there is an illegal - // redeclaration. - if (scope()->HasIllegalRedeclaration()) { + // Visit the declarations and body. + PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS); + { Comment cmnt(masm_, "[ Declarations"); - VisitForEffect(scope()->GetIllegalRedeclaration()); - - } else { - PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS); - { - Comment cmnt(masm_, "[ Declarations"); - VisitDeclarations(scope()->declarations()); - } + VisitDeclarations(scope()->declarations()); + } - // Assert that the declarations do not use ICs. Otherwise the debugger - // won't be able to redirect a PC at an IC to the correct IC in newly - // recompiled code. - DCHECK_EQ(0, ic_total_count_); + // Assert that the declarations do not use ICs. Otherwise the debugger + // won't be able to redirect a PC at an IC to the correct IC in newly + // recompiled code. + DCHECK_EQ(0, ic_total_count_); - { - Comment cmnt(masm_, "[ Stack check"); - PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS); - Label ok; - __ LoadRoot(ip, Heap::kStackLimitRootIndex); - __ cmpl(sp, ip); - __ bc_short(ge, &ok); - __ Call(isolate()->builtins()->StackCheck(), RelocInfo::CODE_TARGET); - __ bind(&ok); - } + { + Comment cmnt(masm_, "[ Stack check"); + PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS); + Label ok; + __ LoadRoot(ip, Heap::kStackLimitRootIndex); + __ cmpl(sp, ip); + __ bc_short(ge, &ok); + __ Call(isolate()->builtins()->StackCheck(), RelocInfo::CODE_TARGET); + __ bind(&ok); + } - { - Comment cmnt(masm_, "[ Body"); - DCHECK(loop_depth() == 0); - VisitStatements(literal()->body()); - DCHECK(loop_depth() == 0); - } + { + Comment cmnt(masm_, "[ Body"); + DCHECK(loop_depth() == 0); + VisitStatements(literal()->body()); + DCHECK(loop_depth() == 0); } // Always emit a 'return undefined' in case control fell off the end of @@ -516,7 +509,7 @@ void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const { void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const { codegen()->PrepareForBailoutBeforeSplit(condition(), true, true_label_, false_label_); - DCHECK(lit->IsNull() || lit->IsUndefined() || !lit->IsUndetectableObject()); + DCHECK(lit->IsNull() || lit->IsUndefined() || !lit->IsUndetectable()); if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) { if (false_label_ != fall_through_) __ b(false_label_); } else if (lit->IsTrue() || lit->IsJSObject()) { @@ -616,7 +609,7 @@ void FullCodeGenerator::TestContext::Plug(bool flag) const { void FullCodeGenerator::DoTest(Expression* condition, Label* if_true, Label* if_false, Label* fall_through) { - Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate()); + Handle<Code> ic = ToBooleanICStub::GetUninitialized(isolate()); CallIC(ic, condition->test_id()); __ CompareRoot(result_register(), Heap::kTrueValueRootIndex); Split(eq, if_true, if_false, fall_through); @@ -955,14 +948,14 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { FeedbackVectorSlot slot = stmt->ForInFeedbackSlot(); - Label loop, exit; - ForIn loop_statement(this, stmt); - increment_loop_depth(); - // Get the object to enumerate over. SetExpressionAsStatementPosition(stmt->enumerable()); VisitForAccumulatorValue(stmt->enumerable()); - OperandStackDepthIncrement(ForIn::kElementCount); + OperandStackDepthIncrement(5); + + Label loop, exit; + Iteration loop_statement(this, stmt); + increment_loop_depth(); // If the object is null or undefined, skip over the loop, otherwise convert // it to a JS receiver. See ECMA-262 version 5, section 12.6.4. @@ -1038,11 +1031,6 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { // We got a fixed array in register r3. Iterate through that. __ bind(&fixed_array); - int const vector_index = SmiFromSlot(slot)->value(); - __ EmitLoadTypeFeedbackVector(r4); - __ mov(r5, Operand(TypeFeedbackVector::MegamorphicSentinel(isolate()))); - __ StoreP( - r5, FieldMemOperand(r4, FixedArray::OffsetOfElementAt(vector_index)), r0); __ LoadSmiLiteral(r4, Smi::FromInt(1)); // Smi(1) indicates slow check __ Push(r4, r3); // Smi and array __ LoadP(r4, FieldMemOperand(r3, FixedArray::kLengthOffset)); @@ -1079,12 +1067,8 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { __ cmp(r7, r5); __ beq(&update_each); - // We might get here from TurboFan or Crankshaft when something in the - // for-in loop body deopts and only now notice in fullcodegen, that we - // can now longer use the enum cache, i.e. left fast mode. So better record - // this information here, in case we later OSR back into this loop or - // reoptimize the whole function w/o rerunning the loop with the slow - // mode object in fullcodegen (which would result in a deopt loop). + // We need to filter the key, record slow-path here. + int const vector_index = SmiFromSlot(slot)->value(); __ EmitLoadTypeFeedbackVector(r3); __ mov(r5, Operand(TypeFeedbackVector::MegamorphicSentinel(isolate()))); __ StoreP( @@ -1138,28 +1122,6 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { } -void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info, - bool pretenure) { - // Use the fast case closure allocation code that allocates in new - // space for nested functions that don't need literals cloning. If - // we're running with the --always-opt or the --prepare-always-opt - // flag, we need to use the runtime function so that the new function - // we are creating here gets a chance to have its code optimized and - // doesn't just get a copy of the existing unoptimized code. - if (!FLAG_always_opt && !FLAG_prepare_always_opt && !pretenure && - scope()->is_function_scope() && info->num_literals() == 0) { - FastNewClosureStub stub(isolate(), info->language_mode(), info->kind()); - __ mov(r5, Operand(info)); - __ CallStub(&stub); - } else { - __ Push(info); - __ CallRuntime(pretenure ? Runtime::kNewClosure_Tenured - : Runtime::kNewClosure); - } - context()->Plug(r3); -} - - void FullCodeGenerator::EmitSetHomeObject(Expression* initializer, int offset, FeedbackVectorSlot slot) { DCHECK(NeedsHomeObject(initializer)); @@ -1592,13 +1554,6 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { } } - if (expr->has_function()) { - DCHECK(result_saved); - __ LoadP(r3, MemOperand(sp)); - __ push(r3); - __ CallRuntime(Runtime::kToFastProperties); - } - if (result_saved) { context()->PlugTOS(); } else { @@ -1843,64 +1798,44 @@ void FullCodeGenerator::VisitYield(Yield* expr) { // this. It stays on the stack while we update the iterator. VisitForStackValue(expr->expression()); - switch (expr->yield_kind()) { - case Yield::kSuspend: - // Pop value from top-of-stack slot; box result into result register. - EmitCreateIteratorResult(false); - __ push(result_register()); - // Fall through. - case Yield::kInitial: { - Label suspend, continuation, post_runtime, resume; - - __ b(&suspend); - __ bind(&continuation); - // When we arrive here, the stack top is the resume mode and - // result_register() holds the input value (the argument given to the - // respective resume operation). - __ RecordGeneratorContinuation(); - __ pop(r4); - __ CmpSmiLiteral(r4, Smi::FromInt(JSGeneratorObject::RETURN), r0); - __ bne(&resume); - __ push(result_register()); - EmitCreateIteratorResult(true); - EmitUnwindAndReturn(); - - __ bind(&suspend); - VisitForAccumulatorValue(expr->generator_object()); - DCHECK(continuation.pos() > 0 && Smi::IsValid(continuation.pos())); - __ LoadSmiLiteral(r4, Smi::FromInt(continuation.pos())); - __ StoreP(r4, FieldMemOperand(r3, JSGeneratorObject::kContinuationOffset), - r0); - __ StoreP(cp, FieldMemOperand(r3, JSGeneratorObject::kContextOffset), r0); - __ mr(r4, cp); - __ RecordWriteField(r3, JSGeneratorObject::kContextOffset, r4, r5, - kLRHasBeenSaved, kDontSaveFPRegs); - __ addi(r4, fp, Operand(StandardFrameConstants::kExpressionsOffset)); - __ cmp(sp, r4); - __ beq(&post_runtime); - __ push(r3); // generator object - __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); - __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); - __ bind(&post_runtime); - PopOperand(result_register()); - EmitReturnSequence(); - - __ bind(&resume); - context()->Plug(result_register()); - break; - } - - case Yield::kFinal: { - // Pop value from top-of-stack slot, box result into result register. - OperandStackDepthDecrement(1); - EmitCreateIteratorResult(true); - EmitUnwindAndReturn(); - break; - } + Label suspend, continuation, post_runtime, resume; + + __ b(&suspend); + __ bind(&continuation); + // When we arrive here, the stack top is the resume mode and + // result_register() holds the input value (the argument given to the + // respective resume operation). + __ RecordGeneratorContinuation(); + __ pop(r4); + __ CmpSmiLiteral(r4, Smi::FromInt(JSGeneratorObject::RETURN), r0); + __ bne(&resume); + __ push(result_register()); + EmitCreateIteratorResult(true); + EmitUnwindAndReturn(); + + __ bind(&suspend); + OperandStackDepthIncrement(1); // Not popped on this path. + VisitForAccumulatorValue(expr->generator_object()); + DCHECK(continuation.pos() > 0 && Smi::IsValid(continuation.pos())); + __ LoadSmiLiteral(r4, Smi::FromInt(continuation.pos())); + __ StoreP(r4, FieldMemOperand(r3, JSGeneratorObject::kContinuationOffset), + r0); + __ StoreP(cp, FieldMemOperand(r3, JSGeneratorObject::kContextOffset), r0); + __ mr(r4, cp); + __ RecordWriteField(r3, JSGeneratorObject::kContextOffset, r4, r5, + kLRHasBeenSaved, kDontSaveFPRegs); + __ addi(r4, fp, Operand(StandardFrameConstants::kExpressionsOffset)); + __ cmp(sp, r4); + __ beq(&post_runtime); + __ push(r3); // generator object + __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); + __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); + __ bind(&post_runtime); + PopOperand(result_register()); + EmitReturnSequence(); - case Yield::kDelegating: - UNREACHABLE(); - } + __ bind(&resume); + context()->Plug(result_register()); } @@ -1930,7 +1865,10 @@ void FullCodeGenerator::EmitGeneratorResume( __ LoadP(r5, FieldMemOperand(r4, JSGeneratorObject::kReceiverOffset)); __ push(r5); - // Push holes for the rest of the arguments to the generator function. + // Push holes for arguments to generator function. Since the parser forced + // context allocation for any variables in generators, the actual argument + // values have already been copied into the context and these dummy values + // will never be used. __ LoadP(r6, FieldMemOperand(r7, JSFunction::kSharedFunctionInfoOffset)); __ LoadWordArith( r6, FieldMemOperand(r6, SharedFunctionInfo::kFormalParameterCountOffset)); @@ -1959,9 +1897,7 @@ void FullCodeGenerator::EmitGeneratorResume( // fp = caller's frame pointer. // cp = callee's context, // r7 = callee's JS function. - __ PushFixedFrame(r7); - // Adjust FP to point to saved FP. - __ addi(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp)); + __ PushStandardFrame(r7); // Load the operand stack size. __ LoadP(r6, FieldMemOperand(r4, JSGeneratorObject::kOperandStackOffset)); @@ -2060,7 +1996,7 @@ void FullCodeGenerator::EmitCreateIteratorResult(bool done) { __ bind(&done_allocate); __ LoadNativeContextSlot(Context::ITERATOR_RESULT_MAP_INDEX, r4); - __ pop(r5); + PopOperand(r5); __ LoadRoot(r6, done ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex); __ LoadRoot(r7, Heap::kEmptyFixedArrayRootIndex); @@ -2072,18 +2008,6 @@ void FullCodeGenerator::EmitCreateIteratorResult(bool done) { } -void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { - SetExpressionPosition(prop); - Literal* key = prop->key()->AsLiteral(); - DCHECK(!prop->IsSuperAccess()); - - __ mov(LoadDescriptor::NameRegister(), Operand(key->value())); - __ mov(LoadDescriptor::SlotRegister(), - Operand(SmiFromSlot(prop->PropertyFeedbackSlot()))); - CallLoadIC(NOT_INSIDE_TYPEOF); -} - - void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, Token::Value op, Expression* left_expr, @@ -2715,7 +2639,7 @@ void FullCodeGenerator::EmitCall(Call* expr, ConvertReceiverMode mode) { } PrepareForBailoutForId(expr->CallId(), NO_REGISTERS); - SetCallPosition(expr); + SetCallPosition(expr, expr->tail_call_mode()); if (expr->tail_call_mode() == TailCallMode::kAllow) { if (FLAG_trace) { __ CallRuntime(Runtime::kTraceTailCall); @@ -3198,23 +3122,6 @@ void FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) { } -void FullCodeGenerator::EmitToInteger(CallRuntime* expr) { - ZoneList<Expression*>* args = expr->arguments(); - DCHECK_EQ(1, args->length()); - - // Load the argument into r3 and convert it. - VisitForAccumulatorValue(args->at(0)); - - // Convert the object to an integer. - Label done_convert; - __ JumpIfSmi(r3, &done_convert); - __ Push(r3); - __ CallRuntime(Runtime::kToInteger); - __ bind(&done_convert); - context()->Plug(r3); -} - - void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) { ZoneList<Expression*>* args = expr->arguments(); DCHECK(args->length() == 1); @@ -3384,6 +3291,11 @@ void FullCodeGenerator::EmitGetSuperConstructor(CallRuntime* expr) { context()->Plug(r3); } +void FullCodeGenerator::EmitGetOrdinaryHasInstance(CallRuntime* expr) { + DCHECK_EQ(0, expr->arguments()->length()); + __ LoadNativeContextSlot(Context::ORDINARY_HAS_INSTANCE_INDEX, r3); + context()->Plug(r3); +} void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) { DCHECK(expr->arguments()->length() == 0); @@ -3425,11 +3337,13 @@ void FullCodeGenerator::EmitCreateIterResultObject(CallRuntime* expr) { void FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) { + // Push function. + __ LoadNativeContextSlot(expr->context_index(), r3); + PushOperand(r3); + // Push undefined as the receiver. __ LoadRoot(r3, Heap::kUndefinedValueRootIndex); PushOperand(r3); - - __ LoadNativeContextSlot(expr->context_index(), r3); } @@ -3443,60 +3357,9 @@ void FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) { __ Call(isolate()->builtins()->Call(ConvertReceiverMode::kNullOrUndefined), RelocInfo::CODE_TARGET); OperandStackDepthDecrement(arg_count + 1); -} - - -void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { - ZoneList<Expression*>* args = expr->arguments(); - int arg_count = args->length(); - - if (expr->is_jsruntime()) { - Comment cmnt(masm_, "[ CallRuntime"); - EmitLoadJSRuntimeFunction(expr); - - // Push the target function under the receiver. - __ LoadP(ip, MemOperand(sp, 0)); - PushOperand(ip); - __ StoreP(r3, MemOperand(sp, kPointerSize)); - - // Push the arguments ("left-to-right"). - for (int i = 0; i < arg_count; i++) { - VisitForStackValue(args->at(i)); - } - - PrepareForBailoutForId(expr->CallId(), NO_REGISTERS); - EmitCallJSRuntimeFunction(expr); - - // Restore context register. - __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); - - context()->DropAndPlug(1, r3); - - } else { - const Runtime::Function* function = expr->function(); - switch (function->function_id) { -#define CALL_INTRINSIC_GENERATOR(Name) \ - case Runtime::kInline##Name: { \ - Comment cmnt(masm_, "[ Inline" #Name); \ - return Emit##Name(expr); \ - } - FOR_EACH_FULL_CODE_INTRINSIC(CALL_INTRINSIC_GENERATOR) -#undef CALL_INTRINSIC_GENERATOR - default: { - Comment cmnt(masm_, "[ CallRuntime for unhandled intrinsic"); - // Push the arguments ("left-to-right"). - for (int i = 0; i < arg_count; i++) { - VisitForStackValue(args->at(i)); - } - // Call the C runtime function. - PrepareForBailoutForId(expr->CallId(), NO_REGISTERS); - __ CallRuntime(expr->function(), arg_count); - OperandStackDepthDecrement(arg_count); - context()->Plug(r3); - } - } - } + // Restore context register. + __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); } @@ -3731,11 +3594,11 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { __ b(&stub_call); __ bind(&slow); } - if (!is_strong(language_mode())) { - ToNumberStub convert_stub(isolate()); - __ CallStub(&convert_stub); - PrepareForBailoutForId(expr->ToNumberId(), TOS_REG); - } + + // Convert old value into a number. + ToNumberStub convert_stub(isolate()); + __ CallStub(&convert_stub); + PrepareForBailoutForId(expr->ToNumberId(), TOS_REG); // Save result for postfix expressions. if (expr->is_postfix()) { @@ -3774,9 +3637,6 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { patch_site.EmitPatchInfo(); __ bind(&done); - if (is_strong(language_mode())) { - PrepareForBailoutForId(expr->ToNumberId(), TOS_REG); - } // Store the value returned in r3. switch (assign_type) { case VARIABLE: @@ -4032,26 +3892,25 @@ void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr, __ cmp(r3, r4); Split(eq, if_true, if_false, fall_through); } else { - Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil); - CallIC(ic, expr->CompareOperationFeedbackId()); - __ CompareRoot(r3, Heap::kTrueValueRootIndex); - Split(eq, if_true, if_false, fall_through); + __ JumpIfSmi(r3, if_false); + __ LoadP(r3, FieldMemOperand(r3, HeapObject::kMapOffset)); + __ lbz(r4, FieldMemOperand(r3, Map::kBitFieldOffset)); + __ andi(r0, r4, Operand(1 << Map::kIsUndetectable)); + Split(ne, if_true, if_false, fall_through, cr0); } context()->Plug(if_true, if_false); } -void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { - __ LoadP(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); - context()->Plug(r3); -} - - Register FullCodeGenerator::result_register() { return r3; } Register FullCodeGenerator::context_register() { return cp; } +void FullCodeGenerator::LoadFromFrameField(int frame_offset, Register value) { + DCHECK_EQ(static_cast<int>(POINTER_SIZE_ALIGN(frame_offset)), frame_offset); + __ LoadP(value, MemOperand(fp, frame_offset), r0); +} void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { DCHECK_EQ(static_cast<int>(POINTER_SIZE_ALIGN(frame_offset)), frame_offset); @@ -4122,12 +3981,6 @@ void FullCodeGenerator::ClearPendingMessage() { } -void FullCodeGenerator::EmitLoadStoreICSlot(FeedbackVectorSlot slot) { - DCHECK(!slot.IsInvalid()); - __ mov(VectorStoreICTrampolineDescriptor::SlotRegister(), - Operand(SmiFromSlot(slot))); -} - void FullCodeGenerator::DeferredCommands::EmitCommands() { DCHECK(!result_register().is(r4)); // Restore the accumulator (r3) and token (r4). @@ -4180,7 +4033,6 @@ void BackEdgeTable::PatchAt(Code* unoptimized_code, Address pc, break; } case ON_STACK_REPLACEMENT: - case OSR_AFTER_STACK_CHECK: // <decrement profiling counter> // crset // bge <ok> ;; not changed @@ -4209,8 +4061,10 @@ BackEdgeTable::BackEdgeState BackEdgeTable::GetBackEdgeState( Isolate* isolate, Code* unoptimized_code, Address pc) { Address mov_address = Assembler::target_address_from_return_address(pc); Address cmp_address = mov_address - 2 * Assembler::kInstrSize; +#ifdef DEBUG Address interrupt_address = Assembler::target_address_at(mov_address, unoptimized_code); +#endif if (Assembler::IsCmpImmediate(Assembler::instr_at(cmp_address))) { DCHECK(interrupt_address == isolate->builtins()->InterruptCheck()->entry()); @@ -4219,13 +4073,9 @@ BackEdgeTable::BackEdgeState BackEdgeTable::GetBackEdgeState( DCHECK(Assembler::IsCrSet(Assembler::instr_at(cmp_address))); - if (interrupt_address == isolate->builtins()->OnStackReplacement()->entry()) { - return ON_STACK_REPLACEMENT; - } - DCHECK(interrupt_address == - isolate->builtins()->OsrAfterStackCheck()->entry()); - return OSR_AFTER_STACK_CHECK; + isolate->builtins()->OnStackReplacement()->entry()); + return ON_STACK_REPLACEMENT; } } // namespace internal } // namespace v8 |