Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(786)

Unified Diff: src/ppc/code-stubs-ppc.cc

Issue 901083004: Contribution of PowerPC port (continuation of 422063005) - PPC dir update (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Contribution of PowerPC port (continuation of 422063005) - PPC dir update -comments and rebase Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/ppc/code-stubs-ppc.h ('k') | src/ppc/codegen-ppc.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/ppc/code-stubs-ppc.cc
diff --git a/src/ppc/code-stubs-ppc.cc b/src/ppc/code-stubs-ppc.cc
index 2c65b44978dd7c7a8060b1164ac380392c0b6408..0226ffbf572e3710ee07e65fd40c86de0c540bc8 100644
--- a/src/ppc/code-stubs-ppc.cc
+++ b/src/ppc/code-stubs-ppc.cc
@@ -157,7 +157,7 @@ void DoubleToIStub::Generate(MacroAssembler* masm) {
// Test for overflow
#if V8_TARGET_ARCH_PPC64
- __ TestIfInt32(result_reg, scratch, r0);
+ __ TestIfInt32(result_reg, r0);
#else
__ TestIfInt32(scratch, result_reg, r0);
#endif
@@ -328,15 +328,20 @@ static void EmitIdenticalObjectComparison(MacroAssembler* masm, Label* slow,
// not (it's a NaN). For <= and >= we need to load r0 with the failing
// value if it's a NaN.
if (cond != eq) {
- Label not_equal;
- __ bne(&not_equal);
- // All-zero means Infinity means equal.
- __ Ret();
- __ bind(&not_equal);
- if (cond == le) {
- __ li(r3, Operand(GREATER)); // NaN <= NaN should fail.
+ if (CpuFeatures::IsSupported(ISELECT)) {
+ __ li(r4, Operand((cond == le) ? GREATER : LESS));
+ __ isel(eq, r3, r3, r4);
} else {
- __ li(r3, Operand(LESS)); // NaN >= NaN should fail.
+ Label not_equal;
+ __ bne(&not_equal);
+ // All-zero means Infinity means equal.
+ __ Ret();
+ __ bind(&not_equal);
+ if (cond == le) {
+ __ li(r3, Operand(GREATER)); // NaN <= NaN should fail.
+ } else {
+ __ li(r3, Operand(LESS)); // NaN >= NaN should fail.
+ }
}
}
__ Ret();
@@ -571,7 +576,7 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) {
// If either is a Smi (we know that not both are), then they can only
// be strictly equal if the other is a HeapNumber.
STATIC_ASSERT(kSmiTag == 0);
- DCHECK_EQ(0, Smi::FromInt(0));
+ DCHECK_EQ(static_cast<Smi*>(0), Smi::FromInt(0));
__ and_(r5, lhs, rhs);
__ JumpIfNotSmi(r5, &not_smis);
// One operand is a smi. EmitSmiNonsmiComparison generates code that can:
@@ -592,16 +597,25 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) {
Label nan, equal, less_than;
__ bunordered(&nan);
- __ beq(&equal);
- __ blt(&less_than);
- __ li(r3, Operand(GREATER));
- __ Ret();
- __ bind(&equal);
- __ li(r3, Operand(EQUAL));
- __ Ret();
- __ bind(&less_than);
- __ li(r3, Operand(LESS));
- __ Ret();
+ if (CpuFeatures::IsSupported(ISELECT)) {
+ DCHECK(EQUAL == 0);
+ __ li(r4, Operand(GREATER));
+ __ li(r5, Operand(LESS));
+ __ isel(eq, r3, r0, r4);
+ __ isel(lt, r3, r5, r3);
+ __ Ret();
+ } else {
+ __ beq(&equal);
+ __ blt(&less_than);
+ __ li(r3, Operand(GREATER));
+ __ Ret();
+ __ bind(&equal);
+ __ li(r3, Operand(EQUAL));
+ __ Ret();
+ __ bind(&less_than);
+ __ li(r3, Operand(LESS));
+ __ Ret();
+ }
__ bind(&nan);
// If one of the sides was a NaN then the v flag is set. Load r3 with
@@ -862,11 +876,16 @@ void MathPowStub::Generate(MacroAssembler* masm) {
__ ConvertIntToDouble(scratch2, double_result);
// Get absolute value of exponent.
- Label positive_exponent;
__ cmpi(scratch, Operand::Zero());
- __ bge(&positive_exponent);
- __ neg(scratch, scratch);
- __ bind(&positive_exponent);
+ if (CpuFeatures::IsSupported(ISELECT)) {
+ __ neg(scratch2, scratch);
+ __ isel(lt, scratch, scratch2, scratch);
+ } else {
+ Label positive_exponent;
+ __ bge(&positive_exponent);
+ __ neg(scratch, scratch);
+ __ bind(&positive_exponent);
+ }
Label while_true, no_carry, loop_end;
__ bind(&while_true);
@@ -937,11 +956,11 @@ bool CEntryStub::NeedsImmovableCode() { return true; }
void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) {
CEntryStub::GenerateAheadOfTime(isolate);
- // WriteInt32ToHeapNumberStub::GenerateFixedRegStubsAheadOfTime(isolate);
StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate);
StubFailureTrampolineStub::GenerateAheadOfTime(isolate);
ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
CreateAllocationSiteStub::GenerateAheadOfTime(isolate);
+ CreateWeakCellStub::GenerateAheadOfTime(isolate);
BinaryOpICStub::GenerateAheadOfTime(isolate);
StoreRegistersStateStub::GenerateAheadOfTime(isolate);
RestoreRegistersStateStub::GenerateAheadOfTime(isolate);
@@ -1000,7 +1019,7 @@ void CEntryStub::Generate(MacroAssembler* masm) {
int arg_stack_space = 1;
// PPC LINUX ABI:
-#if V8_TARGET_ARCH_PPC64 && !ABI_RETURNS_OBJECT_PAIRS_IN_REGS
+#if !ABI_RETURNS_OBJECT_PAIRS_IN_REGS
// Pass buffer for return value on stack if necessary
if (result_size() > 1) {
DCHECK_EQ(2, result_size());
@@ -1020,7 +1039,7 @@ void CEntryStub::Generate(MacroAssembler* masm) {
// Result returned in registers or stack, depending on result size and ABI.
Register isolate_reg = r5;
-#if V8_TARGET_ARCH_PPC64 && !ABI_RETURNS_OBJECT_PAIRS_IN_REGS
+#if !ABI_RETURNS_OBJECT_PAIRS_IN_REGS
if (result_size() > 1) {
// The return value is 16-byte non-scalar value.
// Use frame storage reserved by calling function to pass return
@@ -1068,7 +1087,7 @@ void CEntryStub::Generate(MacroAssembler* masm) {
__ Call(target);
}
-#if V8_TARGET_ARCH_PPC64 && !ABI_RETURNS_OBJECT_PAIRS_IN_REGS
+#if !ABI_RETURNS_OBJECT_PAIRS_IN_REGS
// If return value is on the stack, pop it to registers.
if (result_size() > 1) {
__ LoadP(r4, MemOperand(r3, kPointerSize));
@@ -1499,17 +1518,24 @@ void InstanceofStub::Generate(MacroAssembler* masm) {
__ Push(r3, r4);
__ InvokeBuiltin(Builtins::INSTANCE_OF, CALL_FUNCTION);
}
- Label true_value, done;
- __ cmpi(r3, Operand::Zero());
- __ beq(&true_value);
+ if (CpuFeatures::IsSupported(ISELECT)) {
+ __ cmpi(r3, Operand::Zero());
+ __ LoadRoot(r3, Heap::kTrueValueRootIndex);
+ __ LoadRoot(r4, Heap::kFalseValueRootIndex);
+ __ isel(eq, r3, r3, r4);
+ } else {
+ Label true_value, done;
+ __ cmpi(r3, Operand::Zero());
+ __ beq(&true_value);
- __ LoadRoot(r3, Heap::kFalseValueRootIndex);
- __ b(&done);
+ __ LoadRoot(r3, Heap::kFalseValueRootIndex);
+ __ b(&done);
- __ bind(&true_value);
- __ LoadRoot(r3, Heap::kTrueValueRootIndex);
+ __ bind(&true_value);
+ __ LoadRoot(r3, Heap::kTrueValueRootIndex);
- __ bind(&done);
+ __ bind(&done);
+ }
__ Ret(HasArgsInRegisters() ? 0 : 2);
}
}
@@ -1518,9 +1544,14 @@ void InstanceofStub::Generate(MacroAssembler* masm) {
void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
Label miss;
Register receiver = LoadDescriptor::ReceiverRegister();
-
- NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(masm, receiver, r6,
- r7, &miss);
+ // Ensure that the vector and slot registers won't be clobbered before
+ // calling the miss handler.
+ DCHECK(!FLAG_vector_ics ||
+ !AreAliased(r7, r8, VectorLoadICDescriptor::VectorRegister(),
+ VectorLoadICDescriptor::SlotRegister()));
+
+ NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(masm, receiver, r7,
+ r8, &miss);
__ bind(&miss);
PropertyAccessCompiler::TailCallBuiltin(
masm, PropertyAccessCompiler::MissBuiltin(Code::LOAD_IC));
@@ -1533,10 +1564,16 @@ void LoadIndexedStringStub::Generate(MacroAssembler* masm) {
Register receiver = LoadDescriptor::ReceiverRegister();
Register index = LoadDescriptor::NameRegister();
- Register scratch = r6;
+ Register scratch = r8;
Register result = r3;
DCHECK(!scratch.is(receiver) && !scratch.is(index));
+ DCHECK(!FLAG_vector_ics ||
+ (!scratch.is(VectorLoadICDescriptor::VectorRegister()) &&
+ result.is(VectorLoadICDescriptor::SlotRegister())));
+ // StringCharAtGenerator doesn't use the result register until it's passed
+ // the different miss possibilities. If it did, we would have a conflict
+ // when FLAG_vector_ics is true.
StringCharAtGenerator char_at_generator(receiver, index, scratch, result,
&miss, // When not a string.
&miss, // When not a number.
@@ -1673,11 +1710,15 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
// r4 = parameter count (tagged)
// r5 = argument count (tagged)
// Compute the mapped parameter count = min(r4, r5) in r4.
- Label skip;
__ cmp(r4, r5);
- __ blt(&skip);
- __ mr(r4, r5);
- __ bind(&skip);
+ if (CpuFeatures::IsSupported(ISELECT)) {
+ __ isel(lt, r4, r4, r5);
+ } else {
+ Label skip;
+ __ blt(&skip);
+ __ mr(r4, r5);
+ __ bind(&skip);
+ }
__ bind(&try_allocate);
@@ -1686,15 +1727,21 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
const int kParameterMapHeaderSize =
FixedArray::kHeaderSize + 2 * kPointerSize;
// If there are no mapped parameters, we do not need the parameter_map.
- Label skip2, skip3;
__ CmpSmiLiteral(r4, Smi::FromInt(0), r0);
- __ bne(&skip2);
- __ li(r11, Operand::Zero());
- __ b(&skip3);
- __ bind(&skip2);
- __ SmiToPtrArrayOffset(r11, r4);
- __ addi(r11, r11, Operand(kParameterMapHeaderSize));
- __ bind(&skip3);
+ if (CpuFeatures::IsSupported(ISELECT)) {
+ __ SmiToPtrArrayOffset(r11, r4);
+ __ addi(r11, r11, Operand(kParameterMapHeaderSize));
+ __ isel(eq, r11, r0, r11);
+ } else {
+ Label skip2, skip3;
+ __ bne(&skip2);
+ __ li(r11, Operand::Zero());
+ __ b(&skip3);
+ __ bind(&skip2);
+ __ SmiToPtrArrayOffset(r11, r4);
+ __ addi(r11, r11, Operand(kParameterMapHeaderSize));
+ __ bind(&skip3);
+ }
// 2. Backing store.
__ SmiToPtrArrayOffset(r7, r5);
@@ -1718,14 +1765,20 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
__ LoadP(r7,
MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
__ LoadP(r7, FieldMemOperand(r7, GlobalObject::kNativeContextOffset));
- Label skip4, skip5;
__ cmpi(r4, Operand::Zero());
- __ bne(&skip4);
- __ LoadP(r7, MemOperand(r7, kNormalOffset));
- __ b(&skip5);
- __ bind(&skip4);
- __ LoadP(r7, MemOperand(r7, kAliasedOffset));
- __ bind(&skip5);
+ if (CpuFeatures::IsSupported(ISELECT)) {
+ __ LoadP(r11, MemOperand(r7, kNormalOffset));
+ __ LoadP(r7, MemOperand(r7, kAliasedOffset));
+ __ isel(eq, r7, r11, r7);
+ } else {
+ Label skip4, skip5;
+ __ bne(&skip4);
+ __ LoadP(r7, MemOperand(r7, kNormalOffset));
+ __ b(&skip5);
+ __ bind(&skip4);
+ __ LoadP(r7, MemOperand(r7, kAliasedOffset));
+ __ bind(&skip5);
+ }
// r3 = address of new object (tagged)
// r4 = mapped parameter count (tagged)
@@ -1762,14 +1815,20 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
// r5 = argument count (tagged)
// r7 = address of parameter map or backing store (tagged)
// Initialize parameter map. If there are no mapped arguments, we're done.
- Label skip_parameter_map, skip6;
+ Label skip_parameter_map;
__ CmpSmiLiteral(r4, Smi::FromInt(0), r0);
- __ bne(&skip6);
- // Move backing store address to r6, because it is
- // expected there when filling in the unmapped arguments.
- __ mr(r6, r7);
- __ b(&skip_parameter_map);
- __ bind(&skip6);
+ if (CpuFeatures::IsSupported(ISELECT)) {
+ __ isel(eq, r6, r7, r6);
+ __ beq(&skip_parameter_map);
+ } else {
+ Label skip6;
+ __ bne(&skip6);
+ // Move backing store address to r6, because it is
+ // expected there when filling in the unmapped arguments.
+ __ mr(r6, r7);
+ __ b(&skip_parameter_map);
+ __ bind(&skip6);
+ }
__ LoadRoot(r9, Heap::kSloppyArgumentsElementsMapRootIndex);
__ StoreP(r9, FieldMemOperand(r7, FixedArray::kMapOffset), r0);
@@ -2682,19 +2741,27 @@ void CallConstructStub::Generate(MacroAssembler* masm) {
// entry is at the feedback vector slot given by r6 + 1.
__ LoadP(r5, FieldMemOperand(r8, FixedArray::kHeaderSize + kPointerSize));
} else {
- Label feedback_register_initialized;
// Put the AllocationSite from the feedback vector into r5, or undefined.
__ LoadP(r5, FieldMemOperand(r8, FixedArray::kHeaderSize));
__ LoadP(r8, FieldMemOperand(r5, AllocationSite::kMapOffset));
__ CompareRoot(r8, Heap::kAllocationSiteMapRootIndex);
- __ beq(&feedback_register_initialized);
- __ LoadRoot(r5, Heap::kUndefinedValueRootIndex);
- __ bind(&feedback_register_initialized);
+ if (CpuFeatures::IsSupported(ISELECT)) {
+ __ LoadRoot(r8, Heap::kUndefinedValueRootIndex);
+ __ isel(eq, r5, r5, r8);
+ } else {
+ Label feedback_register_initialized;
+ __ beq(&feedback_register_initialized);
+ __ LoadRoot(r5, Heap::kUndefinedValueRootIndex);
+ __ bind(&feedback_register_initialized);
+ }
}
__ AssertUndefinedOrAllocationSite(r5, r8);
}
+ // Pass function as original constructor.
+ __ mr(r6, r4);
+
// Jump to the function-specific construct stub.
Register jmp_reg = r7;
__ LoadP(jmp_reg, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset));
@@ -2736,12 +2803,11 @@ static void EmitLoadTypeFeedbackVector(MacroAssembler* masm, Register vector) {
void CallIC_ArrayStub::Generate(MacroAssembler* masm) {
// r4 - function
// r6 - slot id
+ // r5 - vector
Label miss;
int argc = arg_count();
ParameterCount actual(argc);
- EmitLoadTypeFeedbackVector(masm, r5);
-
__ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, r7);
__ cmp(r4, r7);
__ bne(&miss);
@@ -2774,21 +2840,44 @@ void CallIC_ArrayStub::Generate(MacroAssembler* masm) {
void CallICStub::Generate(MacroAssembler* masm) {
// r4 - function
// r6 - slot id (Smi)
+ // r5 - vector
+ const int with_types_offset =
+ FixedArray::OffsetOfElementAt(TypeFeedbackVector::kWithTypesIndex);
+ const int generic_offset =
+ FixedArray::OffsetOfElementAt(TypeFeedbackVector::kGenericCountIndex);
Label extra_checks_or_miss, slow_start;
Label slow, non_function, wrap, cont;
Label have_js_function;
int argc = arg_count();
ParameterCount actual(argc);
- EmitLoadTypeFeedbackVector(masm, r5);
-
// The checks. First, does r4 match the recorded monomorphic target?
__ SmiToPtrArrayOffset(r7, r6);
__ add(r7, r5, r7);
__ LoadP(r7, FieldMemOperand(r7, FixedArray::kHeaderSize));
- __ cmp(r4, r7);
+
+ // We don't know that we have a weak cell. We might have a private symbol
+ // or an AllocationSite, but the memory is safe to examine.
+ // AllocationSite::kTransitionInfoOffset - contains a Smi or pointer to
+ // FixedArray.
+ // WeakCell::kValueOffset - contains a JSFunction or Smi(0)
+ // Symbol::kHashFieldSlot - if the low bit is 1, then the hash is not
+ // computed, meaning that it can't appear to be a pointer. If the low bit is
+ // 0, then hash is computed, but the 0 bit prevents the field from appearing
+ // to be a pointer.
+ STATIC_ASSERT(WeakCell::kSize >= kPointerSize);
+ STATIC_ASSERT(AllocationSite::kTransitionInfoOffset ==
+ WeakCell::kValueOffset &&
+ WeakCell::kValueOffset == Symbol::kHashFieldSlot);
+
+ __ LoadP(r8, FieldMemOperand(r7, WeakCell::kValueOffset));
+ __ cmp(r4, r8);
__ bne(&extra_checks_or_miss);
+ // The compare above could have been a SMI/SMI comparison. Guard against this
+ // convincing us that we have a monomorphic JSFunction.
+ __ JumpIfSmi(r4, &extra_checks_or_miss);
+
__ bind(&have_js_function);
if (CallAsMethod()) {
EmitContinueIfStrictOrNative(masm, &cont);
@@ -2813,38 +2902,74 @@ void CallICStub::Generate(MacroAssembler* masm) {
}
__ bind(&extra_checks_or_miss);
- Label miss;
+ Label uninitialized, miss;
__ CompareRoot(r7, Heap::kmegamorphic_symbolRootIndex);
__ beq(&slow_start);
+
+ // The following cases attempt to handle MISS cases without going to the
+ // runtime.
+ if (FLAG_trace_ic) {
+ __ b(&miss);
+ }
+
__ CompareRoot(r7, Heap::kuninitialized_symbolRootIndex);
+ __ beq(&uninitialized);
+
+ // We are going megamorphic. If the feedback is a JSFunction, it is fine
+ // to handle it here. More complex cases are dealt with in the runtime.
+ __ AssertNotSmi(r7);
+ __ CompareObjectType(r7, r8, r8, JS_FUNCTION_TYPE);
+ __ bne(&miss);
+ __ SmiToPtrArrayOffset(r7, r6);
+ __ add(r7, r5, r7);
+ __ LoadRoot(ip, Heap::kmegamorphic_symbolRootIndex);
+ __ StoreP(ip, FieldMemOperand(r7, FixedArray::kHeaderSize), r0);
+ // We have to update statistics for runtime profiling.
+ __ LoadP(r7, FieldMemOperand(r5, with_types_offset));
+ __ SubSmiLiteral(r7, r7, Smi::FromInt(1), r0);
+ __ StoreP(r7, FieldMemOperand(r5, with_types_offset), r0);
+ __ LoadP(r7, FieldMemOperand(r5, generic_offset));
+ __ AddSmiLiteral(r7, r7, Smi::FromInt(1), r0);
+ __ StoreP(r7, FieldMemOperand(r5, generic_offset), r0);
+ __ b(&slow_start);
+
+ __ bind(&uninitialized);
+
+ // We are going monomorphic, provided we actually have a JSFunction.
+ __ JumpIfSmi(r4, &miss);
+
+ // Goto miss case if we do not have a function.
+ __ CompareObjectType(r4, r7, r7, JS_FUNCTION_TYPE);
+ __ bne(&miss);
+
+ // Make sure the function is not the Array() function, which requires special
+ // behavior on MISS.
+ __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, r7);
+ __ cmp(r4, r7);
__ beq(&miss);
- if (!FLAG_trace_ic) {
- // We are going megamorphic. If the feedback is a JSFunction, it is fine
- // to handle it here. More complex cases are dealt with in the runtime.
- __ AssertNotSmi(r7);
- __ CompareObjectType(r7, r8, r8, JS_FUNCTION_TYPE);
- __ bne(&miss);
- __ SmiToPtrArrayOffset(r7, r6);
- __ add(r7, r5, r7);
- __ LoadRoot(ip, Heap::kmegamorphic_symbolRootIndex);
- __ StoreP(ip, FieldMemOperand(r7, FixedArray::kHeaderSize), r0);
- // We have to update statistics for runtime profiling.
- const int with_types_offset =
- FixedArray::OffsetOfElementAt(TypeFeedbackVector::kWithTypesIndex);
- __ LoadP(r7, FieldMemOperand(r5, with_types_offset));
- __ SubSmiLiteral(r7, r7, Smi::FromInt(1), r0);
- __ StoreP(r7, FieldMemOperand(r5, with_types_offset), r0);
- const int generic_offset =
- FixedArray::OffsetOfElementAt(TypeFeedbackVector::kGenericCountIndex);
- __ LoadP(r7, FieldMemOperand(r5, generic_offset));
- __ AddSmiLiteral(r7, r7, Smi::FromInt(1), r0);
- __ StoreP(r7, FieldMemOperand(r5, generic_offset), r0);
- __ jmp(&slow_start);
+ // Update stats.
+ __ LoadP(r7, FieldMemOperand(r5, with_types_offset));
+ __ AddSmiLiteral(r7, r7, Smi::FromInt(1), r0);
+ __ StoreP(r7, FieldMemOperand(r5, with_types_offset), r0);
+
+ // Store the function. Use a stub since we need a frame for allocation.
+ // r5 - vector
+ // r6 - slot
+ // r4 - function
+ {
+ FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
+ CreateWeakCellStub create_stub(masm->isolate());
+ __ Push(r4);
+ __ CallStub(&create_stub);
+ __ Pop(r4);
}
- // We are here because tracing is on or we are going monomorphic.
+ __ b(&have_js_function);
+
+ // We are here because tracing is on or we encountered a MISS case we can't
+ // handle here.
__ bind(&miss);
GenerateMiss(masm);
@@ -2862,25 +2987,20 @@ void CallICStub::Generate(MacroAssembler* masm) {
void CallICStub::GenerateMiss(MacroAssembler* masm) {
- // Get the receiver of the function from the stack; 1 ~ return address.
- __ LoadP(r7, MemOperand(sp, (arg_count() + 1) * kPointerSize), r0);
+ FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
- {
- FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
-
- // Push the receiver and the function and feedback info.
- __ Push(r7, r4, r5, r6);
+ // Push the function and feedback info.
+ __ Push(r4, r5, r6);
- // Call the entry.
- IC::UtilityId id = GetICState() == DEFAULT ? IC::kCallIC_Miss
- : IC::kCallIC_Customization_Miss;
+ // Call the entry.
+ IC::UtilityId id = GetICState() == DEFAULT ? IC::kCallIC_Miss
+ : IC::kCallIC_Customization_Miss;
- ExternalReference miss = ExternalReference(IC_Utility(id), masm->isolate());
- __ CallExternalReference(miss, 4);
+ ExternalReference miss = ExternalReference(IC_Utility(id), masm->isolate());
+ __ CallExternalReference(miss, 3);
- // Move result to r4 and exit the internal frame.
- __ mr(r4, r3);
- }
+ // Move result to r4 and exit the internal frame.
+ __ mr(r4, r3);
}
@@ -3268,6 +3388,49 @@ void SubStringStub::Generate(MacroAssembler* masm) {
}
+void ToNumberStub::Generate(MacroAssembler* masm) {
+ // The ToNumber stub takes one argument in r3.
+ Label not_smi;
+ __ JumpIfNotSmi(r3, &not_smi);
+ __ blr();
+ __ bind(&not_smi);
+
+ Label not_heap_number;
+ __ LoadP(r4, FieldMemOperand(r3, HeapObject::kMapOffset));
+ __ lbz(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset));
+ // r3: object
+ // r4: instance type.
+ __ cmpi(r4, Operand(HEAP_NUMBER_TYPE));
+ __ bne(&not_heap_number);
+ __ blr();
+ __ bind(&not_heap_number);
+
+ Label not_string, slow_string;
+ __ cmpli(r4, Operand(FIRST_NONSTRING_TYPE));
+ __ bge(&not_string);
+ // Check if string has a cached array index.
+ __ lwz(r5, FieldMemOperand(r3, String::kHashFieldOffset));
+ __ And(r0, r5, Operand(String::kContainsCachedArrayIndexMask), SetRC);
+ __ bne(&slow_string, cr0);
+ __ IndexFromHash(r5, r3);
+ __ blr();
+ __ bind(&slow_string);
+ __ push(r3); // Push argument.
+ __ TailCallRuntime(Runtime::kStringToNumber, 1, 1);
+ __ bind(&not_string);
+
+ Label not_oddball;
+ __ cmpi(r4, Operand(ODDBALL_TYPE));
+ __ bne(&not_oddball);
+ __ LoadP(r3, FieldMemOperand(r3, Oddball::kToNumberOffset));
+ __ blr();
+ __ bind(&not_oddball);
+
+ __ push(r3); // Push argument.
+ __ InvokeBuiltin(Builtins::TO_NUMBER, JUMP_FUNCTION);
+}
+
+
void StringHelper::GenerateFlatOneByteStringEquals(MacroAssembler* masm,
Register left,
Register right,
@@ -3308,15 +3471,20 @@ void StringHelper::GenerateFlatOneByteStringEquals(MacroAssembler* masm,
void StringHelper::GenerateCompareFlatOneByteStrings(
MacroAssembler* masm, Register left, Register right, Register scratch1,
Register scratch2, Register scratch3) {
- Label skip, result_not_equal, compare_lengths;
+ Label result_not_equal, compare_lengths;
// Find minimum length and length difference.
__ LoadP(scratch1, FieldMemOperand(left, String::kLengthOffset));
__ LoadP(scratch2, FieldMemOperand(right, String::kLengthOffset));
__ sub(scratch3, scratch1, scratch2, LeaveOE, SetRC);
Register length_delta = scratch3;
- __ ble(&skip, cr0);
- __ mr(scratch1, scratch2);
- __ bind(&skip);
+ if (CpuFeatures::IsSupported(ISELECT)) {
+ __ isel(gt, scratch1, scratch2, scratch1, cr0);
+ } else {
+ Label skip;
+ __ ble(&skip, cr0);
+ __ mr(scratch1, scratch2);
+ __ bind(&skip);
+ }
Register min_length = scratch1;
STATIC_ASSERT(kSmiTag == 0);
__ cmpi(min_length, Operand::Zero());
@@ -3335,15 +3503,23 @@ void StringHelper::GenerateCompareFlatOneByteStrings(
__ bind(&result_not_equal);
// Conditionally update the result based either on length_delta or
// the last comparion performed in the loop above.
- Label less_equal, equal;
- __ ble(&less_equal);
- __ LoadSmiLiteral(r3, Smi::FromInt(GREATER));
- __ Ret();
- __ bind(&less_equal);
- __ beq(&equal);
- __ LoadSmiLiteral(r3, Smi::FromInt(LESS));
- __ bind(&equal);
- __ Ret();
+ if (CpuFeatures::IsSupported(ISELECT)) {
+ __ li(r4, Operand(GREATER));
+ __ li(r5, Operand(LESS));
+ __ isel(eq, r3, r0, r4);
+ __ isel(lt, r3, r5, r3);
+ __ Ret();
+ } else {
+ Label less_equal, equal;
+ __ ble(&less_equal);
+ __ LoadSmiLiteral(r3, Smi::FromInt(GREATER));
+ __ Ret();
+ __ bind(&less_equal);
+ __ beq(&equal);
+ __ LoadSmiLiteral(r3, Smi::FromInt(LESS));
+ __ bind(&equal);
+ __ Ret();
+ }
}
@@ -3511,17 +3687,26 @@ void CompareICStub::GenerateNumbers(MacroAssembler* masm) {
__ bunordered(&unordered);
// Return a result of -1, 0, or 1, based on status bits.
- __ beq(&equal);
- __ blt(&less_than);
- // assume greater than
- __ li(r3, Operand(GREATER));
- __ Ret();
- __ bind(&equal);
- __ li(r3, Operand(EQUAL));
- __ Ret();
- __ bind(&less_than);
- __ li(r3, Operand(LESS));
- __ Ret();
+ if (CpuFeatures::IsSupported(ISELECT)) {
+ DCHECK(EQUAL == 0);
+ __ li(r4, Operand(GREATER));
+ __ li(r5, Operand(LESS));
+ __ isel(eq, r3, r0, r4);
+ __ isel(lt, r3, r5, r3);
+ __ Ret();
+ } else {
+ __ beq(&equal);
+ __ blt(&less_than);
+ // assume greater than
+ __ li(r3, Operand(GREATER));
+ __ Ret();
+ __ bind(&equal);
+ __ li(r3, Operand(EQUAL));
+ __ Ret();
+ __ bind(&less_than);
+ __ li(r3, Operand(LESS));
+ __ Ret();
+ }
__ bind(&unordered);
__ bind(&generic_stub);
@@ -3735,13 +3920,15 @@ void CompareICStub::GenerateObjects(MacroAssembler* masm) {
void CompareICStub::GenerateKnownObjects(MacroAssembler* masm) {
Label miss;
+ Handle<WeakCell> cell = Map::WeakCellForMap(known_map_);
__ and_(r5, r4, r3);
__ JumpIfSmi(r5, &miss);
+ __ GetWeakValue(r7, cell);
__ LoadP(r5, FieldMemOperand(r3, HeapObject::kMapOffset));
__ LoadP(r6, FieldMemOperand(r4, HeapObject::kMapOffset));
- __ Cmpi(r5, Operand(known_map_), r0);
+ __ cmp(r5, r7);
__ bne(&miss);
- __ Cmpi(r6, Operand(known_map_), r0);
+ __ cmp(r6, r7);
__ bne(&miss);
__ sub(r3, r3, r4);
@@ -3825,7 +4012,7 @@ void NameDictionaryLookupStub::GenerateNegativeLookup(
__ and_(index, index, ip);
// Scale the index by multiplying by the entry size.
- DCHECK(NameDictionary::kEntrySize == 3);
+ STATIC_ASSERT(NameDictionary::kEntrySize == 3);
__ ShiftLeftImm(ip, index, Operand(1));
__ add(index, index, ip); // index *= 3.
@@ -4014,7 +4201,6 @@ void NameDictionaryLookupStub::Generate(MacroAssembler* masm) {
__ ShiftLeftImm(scratch, index, Operand(1));
__ add(index, index, scratch); // index *= 3.
- DCHECK_EQ(kSmiTagSize, 1);
__ ShiftLeftImm(scratch, index, Operand(kPointerSizeLog2));
__ add(index, dictionary, scratch);
__ LoadP(entry_key, FieldMemOperand(index, kElementsStartOffset));
@@ -4335,6 +4521,20 @@ void KeyedLoadICTrampolineStub::Generate(MacroAssembler* masm) {
}
+void CallICTrampolineStub::Generate(MacroAssembler* masm) {
+ EmitLoadTypeFeedbackVector(masm, r5);
+ CallICStub stub(isolate(), state());
+ __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET);
+}
+
+
+void CallIC_ArrayTrampolineStub::Generate(MacroAssembler* masm) {
+ EmitLoadTypeFeedbackVector(masm, r5);
+ CallIC_ArrayStub stub(isolate(), state());
+ __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET);
+}
+
+
void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) {
if (masm->isolate()->function_entry_hook() != NULL) {
PredictableCodeSizeScope predictable(masm,
@@ -4711,12 +4911,167 @@ void InternalArrayConstructorStub::Generate(MacroAssembler* masm) {
}
-void CallApiFunctionStub::Generate(MacroAssembler* masm) {
+static int AddressOffset(ExternalReference ref0, ExternalReference ref1) {
+ return ref0.address() - ref1.address();
+}
+
+
+// Calls an API function. Allocates HandleScope, extracts returned value
+// from handle and propagates exceptions. Restores context. stack_space
+// - space to be unwound on exit (includes the call JS arguments space and
+// the additional space allocated for the fast call).
+static void CallApiFunctionAndReturn(MacroAssembler* masm,
+ Register function_address,
+ ExternalReference thunk_ref,
+ int stack_space,
+ MemOperand* stack_space_operand,
+ MemOperand return_value_operand,
+ MemOperand* context_restore_operand) {
+ Isolate* isolate = masm->isolate();
+ ExternalReference next_address =
+ ExternalReference::handle_scope_next_address(isolate);
+ const int kNextOffset = 0;
+ const int kLimitOffset = AddressOffset(
+ ExternalReference::handle_scope_limit_address(isolate), next_address);
+ const int kLevelOffset = AddressOffset(
+ ExternalReference::handle_scope_level_address(isolate), next_address);
+
+ // Additional parameter is the address of the actual callback.
+ DCHECK(function_address.is(r4) || function_address.is(r5));
+ Register scratch = r6;
+
+ __ mov(scratch, Operand(ExternalReference::is_profiling_address(isolate)));
+ __ lbz(scratch, MemOperand(scratch, 0));
+ __ cmpi(scratch, Operand::Zero());
+
+ if (CpuFeatures::IsSupported(ISELECT)) {
+ __ mov(scratch, Operand(thunk_ref));
+ __ isel(eq, scratch, function_address, scratch);
+ } else {
+ Label profiler_disabled;
+ Label end_profiler_check;
+ __ beq(&profiler_disabled);
+ __ mov(scratch, Operand(thunk_ref));
+ __ b(&end_profiler_check);
+ __ bind(&profiler_disabled);
+ __ mr(scratch, function_address);
+ __ bind(&end_profiler_check);
+ }
+
+ // Allocate HandleScope in callee-save registers.
+ // r17 - next_address
+ // r14 - next_address->kNextOffset
+ // r15 - next_address->kLimitOffset
+ // r16 - next_address->kLevelOffset
+ __ mov(r17, Operand(next_address));
+ __ LoadP(r14, MemOperand(r17, kNextOffset));
+ __ LoadP(r15, MemOperand(r17, kLimitOffset));
+ __ lwz(r16, MemOperand(r17, kLevelOffset));
+ __ addi(r16, r16, Operand(1));
+ __ stw(r16, MemOperand(r17, kLevelOffset));
+
+ if (FLAG_log_timer_events) {
+ FrameScope frame(masm, StackFrame::MANUAL);
+ __ PushSafepointRegisters();
+ __ PrepareCallCFunction(1, r3);
+ __ mov(r3, Operand(ExternalReference::isolate_address(isolate)));
+ __ CallCFunction(ExternalReference::log_enter_external_function(isolate),
+ 1);
+ __ PopSafepointRegisters();
+ }
+
+ // Native call returns to the DirectCEntry stub which redirects to the
+ // return address pushed on stack (could have moved after GC).
+ // DirectCEntry stub itself is generated early and never moves.
+ DirectCEntryStub stub(isolate);
+ stub.GenerateCall(masm, scratch);
+
+ if (FLAG_log_timer_events) {
+ FrameScope frame(masm, StackFrame::MANUAL);
+ __ PushSafepointRegisters();
+ __ PrepareCallCFunction(1, r3);
+ __ mov(r3, Operand(ExternalReference::isolate_address(isolate)));
+ __ CallCFunction(ExternalReference::log_leave_external_function(isolate),
+ 1);
+ __ PopSafepointRegisters();
+ }
+
+ Label promote_scheduled_exception;
+ Label exception_handled;
+ Label delete_allocated_handles;
+ Label leave_exit_frame;
+ Label return_value_loaded;
+
+ // load value from ReturnValue
+ __ LoadP(r3, return_value_operand);
+ __ bind(&return_value_loaded);
+ // No more valid handles (the result handle was the last one). Restore
+ // previous handle scope.
+ __ StoreP(r14, MemOperand(r17, kNextOffset));
+ if (__ emit_debug_code()) {
+ __ lwz(r4, MemOperand(r17, kLevelOffset));
+ __ cmp(r4, r16);
+ __ Check(eq, kUnexpectedLevelAfterReturnFromApiCall);
+ }
+ __ subi(r16, r16, Operand(1));
+ __ stw(r16, MemOperand(r17, kLevelOffset));
+ __ LoadP(r0, MemOperand(r17, kLimitOffset));
+ __ cmp(r15, r0);
+ __ bne(&delete_allocated_handles);
+
+ // Check if the function scheduled an exception.
+ __ bind(&leave_exit_frame);
+ __ LoadRoot(r14, Heap::kTheHoleValueRootIndex);
+ __ mov(r15, Operand(ExternalReference::scheduled_exception_address(isolate)));
+ __ LoadP(r15, MemOperand(r15));
+ __ cmp(r14, r15);
+ __ bne(&promote_scheduled_exception);
+ __ bind(&exception_handled);
+
+ bool restore_context = context_restore_operand != NULL;
+ if (restore_context) {
+ __ LoadP(cp, *context_restore_operand);
+ }
+ // LeaveExitFrame expects unwind space to be in a register.
+ if (stack_space_operand != NULL) {
+ __ lwz(r14, *stack_space_operand);
+ } else {
+ __ mov(r14, Operand(stack_space));
+ }
+ __ LeaveExitFrame(false, r14, !restore_context, stack_space_operand != NULL);
+ __ blr();
+
+ __ bind(&promote_scheduled_exception);
+ {
+ FrameScope frame(masm, StackFrame::INTERNAL);
+ __ CallExternalReference(
+ ExternalReference(Runtime::kPromoteScheduledException, isolate), 0);
+ }
+ __ jmp(&exception_handled);
+
+ // HandleScope limit has changed. Delete allocated extensions.
+ __ bind(&delete_allocated_handles);
+ __ StoreP(r15, MemOperand(r17, kLimitOffset));
+ __ mr(r14, r3);
+ __ PrepareCallCFunction(1, r15);
+ __ mov(r3, Operand(ExternalReference::isolate_address(isolate)));
+ __ CallCFunction(ExternalReference::delete_handle_scope_extensions(isolate),
+ 1);
+ __ mr(r3, r14);
+ __ b(&leave_exit_frame);
+}
+
+
+static void CallApiFunctionStubHelper(MacroAssembler* masm,
+ const ParameterCount& argc,
+ bool return_first_arg,
+ bool call_data_undefined) {
// ----------- S t a t e -------------
// -- r3 : callee
// -- r7 : call_data
// -- r5 : holder
// -- r4 : api_function_address
+ // -- r6 : number of arguments if argc is a register
// -- cp : context
// --
// -- sp[0] : last argument
@@ -4731,10 +5086,6 @@ void CallApiFunctionStub::Generate(MacroAssembler* masm) {
Register api_function_address = r4;
Register context = cp;
- int argc = this->argc();
- bool is_store = this->is_store();
- bool call_data_undefined = this->call_data_undefined();
-
typedef FunctionCallbackArguments FCA;
STATIC_ASSERT(FCA::kContextSaveIndex == 6);
@@ -4746,6 +5097,8 @@ void CallApiFunctionStub::Generate(MacroAssembler* masm) {
STATIC_ASSERT(FCA::kHolderIndex == 0);
STATIC_ASSERT(FCA::kArgsLength == 7);
+ DCHECK(argc.is_immediate() || r3.is(argc.reg()));
+
// context save
__ push(context);
// load context from callee
@@ -4766,7 +5119,7 @@ void CallApiFunctionStub::Generate(MacroAssembler* masm) {
// return value default
__ push(scratch);
// isolate
- __ mov(scratch, Operand(ExternalReference::isolate_address(isolate())));
+ __ mov(scratch, Operand(ExternalReference::isolate_address(masm->isolate())));
__ push(scratch);
// holder
__ push(holder);
@@ -4782,6 +5135,8 @@ void CallApiFunctionStub::Generate(MacroAssembler* masm) {
// [0] space for DirectCEntryStub's LR save
// [1-4] FunctionCallbackInfo
const int kApiStackSpace = 5;
+ const int kFunctionCallbackInfoOffset =
+ (kStackFrameExtraParamSlot + 1) * kPointerSize;
FrameScope frame_scope(masm, StackFrame::MANUAL);
__ EnterExitFrame(false, kApiStackSpace);
@@ -4789,38 +5144,73 @@ void CallApiFunctionStub::Generate(MacroAssembler* masm) {
DCHECK(!api_function_address.is(r3) && !scratch.is(r3));
// r3 = FunctionCallbackInfo&
// Arguments is after the return address.
- __ addi(r3, sp, Operand((kStackFrameExtraParamSlot + 1) * kPointerSize));
+ __ addi(r3, sp, Operand(kFunctionCallbackInfoOffset));
// FunctionCallbackInfo::implicit_args_
__ StoreP(scratch, MemOperand(r3, 0 * kPointerSize));
- // FunctionCallbackInfo::values_
- __ addi(ip, scratch, Operand((FCA::kArgsLength - 1 + argc) * kPointerSize));
- __ StoreP(ip, MemOperand(r3, 1 * kPointerSize));
- // FunctionCallbackInfo::length_ = argc
- __ li(ip, Operand(argc));
- __ stw(ip, MemOperand(r3, 2 * kPointerSize));
- // FunctionCallbackInfo::is_construct_call = 0
- __ li(ip, Operand::Zero());
- __ stw(ip, MemOperand(r3, 2 * kPointerSize + kIntSize));
-
- const int kStackUnwindSpace = argc + FCA::kArgsLength + 1;
+ if (argc.is_immediate()) {
+ // FunctionCallbackInfo::values_
+ __ addi(ip, scratch,
+ Operand((FCA::kArgsLength - 1 + argc.immediate()) * kPointerSize));
+ __ StoreP(ip, MemOperand(r3, 1 * kPointerSize));
+ // FunctionCallbackInfo::length_ = argc
+ __ li(ip, Operand(argc.immediate()));
+ __ stw(ip, MemOperand(r3, 2 * kPointerSize));
+ // FunctionCallbackInfo::is_construct_call_ = 0
+ __ li(ip, Operand::Zero());
+ __ stw(ip, MemOperand(r3, 2 * kPointerSize + kIntSize));
+ } else {
+ __ ShiftLeftImm(ip, argc.reg(), Operand(kPointerSizeLog2));
+ __ addi(ip, ip, Operand((FCA::kArgsLength - 1) * kPointerSize));
+ // FunctionCallbackInfo::values_
+ __ add(r0, scratch, ip);
+ __ StoreP(r0, MemOperand(r3, 1 * kPointerSize));
+ // FunctionCallbackInfo::length_ = argc
+ __ stw(argc.reg(), MemOperand(r3, 2 * kPointerSize));
+ // FunctionCallbackInfo::is_construct_call_
+ __ stw(ip, MemOperand(r3, 2 * kPointerSize + kIntSize));
+ }
+
ExternalReference thunk_ref =
- ExternalReference::invoke_function_callback(isolate());
+ ExternalReference::invoke_function_callback(masm->isolate());
AllowExternalCallThatCantCauseGC scope(masm);
MemOperand context_restore_operand(
fp, (2 + FCA::kContextSaveIndex) * kPointerSize);
// Stores return the first js argument
int return_value_offset = 0;
- if (is_store) {
+ if (return_first_arg) {
return_value_offset = 2 + FCA::kArgsLength;
} else {
return_value_offset = 2 + FCA::kReturnValueOffset;
}
MemOperand return_value_operand(fp, return_value_offset * kPointerSize);
+ int stack_space = 0;
+ MemOperand is_construct_call_operand =
+ MemOperand(sp, kFunctionCallbackInfoOffset + 2 * kPointerSize + kIntSize);
+ MemOperand* stack_space_operand = &is_construct_call_operand;
+ if (argc.is_immediate()) {
+ stack_space = argc.immediate() + FCA::kArgsLength + 1;
+ stack_space_operand = NULL;
+ }
+ CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, stack_space,
+ stack_space_operand, return_value_operand,
+ &context_restore_operand);
+}
+
+
+void CallApiFunctionStub::Generate(MacroAssembler* masm) {
+ bool call_data_undefined = this->call_data_undefined();
+ CallApiFunctionStubHelper(masm, ParameterCount(r6), false,
+ call_data_undefined);
+}
+
- __ CallApiFunctionAndReturn(api_function_address, thunk_ref,
- kStackUnwindSpace, return_value_operand,
- &context_restore_operand);
+void CallApiAccessorStub::Generate(MacroAssembler* masm) {
+ bool is_store = this->is_store();
+ int argc = this->argc();
+ bool call_data_undefined = this->call_data_undefined();
+ CallApiFunctionStubHelper(masm, ParameterCount(argc), is_store,
+ call_data_undefined);
}
@@ -4878,9 +5268,9 @@ void CallApiGetterStub::Generate(MacroAssembler* masm) {
ExternalReference thunk_ref =
ExternalReference::invoke_accessor_getter_callback(isolate());
- __ CallApiFunctionAndReturn(api_function_address, thunk_ref,
- kStackUnwindSpace,
- MemOperand(fp, 6 * kPointerSize), NULL);
+ CallApiFunctionAndReturn(masm, api_function_address, thunk_ref,
+ kStackUnwindSpace, NULL,
+ MemOperand(fp, 6 * kPointerSize), NULL);
}
« no previous file with comments | « src/ppc/code-stubs-ppc.h ('k') | src/ppc/codegen-ppc.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698