Index: src/ppc/stub-cache-ppc.cc |
diff --git a/src/arm/stub-cache-arm.cc b/src/ppc/stub-cache-ppc.cc |
similarity index 84% |
copy from src/arm/stub-cache-arm.cc |
copy to src/ppc/stub-cache-ppc.cc |
index c5abfbb7239934767d732283dfc377a6cb4258f0..4cb032755ac0fc8da91f8f7ce23628ae3c0536d6 100644 |
--- a/src/arm/stub-cache-arm.cc |
+++ b/src/ppc/stub-cache-ppc.cc |
@@ -1,10 +1,13 @@ |
// Copyright 2012 the V8 project authors. All rights reserved. |
+// |
+// Copyright IBM Corp. 2012, 2013. All rights reserved. |
+// |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
#include "src/v8.h" |
-#if V8_TARGET_ARCH_ARM |
+#if V8_TARGET_ARCH_PPC |
#include "src/codegen.h" |
#include "src/ic-inl.h" |
@@ -31,9 +34,10 @@ static void ProbeTable(Isolate* isolate, |
ExternalReference value_offset(isolate->stub_cache()->value_reference(table)); |
ExternalReference map_offset(isolate->stub_cache()->map_reference(table)); |
- uint32_t key_off_addr = reinterpret_cast<uint32_t>(key_offset.address()); |
- uint32_t value_off_addr = reinterpret_cast<uint32_t>(value_offset.address()); |
- uint32_t map_off_addr = reinterpret_cast<uint32_t>(map_offset.address()); |
+ uintptr_t key_off_addr = reinterpret_cast<uintptr_t>(key_offset.address()); |
+ uintptr_t value_off_addr = |
+ reinterpret_cast<uintptr_t>(value_offset.address()); |
+ uintptr_t map_off_addr = reinterpret_cast<uintptr_t>(map_offset.address()); |
// Check the relative positions of the address fields. |
ASSERT(value_off_addr > key_off_addr); |
@@ -48,50 +52,54 @@ static void ProbeTable(Isolate* isolate, |
scratch = no_reg; |
// Multiply by 3 because there are 3 fields per entry (name, code, map). |
- __ add(offset_scratch, offset, Operand(offset, LSL, 1)); |
+ __ ShiftLeftImm(offset_scratch, offset, Operand(1)); |
+ __ add(offset_scratch, offset, offset_scratch); |
// Calculate the base address of the entry. |
__ mov(base_addr, Operand(key_offset)); |
- __ add(base_addr, base_addr, Operand(offset_scratch, LSL, kPointerSizeLog2)); |
+ __ ShiftLeftImm(scratch2, offset_scratch, Operand(kPointerSizeLog2)); |
+ __ add(base_addr, base_addr, scratch2); |
// Check that the key in the entry matches the name. |
- __ ldr(ip, MemOperand(base_addr, 0)); |
+ __ LoadP(ip, MemOperand(base_addr, 0)); |
__ cmp(name, ip); |
- __ b(ne, &miss); |
+ __ bne(&miss); |
// Check the map matches. |
- __ ldr(ip, MemOperand(base_addr, map_off_addr - key_off_addr)); |
- __ ldr(scratch2, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
+ __ LoadP(ip, MemOperand(base_addr, map_off_addr - key_off_addr)); |
+ __ LoadP(scratch2, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
__ cmp(ip, scratch2); |
- __ b(ne, &miss); |
+ __ bne(&miss); |
// Get the code entry from the cache. |
Register code = scratch2; |
scratch2 = no_reg; |
- __ ldr(code, MemOperand(base_addr, value_off_addr - key_off_addr)); |
+ __ LoadP(code, MemOperand(base_addr, value_off_addr - key_off_addr)); |
// Check that the flags match what we're looking for. |
Register flags_reg = base_addr; |
base_addr = no_reg; |
- __ ldr(flags_reg, FieldMemOperand(code, Code::kFlagsOffset)); |
- // It's a nice optimization if this constant is encodable in the bic insn. |
+ __ lwz(flags_reg, FieldMemOperand(code, Code::kFlagsOffset)); |
- uint32_t mask = Code::kFlagsNotUsedInLookup; |
- ASSERT(__ ImmediateFitsAddrMode1Instruction(mask)); |
- __ bic(flags_reg, flags_reg, Operand(mask)); |
- __ cmp(flags_reg, Operand(flags)); |
- __ b(ne, &miss); |
+ ASSERT(!r0.is(flags_reg)); |
+ __ li(r0, Operand(Code::kFlagsNotUsedInLookup)); |
+ __ andc(flags_reg, flags_reg, r0); |
+ __ mov(r0, Operand(flags)); |
+ __ cmpl(flags_reg, r0); |
+ __ bne(&miss); |
#ifdef DEBUG |
if (FLAG_test_secondary_stub_cache && table == StubCache::kPrimary) { |
- __ jmp(&miss); |
+ __ b(&miss); |
} else if (FLAG_test_primary_stub_cache && table == StubCache::kSecondary) { |
- __ jmp(&miss); |
+ __ b(&miss); |
} |
#endif |
// Jump to the first instruction in the code stub. |
- __ add(pc, code, Operand(Code::kHeaderSize - kHeapObjectTag)); |
+ __ addi(r0, code, Operand(Code::kHeaderSize - kHeapObjectTag)); |
+ __ mtctr(r0); |
+ __ bctr(); |
// Miss: fall through. |
__ bind(&miss); |
@@ -114,28 +122,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(masm, |
@@ -161,9 +169,15 @@ void StubCache::GenerateProbe(MacroAssembler* masm, |
Isolate* isolate = masm->isolate(); |
Label miss; |
+#if V8_TARGET_ARCH_PPC64 |
+ // Make sure that code is valid. The multiplying code relies on the |
+ // entry size being 24. |
+ ASSERT(sizeof(Entry) == 24); |
+#else |
// Make sure that code is valid. The multiplying code relies on the |
// entry size being 12. |
ASSERT(sizeof(Entry) == 12); |
+#endif |
// Make sure the flags does not name a specific type. |
ASSERT(Code::ExtractTypeFromFlags(flags) == 0); |
@@ -193,18 +207,22 @@ void StubCache::GenerateProbe(MacroAssembler* masm, |
__ JumpIfSmi(receiver, &miss); |
// Get the map of the receiver and compute the hash. |
- __ ldr(scratch, FieldMemOperand(name, Name::kHashFieldOffset)); |
- __ ldr(ip, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
- __ add(scratch, scratch, Operand(ip)); |
+ __ lwz(scratch, FieldMemOperand(name, Name::kHashFieldOffset)); |
+ __ LoadP(ip, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
+ __ add(scratch, scratch, ip); |
+#if V8_TARGET_ARCH_PPC64 |
+ // Use only the low 32 bits of the map pointer. |
+ __ rldicl(scratch, scratch, 0, 32); |
+#endif |
uint32_t mask = kPrimaryTableSize - 1; |
// We shift out the last two bits because they are not part of the hash and |
// they are always 01 for maps. |
- __ mov(scratch, Operand(scratch, LSR, kCacheIndexShift)); |
+ __ ShiftRightImm(scratch, scratch, Operand(kCacheIndexShift)); |
// Mask down the eor argument to the minimum to keep the immediate |
- // ARM-encodable. |
- __ eor(scratch, scratch, Operand((flags >> kCacheIndexShift) & mask)); |
+ // encodable. |
+ __ xori(scratch, scratch, Operand((flags >> kCacheIndexShift) & mask)); |
// Prefer and_ to ubfx here because ubfx takes 2 cycles. |
- __ and_(scratch, scratch, Operand(mask)); |
+ __ andi(scratch, scratch, Operand(mask)); |
// Probe the primary table. |
ProbeTable(isolate, |
@@ -219,10 +237,11 @@ void StubCache::GenerateProbe(MacroAssembler* masm, |
extra3); |
// Primary miss: Compute hash for secondary probe. |
- __ sub(scratch, scratch, Operand(name, LSR, kCacheIndexShift)); |
+ __ ShiftRightImm(extra, name, Operand(kCacheIndexShift)); |
+ __ sub(scratch, scratch, extra); |
uint32_t mask2 = kSecondaryTableSize - 1; |
- __ add(scratch, scratch, Operand((flags >> kCacheIndexShift) & mask2)); |
- __ and_(scratch, scratch, Operand(mask2)); |
+ __ addi(scratch, scratch, Operand((flags >> kCacheIndexShift) & mask2)); |
+ __ andi(scratch, scratch, Operand(mask2)); |
// Probe the secondary table. |
ProbeTable(isolate, |
@@ -254,17 +273,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)); |
} |
@@ -272,7 +292,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(); |
} |
@@ -286,10 +306,10 @@ void PropertyHandlerCompiler::GenerateCheckPropertyCell( |
Handle<Cell> cell = JSGlobalObject::EnsurePropertyCell(global, name); |
ASSERT(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); |
} |
@@ -306,7 +326,7 @@ void NamedStoreHandlerCompiler::GenerateNegativeHolderLookup( |
} |
-// Generate StoreTransition code, value is passed in r0 register. |
+// Generate StoreTransition code, value is passed in r3 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. |
@@ -315,7 +335,7 @@ 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 |
+ // r3 : value |
Label exit; |
int descriptor = transition->LastAdded(); |
@@ -328,7 +348,7 @@ void NamedStoreHandlerCompiler::GenerateStoreTransition( |
Handle<Object> constant(descriptors->GetValue(descriptor), masm->isolate()); |
__ Move(scratch1, constant); |
__ cmp(value_reg, scratch1); |
- __ b(ne, miss_label); |
+ __ bne(miss_label); |
} else if (representation.IsSmi()) { |
__ JumpIfNotSmi(value_reg, miss_label); |
} else if (representation.IsHeapObject()) { |
@@ -336,16 +356,16 @@ void NamedStoreHandlerCompiler::GenerateStoreTransition( |
HeapType* field_type = descriptors->GetFieldType(descriptor); |
HeapType::Iterator<Map> it = field_type->Classes(); |
if (!it.Done()) { |
- __ ldr(scratch1, FieldMemOperand(value_reg, HeapObject::kMapOffset)); |
+ __ LoadP(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); |
+ __ bne(miss_label); |
break; |
} |
- __ b(eq, &do_store); |
+ __ beq(&do_store); |
} |
__ bind(&do_store); |
} |
@@ -357,17 +377,16 @@ void NamedStoreHandlerCompiler::GenerateStoreTransition( |
__ JumpIfNotSmi(value_reg, &heap_number); |
__ SmiUntag(scratch1, value_reg); |
- __ vmov(s0, scratch1); |
- __ vcvt_f64_s32(d0, s0); |
+ __ ConvertIntToDouble(scratch1, d0); |
__ 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)); |
+ __ lfd(d0, FieldMemOperand(value_reg, HeapNumber::kValueOffset)); |
__ bind(&do_store); |
- __ vstr(d0, FieldMemOperand(storage_reg, HeapNumber::kValueOffset)); |
+ __ stfd(d0, FieldMemOperand(storage_reg, HeapNumber::kValueOffset)); |
} |
// Stub never generated for non-global objects that require access |
@@ -380,8 +399,8 @@ void NamedStoreHandlerCompiler::GenerateStoreTransition( |
// 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); |
+ __ mov(r5, Operand(transition)); |
+ __ Push(r5, r3); |
__ TailCallExternalReference( |
ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), |
masm->isolate()), |
@@ -392,7 +411,8 @@ void NamedStoreHandlerCompiler::GenerateStoreTransition( |
// Update the map of the object. |
__ mov(scratch1, Operand(transition)); |
- __ str(scratch1, FieldMemOperand(receiver_reg, HeapObject::kMapOffset)); |
+ __ StoreP(scratch1, FieldMemOperand(receiver_reg, HeapObject::kMapOffset), |
+ r0); |
// Update the write barrier for the map field. |
__ RecordWriteField(receiver_reg, |
@@ -405,7 +425,7 @@ void NamedStoreHandlerCompiler::GenerateStoreTransition( |
OMIT_SMI_CHECK); |
if (details.type() == CONSTANT) { |
- ASSERT(value_reg.is(r0)); |
+ ASSERT(value_reg.is(r3)); |
__ Ret(); |
return; |
} |
@@ -425,15 +445,15 @@ void NamedStoreHandlerCompiler::GenerateStoreTransition( |
// Set the property straight into the object. |
int offset = object->map()->instance_size() + (index * kPointerSize); |
if (representation.IsDouble()) { |
- __ str(storage_reg, FieldMemOperand(receiver_reg, offset)); |
+ __ StoreP(storage_reg, FieldMemOperand(receiver_reg, offset), r0); |
} else { |
- __ str(value_reg, FieldMemOperand(receiver_reg, offset)); |
+ __ StoreP(value_reg, FieldMemOperand(receiver_reg, offset), r0); |
} |
if (!representation.IsSmi()) { |
- // Update the write barrier for the array address. |
+ // Update the write barrier for the array address. |
if (!representation.IsDouble()) { |
- __ mov(storage_reg, value_reg); |
+ __ mr(storage_reg, value_reg); |
} |
__ RecordWriteField(receiver_reg, |
offset, |
@@ -448,18 +468,18 @@ void NamedStoreHandlerCompiler::GenerateStoreTransition( |
// Write to the properties array. |
int offset = index * kPointerSize + FixedArray::kHeaderSize; |
// Get the properties array |
- __ ldr(scratch1, |
- FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset)); |
+ __ LoadP(scratch1, |
+ FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset)); |
if (representation.IsDouble()) { |
- __ str(storage_reg, FieldMemOperand(scratch1, offset)); |
+ __ StoreP(storage_reg, FieldMemOperand(scratch1, offset), r0); |
} else { |
- __ str(value_reg, FieldMemOperand(scratch1, offset)); |
+ __ StoreP(value_reg, FieldMemOperand(scratch1, offset), r0); |
} |
if (!representation.IsSmi()) { |
// Update the write barrier for the array address. |
if (!representation.IsDouble()) { |
- __ mov(storage_reg, value_reg); |
+ __ mr(storage_reg, value_reg); |
} |
__ RecordWriteField(scratch1, |
offset, |
@@ -472,14 +492,14 @@ void NamedStoreHandlerCompiler::GenerateStoreTransition( |
} |
} |
- // Return the value (register r0). |
- ASSERT(value_reg.is(r0)); |
+ // Return the value (register r3). |
+ ASSERT(value_reg.is(r3)); |
__ bind(&exit); |
__ Ret(); |
} |
-// Generate StoreField code, value is passed in r0 register. |
+// Generate StoreField code, value is passed in r3 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. |
@@ -487,7 +507,7 @@ void NamedStoreHandlerCompiler::GenerateStoreField( |
MacroAssembler* masm, Handle<JSObject> object, LookupResult* lookup, |
Register receiver_reg, Register name_reg, Register value_reg, |
Register scratch1, Register scratch2, Label* miss_label) { |
- // r0 : value |
+ // r3 : value |
Label exit; |
// Stub never generated for non-global objects that require access |
@@ -505,46 +525,45 @@ void NamedStoreHandlerCompiler::GenerateStoreField( |
HeapType* field_type = lookup->GetFieldType(); |
HeapType::Iterator<Map> it = field_type->Classes(); |
if (!it.Done()) { |
- __ ldr(scratch1, FieldMemOperand(value_reg, HeapObject::kMapOffset)); |
+ __ LoadP(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); |
+ __ bne(miss_label); |
break; |
} |
- __ b(eq, &do_store); |
+ __ beq(&do_store); |
} |
__ bind(&do_store); |
} |
} else if (representation.IsDouble()) { |
// Load the double storage. |
if (index.is_inobject()) { |
- __ ldr(scratch1, FieldMemOperand(receiver_reg, index.offset())); |
+ __ LoadP(scratch1, FieldMemOperand(receiver_reg, index.offset())); |
} else { |
- __ ldr(scratch1, |
+ __ LoadP(scratch1, |
FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset)); |
- __ ldr(scratch1, FieldMemOperand(scratch1, index.offset())); |
+ __ LoadP(scratch1, FieldMemOperand(scratch1, index.offset())); |
} |
// Store the value into the storage. |
Label do_store, heap_number; |
__ JumpIfNotSmi(value_reg, &heap_number); |
__ SmiUntag(scratch2, value_reg); |
- __ vmov(s0, scratch2); |
- __ vcvt_f64_s32(d0, s0); |
+ __ ConvertIntToDouble(scratch2, d0); |
__ jmp(&do_store); |
__ bind(&heap_number); |
__ CheckMap(value_reg, scratch2, Heap::kHeapNumberMapRootIndex, |
miss_label, DONT_DO_SMI_CHECK); |
- __ vldr(d0, FieldMemOperand(value_reg, HeapNumber::kValueOffset)); |
+ __ lfd(d0, FieldMemOperand(value_reg, HeapNumber::kValueOffset)); |
__ bind(&do_store); |
- __ vstr(d0, FieldMemOperand(scratch1, HeapNumber::kValueOffset)); |
- // Return the value (register r0). |
- ASSERT(value_reg.is(r0)); |
+ __ stfd(d0, FieldMemOperand(scratch1, HeapNumber::kValueOffset)); |
+ // Return the value (register r3). |
+ ASSERT(value_reg.is(r3)); |
__ Ret(); |
return; |
} |
@@ -554,7 +573,7 @@ void NamedStoreHandlerCompiler::GenerateStoreField( |
? INLINE_SMI_CHECK : OMIT_SMI_CHECK; |
if (index.is_inobject()) { |
// Set the property straight into the object. |
- __ str(value_reg, FieldMemOperand(receiver_reg, index.offset())); |
+ __ StoreP(value_reg, FieldMemOperand(receiver_reg, index.offset()), r0); |
if (!representation.IsSmi()) { |
// Skip updating write barrier if storing a smi. |
@@ -562,7 +581,7 @@ void NamedStoreHandlerCompiler::GenerateStoreField( |
// Update the write barrier for the array address. |
// Pass the now unused name_reg as a scratch register. |
- __ mov(name_reg, value_reg); |
+ __ mr(name_reg, value_reg); |
__ RecordWriteField(receiver_reg, |
index.offset(), |
name_reg, |
@@ -575,9 +594,9 @@ void NamedStoreHandlerCompiler::GenerateStoreField( |
} else { |
// Write to the properties array. |
// Get the properties array |
- __ ldr(scratch1, |
+ __ LoadP(scratch1, |
FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset)); |
- __ str(value_reg, FieldMemOperand(scratch1, index.offset())); |
+ __ StoreP(value_reg, FieldMemOperand(scratch1, index.offset()), r0); |
if (!representation.IsSmi()) { |
// Skip updating write barrier if storing a smi. |
@@ -585,7 +604,7 @@ void NamedStoreHandlerCompiler::GenerateStoreField( |
// Update the write barrier for the array address. |
// Ok to clobber receiver_reg and name_reg, since we return. |
- __ mov(name_reg, value_reg); |
+ __ mr(name_reg, value_reg); |
__ RecordWriteField(scratch1, |
index.offset(), |
name_reg, |
@@ -597,8 +616,8 @@ void NamedStoreHandlerCompiler::GenerateStoreField( |
} |
} |
- // Return the value (register r0). |
- ASSERT(value_reg.is(r0)); |
+ // Return the value (register r3). |
+ ASSERT(value_reg.is(r3)); |
__ bind(&exit); |
__ Ret(); |
} |
@@ -666,10 +685,10 @@ void PropertyHandlerCompiler::GenerateFastApiCall( |
ASSERT(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; |
@@ -700,7 +719,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); |
@@ -780,16 +800,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 |
@@ -812,7 +832,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)); |
} |
@@ -881,7 +901,7 @@ Register NamedLoadHandlerCompiler::CallbackFrontend(Handle<HeapType> type, |
// Load the properties dictionary. |
Register dictionary = scratch4(); |
- __ ldr(dictionary, FieldMemOperand(reg, JSObject::kPropertiesOffset)); |
+ __ LoadP(dictionary, FieldMemOperand(reg, JSObject::kPropertiesOffset)); |
// Probe the dictionary. |
Label probe_done; |
@@ -900,9 +920,10 @@ Register NamedLoadHandlerCompiler::CallbackFrontend(Handle<HeapType> type, |
const int kElementsStartOffset = NameDictionary::kHeaderSize + |
NameDictionary::kElementsStartIndex * kPointerSize; |
const int kValueOffset = kElementsStartOffset + kPointerSize; |
- __ ldr(scratch2(), FieldMemOperand(pointer, kValueOffset)); |
- __ cmp(scratch2(), Operand(callback)); |
- __ b(ne, &miss); |
+ __ LoadP(scratch2(), FieldMemOperand(pointer, kValueOffset)); |
+ __ mov(scratch3(), Operand(callback)); |
+ __ cmp(scratch2(), scratch3()); |
+ __ bne(&miss); |
} |
FrontendFooter(name, &miss); |
@@ -913,7 +934,7 @@ Register NamedLoadHandlerCompiler::CallbackFrontend(Handle<HeapType> type, |
void NamedLoadHandlerCompiler::GenerateLoadField( |
Register reg, Handle<JSObject> holder, FieldIndex field, |
Representation representation) { |
- if (!reg.is(receiver())) __ mov(receiver(), reg); |
+ if (!reg.is(receiver())) __ mr(receiver(), reg); |
LoadFieldStub stub(isolate(), field); |
GenerateTailCall(masm(), stub.GetCode()); |
} |
@@ -921,7 +942,7 @@ void NamedLoadHandlerCompiler::GenerateLoadField( |
void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { |
// Return the constant value. |
- __ Move(r0, value); |
+ __ Move(r3, value); |
__ Ret(); |
} |
@@ -943,23 +964,22 @@ void NamedLoadHandlerCompiler::GenerateLoadCallback( |
__ push(receiver()); |
if (heap()->InNewSpace(callback->data())) { |
__ Move(scratch3(), callback); |
- __ ldr(scratch3(), FieldMemOperand(scratch3(), |
+ __ 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 |
- Register getter_address_reg = r2; |
+ Register getter_address_reg = r5; |
Address getter_address = v8::ToCData<Address>(callback->getter()); |
ApiFunction fun(getter_address); |
@@ -1029,8 +1049,8 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor( |
// 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(); |
@@ -1067,8 +1087,7 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( |
// Stub never generated for non-global objects that require access checks. |
ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); |
- __ push(receiver()); // receiver |
- __ push(holder_reg); |
+ __ Push(receiver(), holder_reg); // receiver |
__ mov(ip, Operand(callback)); // callback info |
__ push(ip); |
__ mov(ip, Operand(name)); |
@@ -1104,8 +1123,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); |
@@ -1119,10 +1138,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(); |
} |
@@ -1152,7 +1171,7 @@ Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( |
// Return undefined if maps of the full prototype chain are still the |
// same and no global property with this name contains a value. |
- __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); |
+ __ LoadRoot(r3, Heap::kUndefinedValueRootIndex); |
__ Ret(); |
// Return the generated code. |
@@ -1164,7 +1183,7 @@ Register* PropertyAccessCompiler::load_calling_convention() { |
// receiver, name, scratch1, scratch2, scratch3, scratch4. |
Register receiver = LoadIC::ReceiverRegister(); |
Register name = LoadIC::NameRegister(); |
- static Register registers[] = { receiver, name, r3, r0, r4, r5 }; |
+ static Register registers[] = { receiver, name, r6, r3, r7, r8 }; |
return registers; |
} |
@@ -1173,7 +1192,7 @@ Register* PropertyAccessCompiler::store_calling_convention() { |
// receiver, name, scratch1, scratch2, scratch3. |
Register receiver = StoreIC::ReceiverRegister(); |
Register name = StoreIC::NameRegister(); |
- static Register registers[] = { receiver, name, r3, r4, r5 }; |
+ static Register registers[] = { receiver, name, r6, r7, r8 }; |
return registers; |
} |
@@ -1183,7 +1202,7 @@ Register* PropertyAccessCompiler::keyed_store_calling_convention() { |
Register receiver = KeyedStoreIC::ReceiverRegister(); |
Register name = KeyedStoreIC::NameRegister(); |
Register map = KeyedStoreIC::MapRegister(); |
- static Register registers[] = { receiver, name, map, r4, r5 }; |
+ static Register registers[] = { receiver, name, map, r7, r8 }; |
return registers; |
} |
@@ -1199,8 +1218,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 |
// ----------------------------------- |
{ |
@@ -1210,8 +1229,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); |
@@ -1225,7 +1244,7 @@ void NamedLoadHandlerCompiler::GenerateLoadViaGetter( |
} |
// Restore context register. |
- __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
+ __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
} |
__ Ret(); |
} |
@@ -1242,19 +1261,19 @@ Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( |
FrontendHeader(type, receiver(), global, name, &miss); |
// Get the value from the cell. |
- __ mov(r3, Operand(cell)); |
- __ ldr(r4, FieldMemOperand(r3, Cell::kValueOffset)); |
+ __ mov(r6, Operand(cell)); |
+ __ LoadP(r7, FieldMemOperand(r6, Cell::kValueOffset)); |
// Check for deleted property if property can actually be deleted. |
if (!is_dont_delete) { |
__ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
- __ cmp(r4, ip); |
- __ b(eq, &miss); |
+ __ cmp(r7, ip); |
+ __ beq(&miss); |
} |
Counters* counters = isolate()->counters(); |
- __ IncrementCounter(counters->named_load_global_stub(), 1, r1, r3); |
- __ mov(r0, r4); |
+ __ IncrementCounter(counters->named_load_global_stub(), 1, r4, r6); |
+ __ mr(r3, r7); |
__ Ret(); |
FrontendFooter(name, &miss); |
@@ -1273,8 +1292,8 @@ Handle<Code> PropertyICCompiler::CompilePolymorphic(TypeHandleList* types, |
if (check == PROPERTY && |
(kind() == Code::KEYED_LOAD_IC || kind() == Code::KEYED_STORE_IC)) { |
- __ cmp(this->name(), Operand(name)); |
- __ b(ne, &miss); |
+ __ Cmpi(this->name(), Operand(name), r0); |
+ __ bne(&miss); |
} |
Label number_case; |
@@ -1288,7 +1307,7 @@ Handle<Code> PropertyICCompiler::CompilePolymorphic(TypeHandleList* types, |
int receiver_count = types->length(); |
int number_of_handled_maps = 0; |
- __ ldr(map_reg, FieldMemOperand(receiver(), HeapObject::kMapOffset)); |
+ __ LoadP(map_reg, FieldMemOperand(receiver(), HeapObject::kMapOffset)); |
for (int current = 0; current < receiver_count; ++current) { |
Handle<HeapType> type = types->at(current); |
Handle<Map> map = IC::TypeToMap(*type, isolate()); |
@@ -1333,15 +1352,18 @@ Handle<Code> PropertyICCompiler::CompileIndexedStorePolymorphic( |
__ JumpIfSmi(receiver(), &miss); |
int receiver_count = receiver_maps->length(); |
- __ ldr(scratch1(), FieldMemOperand(receiver(), HeapObject::kMapOffset)); |
+ __ LoadP(scratch1(), FieldMemOperand(receiver(), HeapObject::kMapOffset)); |
for (int i = 0; i < receiver_count; ++i) { |
__ mov(ip, Operand(receiver_maps->at(i))); |
__ cmp(scratch1(), ip); |
if (transitioned_maps->at(i).is_null()) { |
- __ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET, eq); |
+ Label skip; |
+ __ bne(&skip); |
+ __ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET); |
+ __ bind(&skip); |
} else { |
Label next_map; |
- __ b(ne, &next_map); |
+ __ bne(&next_map); |
__ mov(transition_map(), Operand(transitioned_maps->at(i))); |
__ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET, al); |
__ bind(&next_map); |
@@ -1367,18 +1389,18 @@ void IndexedHandlerCompiler::GenerateLoadDictionaryElement( |
Register key = LoadIC::NameRegister(); |
Register receiver = LoadIC::ReceiverRegister(); |
- ASSERT(receiver.is(r1)); |
- ASSERT(key.is(r2)); |
+ ASSERT(receiver.is(r4)); |
+ ASSERT(key.is(r5)); |
- __ UntagAndJumpIfNotSmi(r6, key, &miss); |
- __ ldr(r4, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
- __ LoadFromNumberDictionary(&slow, r4, key, r0, r6, r3, r5); |
+ __ UntagAndJumpIfNotSmi(r9, key, &miss); |
+ __ LoadP(r7, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
+ __ LoadFromNumberDictionary(&slow, r7, key, r3, r9, r6, r8); |
__ Ret(); |
__ bind(&slow); |
__ IncrementCounter( |
masm->isolate()->counters()->keyed_load_external_array_slow(), |
- 1, r2, r3); |
+ 1, r5, r6); |
TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Slow); |
@@ -1393,4 +1415,4 @@ void IndexedHandlerCompiler::GenerateLoadDictionaryElement( |
} } // namespace v8::internal |
-#endif // V8_TARGET_ARCH_ARM |
+#endif // V8_TARGET_ARCH_PPC |