From a6c5fa6993c1506ab5df42c1e7f2cae9b58c7771 Mon Sep 17 00:00:00 2001 From: "sgjesse@chromium.org" Date: Fri, 7 Jan 2011 07:33:46 +0000 Subject: [PATCH] ARM implementations of LoadElements, LoadKeyedFastElement, StoreNamedField, StoreKeyedFastElement. BUG=none TEST=none Patch by Martyn Capewell from ARM Ltd. Review URL: http://codereview.chromium.org/5967008 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6214 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/lithium-arm.cc | 8 +-- src/arm/lithium-arm.h | 4 -- src/arm/lithium-codegen-arm.cc | 102 +++++++++++++++++++++++++++++-- src/ia32/lithium-codegen-ia32.cc | 1 - 4 files changed, 99 insertions(+), 16 deletions(-) diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc index 30a1bb7aeb..046bb58a52 100644 --- a/src/arm/lithium-arm.cc +++ b/src/arm/lithium-arm.cc @@ -1924,7 +1924,7 @@ LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) { LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) { - bool needs_write_barrier = !instr->value()->type().IsSmi(); + bool needs_write_barrier = instr->NeedsWriteBarrier(); LOperand* obj = needs_write_barrier ? UseTempRegister(instr->object()) @@ -1934,17 +1934,11 @@ LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) { ? UseTempRegister(instr->value()) : UseRegister(instr->value()); - // We only need a scratch register if we have a write barrier or we - // have a store into the properties array (not in-object-property). - LOperand* temp = (!instr->is_in_object() || needs_write_barrier) - ? TempRegister() : NULL; - return new LStoreNamedField(obj, instr->name(), val, instr->is_in_object(), instr->offset(), - temp, needs_write_barrier, instr->transition()); } diff --git a/src/arm/lithium-arm.h b/src/arm/lithium-arm.h index 077b71a0a5..9e88e64f61 100644 --- a/src/arm/lithium-arm.h +++ b/src/arm/lithium-arm.h @@ -1563,13 +1563,11 @@ class LStoreNamedField: public LStoreNamed { LOperand* val, bool in_object, int offset, - LOperand* temp, bool needs_write_barrier, Handle transition) : LStoreNamed(obj, name, val), is_in_object_(in_object), offset_(offset), - temp_(temp), needs_write_barrier_(needs_write_barrier), transition_(transition) { } @@ -1577,7 +1575,6 @@ class LStoreNamedField: public LStoreNamed { bool is_in_object() { return is_in_object_; } int offset() { return offset_; } - LOperand* temp() { return temp_; } bool needs_write_barrier() { return needs_write_barrier_; } Handle transition() const { return transition_; } void set_transition(Handle map) { transition_ = map; } @@ -1585,7 +1582,6 @@ class LStoreNamedField: public LStoreNamed { private: bool is_in_object_; int offset_; - LOperand* temp_; bool needs_write_barrier_; Handle transition_; }; diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc index 1bd61944b5..dca5f9b350 100644 --- a/src/arm/lithium-codegen-arm.cc +++ b/src/arm/lithium-codegen-arm.cc @@ -1583,7 +1583,22 @@ void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { void LCodeGen::DoLoadElements(LLoadElements* instr) { - Abort("DoLoadElements unimplemented."); + ASSERT(instr->result()->Equals(instr->input())); + Register reg = ToRegister(instr->input()); + Register scratch = scratch0(); + + __ ldr(reg, FieldMemOperand(reg, JSObject::kElementsOffset)); + if (FLAG_debug_code) { + Label done; + __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset)); + __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex); + __ cmp(scratch, ip); + __ b(eq, &done); + __ LoadRoot(ip, Heap::kFixedCOWArrayMapRootIndex); + __ cmp(scratch, ip); + __ Check(eq, "Check for fast elements failed."); + __ bind(&done); + } } @@ -1606,7 +1621,38 @@ void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) { - Abort("DoLoadKeyedFastElement unimplemented."); + Register elements = ToRegister(instr->elements()); + Register key = EmitLoadRegister(instr->key(), scratch0()); + Register result; + Register scratch = scratch0(); + + if (instr->load_result() != NULL) { + result = ToRegister(instr->load_result()); + } else { + result = ToRegister(instr->result()); + ASSERT(result.is(elements)); + } + + // Load the result. + __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2)); + __ ldr(result, FieldMemOperand(scratch, FixedArray::kHeaderSize)); + + Representation r = instr->hydrogen()->representation(); + if (r.IsInteger32()) { + // Untag and check for smi. + __ SmiUntag(result); + DeoptimizeIf(cs, instr->environment()); + } else if (r.IsDouble()) { + EmitNumberUntagD(result, + ToDoubleRegister(instr->result()), + instr->environment()); + } else { + // Check for the hole value. + ASSERT(r.IsTagged()); + __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex); + __ cmp(result, scratch); + DeoptimizeIf(eq, instr->environment()); + } } @@ -1821,7 +1867,34 @@ void LCodeGen::DoCallRuntime(LCallRuntime* instr) { void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { - Abort("DoStoreNamedField unimplemented."); + Register object = ToRegister(instr->object()); + Register value = ToRegister(instr->value()); + Register scratch = scratch0(); + int offset = instr->offset(); + + ASSERT(!object.is(value)); + + if (!instr->transition().is_null()) { + __ mov(scratch, Operand(instr->transition())); + __ str(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); + } + + // Do the store. + if (instr->is_in_object()) { + __ str(value, FieldMemOperand(object, offset)); + if (instr->needs_write_barrier()) { + // Update the write barrier for the object for in-object properties. + __ RecordWrite(object, Operand(offset), value, scratch); + } + } else { + __ ldr(scratch, FieldMemOperand(object, JSObject::kPropertiesOffset)); + __ str(value, FieldMemOperand(scratch, offset)); + if (instr->needs_write_barrier()) { + // Update the write barrier for the properties array. + // object is used as a scratch register. + __ RecordWrite(scratch, Operand(offset), value, object); + } + } } @@ -1843,7 +1916,28 @@ void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) { - Abort("DoStoreKeyedFastElement unimplemented."); + Register value = ToRegister(instr->value()); + Register elements = ToRegister(instr->object()); + Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg; + Register scratch = scratch0(); + + // Do the store. + if (instr->key()->IsConstantOperand()) { + ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); + LConstantOperand* const_operand = LConstantOperand::cast(instr->key()); + int offset = + ToInteger32(const_operand) * kPointerSize + FixedArray::kHeaderSize; + __ str(value, FieldMemOperand(elements, offset)); + } else { + __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2)); + __ str(value, FieldMemOperand(scratch, FixedArray::kHeaderSize)); + } + + if (instr->hydrogen()->NeedsWriteBarrier()) { + // Compute address of modified element and store it into key register. + __ add(key, scratch, Operand(FixedArray::kHeaderSize)); + __ RecordWrite(elements, key, value); + } } diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc index ee690c12e9..cea78e110c 100644 --- a/src/ia32/lithium-codegen-ia32.cc +++ b/src/ia32/lithium-codegen-ia32.cc @@ -2638,7 +2638,6 @@ void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) { value); } - // Update the write barrier unless we're certain that we're storing a smi. if (instr->hydrogen()->NeedsWriteBarrier()) { // Compute address of modified element and store it into key register. __ lea(key, FieldOperand(elements, key, times_4, FixedArray::kHeaderSize));