Index: src/ic/ppc/handler-compiler-ppc.cc |
diff --git a/src/ic/arm/handler-compiler-arm.cc b/src/ic/ppc/handler-compiler-ppc.cc |
similarity index 70% |
copy from src/ic/arm/handler-compiler-arm.cc |
copy to src/ic/ppc/handler-compiler-ppc.cc |
index 5314d48ff62256d042f1c7293d78fa18f66e6f06..2f29c83412c55a63e50391eca7e44b58218b7c2a 100644 |
--- a/src/ic/arm/handler-compiler-arm.cc |
+++ b/src/ic/ppc/handler-compiler-ppc.cc |
@@ -4,7 +4,7 @@ |
#include "src/v8.h" |
-#if V8_TARGET_ARCH_ARM |
+#if V8_TARGET_ARCH_PPC |
#include "src/ic/call-optimization.h" |
#include "src/ic/handler-compiler.h" |
@@ -20,8 +20,8 @@ void NamedLoadHandlerCompiler::GenerateLoadViaGetter( |
MacroAssembler* masm, Handle<HeapType> type, Register receiver, |
Handle<JSFunction> getter) { |
// ----------- S t a t e ------------- |
- // -- r0 : receiver |
- // -- r2 : name |
+ // -- r3 : receiver |
+ // -- r5 : name |
// -- lr : return address |
// ----------------------------------- |
{ |
@@ -31,8 +31,8 @@ void NamedLoadHandlerCompiler::GenerateLoadViaGetter( |
// Call the JavaScript getter with the receiver on the stack. |
if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) { |
// Swap in the global receiver. |
- __ ldr(receiver, |
- FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset)); |
+ __ LoadP(receiver, |
+ FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset)); |
} |
__ push(receiver); |
ParameterCount actual(0); |
@@ -46,7 +46,7 @@ void NamedLoadHandlerCompiler::GenerateLoadViaGetter( |
} |
// Restore context register. |
- __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
+ __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
} |
__ Ret(); |
} |
@@ -68,8 +68,8 @@ void NamedStoreHandlerCompiler::GenerateStoreViaSetter( |
// Call the JavaScript setter with receiver and value on the stack. |
if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) { |
// Swap in the global receiver. |
- __ ldr(receiver, |
- FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset)); |
+ __ LoadP(receiver, |
+ FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset)); |
} |
__ Push(receiver, value()); |
ParameterCount actual(1); |
@@ -83,10 +83,10 @@ void NamedStoreHandlerCompiler::GenerateStoreViaSetter( |
} |
// We have to return the passed value, not the return value of the setter. |
- __ pop(r0); |
+ __ pop(r3); |
// Restore context register. |
- __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
+ __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
} |
__ Ret(); |
} |
@@ -108,28 +108,28 @@ void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup( |
// Bail out if the receiver has a named interceptor or requires access checks. |
Register map = scratch1; |
- __ ldr(map, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
- __ ldrb(scratch0, FieldMemOperand(map, Map::kBitFieldOffset)); |
- __ tst(scratch0, Operand(kInterceptorOrAccessCheckNeededMask)); |
- __ b(ne, miss_label); |
+ __ LoadP(map, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
+ __ lbz(scratch0, FieldMemOperand(map, Map::kBitFieldOffset)); |
+ __ andi(r0, scratch0, Operand(kInterceptorOrAccessCheckNeededMask)); |
+ __ bne(miss_label, cr0); |
// Check that receiver is a JSObject. |
- __ ldrb(scratch0, FieldMemOperand(map, Map::kInstanceTypeOffset)); |
- __ cmp(scratch0, Operand(FIRST_SPEC_OBJECT_TYPE)); |
- __ b(lt, miss_label); |
+ __ lbz(scratch0, FieldMemOperand(map, Map::kInstanceTypeOffset)); |
+ __ cmpi(scratch0, Operand(FIRST_SPEC_OBJECT_TYPE)); |
+ __ blt(miss_label); |
// Load properties array. |
Register properties = scratch0; |
- __ ldr(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); |
+ __ LoadP(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); |
// Check that the properties array is a dictionary. |
- __ ldr(map, FieldMemOperand(properties, HeapObject::kMapOffset)); |
+ __ LoadP(map, FieldMemOperand(properties, HeapObject::kMapOffset)); |
Register tmp = properties; |
__ LoadRoot(tmp, Heap::kHashTableMapRootIndex); |
__ cmp(map, tmp); |
- __ b(ne, miss_label); |
+ __ bne(miss_label); |
// Restore the temporarily used register. |
- __ ldr(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); |
+ __ LoadP(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); |
NameDictionaryLookupStub::GenerateNegativeLookup( |
@@ -149,17 +149,18 @@ void NamedLoadHandlerCompiler::GenerateDirectLoadGlobalFunctionPrototype( |
// Check we're still in the same context. |
Register scratch = prototype; |
const int offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX); |
- __ ldr(scratch, MemOperand(cp, offset)); |
- __ ldr(scratch, FieldMemOperand(scratch, GlobalObject::kNativeContextOffset)); |
- __ ldr(scratch, MemOperand(scratch, Context::SlotOffset(index))); |
+ __ LoadP(scratch, MemOperand(cp, offset)); |
+ __ LoadP(scratch, |
+ FieldMemOperand(scratch, GlobalObject::kNativeContextOffset)); |
+ __ LoadP(scratch, MemOperand(scratch, Context::SlotOffset(index))); |
__ Move(ip, function); |
__ cmp(ip, scratch); |
- __ b(ne, miss); |
+ __ bne(miss); |
// Load its initial map. The global functions all have initial maps. |
__ Move(prototype, Handle<Map>(function->initial_map())); |
// Load the prototype from the initial map. |
- __ ldr(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset)); |
+ __ LoadP(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset)); |
} |
@@ -167,7 +168,7 @@ void NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype( |
MacroAssembler* masm, Register receiver, Register scratch1, |
Register scratch2, Label* miss_label) { |
__ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); |
- __ mov(r0, scratch1); |
+ __ mr(r3, scratch1); |
__ Ret(); |
} |
@@ -181,10 +182,10 @@ void PropertyHandlerCompiler::GenerateCheckPropertyCell( |
Handle<Cell> cell = JSGlobalObject::EnsurePropertyCell(global, name); |
DCHECK(cell->value()->IsTheHole()); |
__ mov(scratch, Operand(cell)); |
- __ ldr(scratch, FieldMemOperand(scratch, Cell::kValueOffset)); |
+ __ LoadP(scratch, FieldMemOperand(scratch, Cell::kValueOffset)); |
__ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
__ cmp(scratch, ip); |
- __ b(ne, miss); |
+ __ bne(miss); |
} |
@@ -233,10 +234,10 @@ void PropertyHandlerCompiler::GenerateFastApiCall( |
DCHECK(optimization.is_simple_api_call()); |
// Abi for CallApiFunctionStub. |
- Register callee = r0; |
- Register call_data = r4; |
- Register holder = r2; |
- Register api_function_address = r1; |
+ Register callee = r3; |
+ Register call_data = r7; |
+ Register holder = r5; |
+ Register api_function_address = r4; |
// Put holder in place. |
CallOptimization::HolderLookup holder_lookup; |
@@ -266,7 +267,8 @@ void PropertyHandlerCompiler::GenerateFastApiCall( |
// Put call_data in place. |
if (isolate->heap()->InNewSpace(*call_data_obj)) { |
__ Move(call_data, api_call_info); |
- __ ldr(call_data, FieldMemOperand(call_data, CallHandlerInfo::kDataOffset)); |
+ __ LoadP(call_data, |
+ FieldMemOperand(call_data, CallHandlerInfo::kDataOffset)); |
} else if (call_data_obj->IsUndefined()) { |
call_data_undefined = true; |
__ LoadRoot(call_data, Heap::kUndefinedValueRootIndex); |
@@ -326,183 +328,41 @@ void NamedStoreHandlerCompiler::GenerateRestoreName(Label* label, |
} |
-// Generate StoreTransition code, value is passed in r0 register. |
-// When leaving generated code after success, the receiver_reg and name_reg |
-// may be clobbered. Upon branch to miss_label, the receiver and name |
-// registers have their original values. |
-void NamedStoreHandlerCompiler::GenerateStoreTransition( |
- Handle<Map> transition, Handle<Name> name, Register receiver_reg, |
- Register storage_reg, Register value_reg, Register scratch1, |
- Register scratch2, Register scratch3, Label* miss_label, Label* slow) { |
- // r0 : value |
- Label exit; |
- |
- int descriptor = transition->LastAdded(); |
- DescriptorArray* descriptors = transition->instance_descriptors(); |
- PropertyDetails details = descriptors->GetDetails(descriptor); |
- Representation representation = details.representation(); |
- DCHECK(!representation.IsNone()); |
- |
- if (details.type() == CONSTANT) { |
- Handle<Object> constant(descriptors->GetValue(descriptor), isolate()); |
- __ Move(scratch1, constant); |
- __ cmp(value_reg, scratch1); |
- __ b(ne, miss_label); |
- } else if (representation.IsSmi()) { |
- __ JumpIfNotSmi(value_reg, miss_label); |
- } else if (representation.IsHeapObject()) { |
- __ JumpIfSmi(value_reg, miss_label); |
- HeapType* field_type = descriptors->GetFieldType(descriptor); |
- HeapType::Iterator<Map> it = field_type->Classes(); |
- if (!it.Done()) { |
- __ ldr(scratch1, FieldMemOperand(value_reg, HeapObject::kMapOffset)); |
- Label do_store; |
- while (true) { |
- __ CompareMap(scratch1, it.Current(), &do_store); |
- it.Advance(); |
- if (it.Done()) { |
- __ b(ne, miss_label); |
- break; |
- } |
- __ b(eq, &do_store); |
- } |
- __ bind(&do_store); |
- } |
- } else if (representation.IsDouble()) { |
- Label do_store, heap_number; |
- __ LoadRoot(scratch3, Heap::kMutableHeapNumberMapRootIndex); |
- __ AllocateHeapNumber(storage_reg, scratch1, scratch2, scratch3, slow, |
- TAG_RESULT, MUTABLE); |
- |
- __ JumpIfNotSmi(value_reg, &heap_number); |
- __ SmiUntag(scratch1, value_reg); |
- __ vmov(s0, scratch1); |
- __ vcvt_f64_s32(d0, s0); |
- __ jmp(&do_store); |
- |
- __ bind(&heap_number); |
- __ CheckMap(value_reg, scratch1, Heap::kHeapNumberMapRootIndex, miss_label, |
- DONT_DO_SMI_CHECK); |
- __ vldr(d0, FieldMemOperand(value_reg, HeapNumber::kValueOffset)); |
- |
- __ bind(&do_store); |
- __ vstr(d0, FieldMemOperand(storage_reg, HeapNumber::kValueOffset)); |
- } |
- |
- // Stub never generated for objects that require access checks. |
- DCHECK(!transition->is_access_check_needed()); |
- |
- // Perform map transition for the receiver if necessary. |
- if (details.type() == FIELD && |
- Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) { |
- // The properties must be extended before we can store the value. |
- // We jump to a runtime call that extends the properties array. |
- __ push(receiver_reg); |
- __ mov(r2, Operand(transition)); |
- __ Push(r2, r0); |
- __ TailCallExternalReference( |
- ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), |
- isolate()), |
- 3, 1); |
- return; |
- } |
- |
- // Update the map of the object. |
- __ mov(scratch1, Operand(transition)); |
- __ str(scratch1, FieldMemOperand(receiver_reg, HeapObject::kMapOffset)); |
- |
- // Update the write barrier for the map field. |
- __ RecordWriteField(receiver_reg, HeapObject::kMapOffset, scratch1, scratch2, |
- kLRHasNotBeenSaved, kDontSaveFPRegs, OMIT_REMEMBERED_SET, |
- OMIT_SMI_CHECK); |
- |
- if (details.type() == CONSTANT) { |
- DCHECK(value_reg.is(r0)); |
- __ Ret(); |
- return; |
- } |
- |
- int index = transition->instance_descriptors()->GetFieldIndex( |
- transition->LastAdded()); |
- |
- // Adjust for the number of properties stored in the object. Even in the |
- // face of a transition we can use the old map here because the size of the |
- // object and the number of in-object properties is not going to change. |
- index -= transition->inobject_properties(); |
- |
- // TODO(verwaest): Share this code as a code stub. |
- SmiCheck smi_check = |
- representation.IsTagged() ? INLINE_SMI_CHECK : OMIT_SMI_CHECK; |
- if (index < 0) { |
- // Set the property straight into the object. |
- int offset = transition->instance_size() + (index * kPointerSize); |
- if (representation.IsDouble()) { |
- __ str(storage_reg, FieldMemOperand(receiver_reg, offset)); |
- } else { |
- __ str(value_reg, FieldMemOperand(receiver_reg, offset)); |
- } |
+void NamedStoreHandlerCompiler::GenerateRestoreNameAndMap( |
+ Handle<Name> name, Handle<Map> transition) { |
+ __ mov(this->name(), Operand(name)); |
+ __ mov(StoreTransitionDescriptor::MapRegister(), Operand(transition)); |
+} |
- if (!representation.IsSmi()) { |
- // Update the write barrier for the array address. |
- if (!representation.IsDouble()) { |
- __ mov(storage_reg, value_reg); |
- } |
- __ RecordWriteField(receiver_reg, offset, storage_reg, scratch1, |
- kLRHasNotBeenSaved, kDontSaveFPRegs, |
- EMIT_REMEMBERED_SET, smi_check); |
- } |
- } else { |
- // Write to the properties array. |
- int offset = index * kPointerSize + FixedArray::kHeaderSize; |
- // Get the properties array |
- __ ldr(scratch1, |
- FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset)); |
- if (representation.IsDouble()) { |
- __ str(storage_reg, FieldMemOperand(scratch1, offset)); |
- } else { |
- __ str(value_reg, FieldMemOperand(scratch1, offset)); |
- } |
- if (!representation.IsSmi()) { |
- // Update the write barrier for the array address. |
- if (!representation.IsDouble()) { |
- __ mov(storage_reg, value_reg); |
- } |
- __ RecordWriteField(scratch1, offset, storage_reg, receiver_reg, |
- kLRHasNotBeenSaved, kDontSaveFPRegs, |
- EMIT_REMEMBERED_SET, smi_check); |
- } |
- } |
- |
- // Return the value (register r0). |
- DCHECK(value_reg.is(r0)); |
- __ bind(&exit); |
- __ Ret(); |
+void NamedStoreHandlerCompiler::GenerateConstantCheck(Object* constant, |
+ Register value_reg, |
+ Label* miss_label) { |
+ __ Move(scratch1(), handle(constant, isolate())); |
+ __ cmp(value_reg, scratch1()); |
+ __ bne(miss_label); |
} |
-void NamedStoreHandlerCompiler::GenerateStoreField(LookupIterator* lookup, |
- Register value_reg, |
- Label* miss_label) { |
- DCHECK(lookup->representation().IsHeapObject()); |
+void NamedStoreHandlerCompiler::GenerateFieldTypeChecks(HeapType* field_type, |
+ Register value_reg, |
+ Label* miss_label) { |
__ JumpIfSmi(value_reg, miss_label); |
- HeapType::Iterator<Map> it = lookup->GetFieldType()->Classes(); |
- __ ldr(scratch1(), FieldMemOperand(value_reg, HeapObject::kMapOffset)); |
- Label do_store; |
- while (true) { |
- __ CompareMap(scratch1(), it.Current(), &do_store); |
- it.Advance(); |
- if (it.Done()) { |
- __ b(ne, miss_label); |
- break; |
+ HeapType::Iterator<Map> it = field_type->Classes(); |
+ if (!it.Done()) { |
+ __ LoadP(scratch1(), FieldMemOperand(value_reg, HeapObject::kMapOffset)); |
+ Label do_store; |
+ while (true) { |
+ __ CompareMap(scratch1(), it.Current(), &do_store); |
+ it.Advance(); |
+ if (it.Done()) { |
+ __ bne(miss_label); |
+ break; |
+ } |
+ __ beq(&do_store); |
} |
- __ b(eq, &do_store); |
+ __ bind(&do_store); |
} |
- __ bind(&do_store); |
- |
- StoreFieldStub stub(isolate(), lookup->GetFieldIndex(), |
- lookup->representation()); |
- GenerateTailCall(masm(), stub.GetCode()); |
} |
@@ -553,16 +413,16 @@ Register PropertyHandlerCompiler::CheckPrototypes( |
GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1, |
scratch2); |
- __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); |
+ __ LoadP(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); |
reg = holder_reg; // From now on the object will be in holder_reg. |
- __ ldr(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); |
+ __ LoadP(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); |
} else { |
Register map_reg = scratch1; |
if (depth != 1 || check == CHECK_ALL_MAPS) { |
// CheckMap implicitly loads the map of |reg| into |map_reg|. |
__ CheckMap(reg, map_reg, current_map, miss, DONT_DO_SMI_CHECK); |
} else { |
- __ ldr(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset)); |
+ __ LoadP(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset)); |
} |
// Check access rights to the global object. This has to happen after |
@@ -587,7 +447,7 @@ Register PropertyHandlerCompiler::CheckPrototypes( |
bool load_prototype_from_map = |
heap()->InNewSpace(*prototype) || depth == 1; |
if (load_prototype_from_map) { |
- __ ldr(reg, FieldMemOperand(map_reg, Map::kPrototypeOffset)); |
+ __ LoadP(reg, FieldMemOperand(map_reg, Map::kPrototypeOffset)); |
} else { |
__ mov(reg, Operand(prototype)); |
} |
@@ -642,7 +502,7 @@ void NamedStoreHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { |
void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { |
// Return the constant value. |
- __ Move(r0, value); |
+ __ Move(r3, value); |
__ Ret(); |
} |
@@ -664,18 +524,17 @@ void NamedLoadHandlerCompiler::GenerateLoadCallback( |
__ push(receiver()); |
if (heap()->InNewSpace(callback->data())) { |
__ Move(scratch3(), callback); |
- __ ldr(scratch3(), |
- FieldMemOperand(scratch3(), ExecutableAccessorInfo::kDataOffset)); |
+ __ LoadP(scratch3(), |
+ FieldMemOperand(scratch3(), ExecutableAccessorInfo::kDataOffset)); |
} else { |
__ Move(scratch3(), Handle<Object>(callback->data(), isolate())); |
} |
__ push(scratch3()); |
__ LoadRoot(scratch3(), Heap::kUndefinedValueRootIndex); |
- __ mov(scratch4(), scratch3()); |
+ __ mr(scratch4(), scratch3()); |
__ Push(scratch3(), scratch4()); |
__ mov(scratch4(), Operand(ExternalReference::isolate_address(isolate()))); |
__ Push(scratch4(), reg); |
- __ mov(scratch2(), sp); // scratch2 = PropertyAccessorInfo::args_ |
__ push(name()); |
// Abi for CallApiGetter |
@@ -732,8 +591,8 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptorWithFollowup( |
// the case, return immediately. |
Label interceptor_failed; |
__ LoadRoot(scratch1(), Heap::kNoInterceptorResultSentinelRootIndex); |
- __ cmp(r0, scratch1()); |
- __ b(eq, &interceptor_failed); |
+ __ cmp(r3, scratch1()); |
+ __ beq(&interceptor_failed); |
frame_scope.GenerateLeaveFrame(); |
__ Ret(); |
@@ -769,9 +628,8 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( |
Handle<ExecutableAccessorInfo> callback) { |
Register holder_reg = Frontend(receiver(), name); |
- __ push(receiver()); // receiver |
- __ push(holder_reg); |
- __ mov(ip, Operand(callback)); // callback info |
+ __ Push(receiver(), holder_reg); // receiver |
+ __ mov(ip, Operand(callback)); // callback info |
__ push(ip); |
__ mov(ip, Operand(name)); |
__ Push(ip, value()); |
@@ -813,17 +671,17 @@ Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( |
// Get the value from the cell. |
Register result = StoreDescriptor::ValueRegister(); |
__ mov(result, Operand(cell)); |
- __ ldr(result, FieldMemOperand(result, Cell::kValueOffset)); |
+ __ LoadP(result, FieldMemOperand(result, Cell::kValueOffset)); |
// Check for deleted property if property can actually be deleted. |
if (is_configurable) { |
__ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
__ cmp(result, ip); |
- __ b(eq, &miss); |
+ __ beq(&miss); |
} |
Counters* counters = isolate()->counters(); |
- __ IncrementCounter(counters->named_load_global_stub(), 1, r1, r3); |
+ __ IncrementCounter(counters->named_load_global_stub(), 1, r4, r6); |
__ Ret(); |
FrontendFooter(name, &miss); |