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
This commit is contained in:
parent
1eb68a859f
commit
a6c5fa6993
@ -1924,7 +1924,7 @@ LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
|
|||||||
|
|
||||||
|
|
||||||
LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* 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
|
LOperand* obj = needs_write_barrier
|
||||||
? UseTempRegister(instr->object())
|
? UseTempRegister(instr->object())
|
||||||
@ -1934,17 +1934,11 @@ LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
|
|||||||
? UseTempRegister(instr->value())
|
? UseTempRegister(instr->value())
|
||||||
: UseRegister(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,
|
return new LStoreNamedField(obj,
|
||||||
instr->name(),
|
instr->name(),
|
||||||
val,
|
val,
|
||||||
instr->is_in_object(),
|
instr->is_in_object(),
|
||||||
instr->offset(),
|
instr->offset(),
|
||||||
temp,
|
|
||||||
needs_write_barrier,
|
needs_write_barrier,
|
||||||
instr->transition());
|
instr->transition());
|
||||||
}
|
}
|
||||||
|
@ -1563,13 +1563,11 @@ class LStoreNamedField: public LStoreNamed {
|
|||||||
LOperand* val,
|
LOperand* val,
|
||||||
bool in_object,
|
bool in_object,
|
||||||
int offset,
|
int offset,
|
||||||
LOperand* temp,
|
|
||||||
bool needs_write_barrier,
|
bool needs_write_barrier,
|
||||||
Handle<Map> transition)
|
Handle<Map> transition)
|
||||||
: LStoreNamed(obj, name, val),
|
: LStoreNamed(obj, name, val),
|
||||||
is_in_object_(in_object),
|
is_in_object_(in_object),
|
||||||
offset_(offset),
|
offset_(offset),
|
||||||
temp_(temp),
|
|
||||||
needs_write_barrier_(needs_write_barrier),
|
needs_write_barrier_(needs_write_barrier),
|
||||||
transition_(transition) { }
|
transition_(transition) { }
|
||||||
|
|
||||||
@ -1577,7 +1575,6 @@ class LStoreNamedField: public LStoreNamed {
|
|||||||
|
|
||||||
bool is_in_object() { return is_in_object_; }
|
bool is_in_object() { return is_in_object_; }
|
||||||
int offset() { return offset_; }
|
int offset() { return offset_; }
|
||||||
LOperand* temp() { return temp_; }
|
|
||||||
bool needs_write_barrier() { return needs_write_barrier_; }
|
bool needs_write_barrier() { return needs_write_barrier_; }
|
||||||
Handle<Map> transition() const { return transition_; }
|
Handle<Map> transition() const { return transition_; }
|
||||||
void set_transition(Handle<Map> map) { transition_ = map; }
|
void set_transition(Handle<Map> map) { transition_ = map; }
|
||||||
@ -1585,7 +1582,6 @@ class LStoreNamedField: public LStoreNamed {
|
|||||||
private:
|
private:
|
||||||
bool is_in_object_;
|
bool is_in_object_;
|
||||||
int offset_;
|
int offset_;
|
||||||
LOperand* temp_;
|
|
||||||
bool needs_write_barrier_;
|
bool needs_write_barrier_;
|
||||||
Handle<Map> transition_;
|
Handle<Map> transition_;
|
||||||
};
|
};
|
||||||
|
@ -1583,7 +1583,22 @@ void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) {
|
|||||||
|
|
||||||
|
|
||||||
void LCodeGen::DoLoadElements(LLoadElements* 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) {
|
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) {
|
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) {
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2638,7 +2638,6 @@ void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) {
|
|||||||
value);
|
value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the write barrier unless we're certain that we're storing a smi.
|
|
||||||
if (instr->hydrogen()->NeedsWriteBarrier()) {
|
if (instr->hydrogen()->NeedsWriteBarrier()) {
|
||||||
// Compute address of modified element and store it into key register.
|
// Compute address of modified element and store it into key register.
|
||||||
__ lea(key, FieldOperand(elements, key, times_4, FixedArray::kHeaderSize));
|
__ lea(key, FieldOperand(elements, key, times_4, FixedArray::kHeaderSize));
|
||||||
|
Loading…
Reference in New Issue
Block a user