Chromium Code Reviews

Unified Diff: src/arm/codegen-arm.cc

Issue 1719021: Add inlining of keyed store on ARM... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
« no previous file with comments | « src/arm/codegen-arm.h ('k') | src/arm/ic-arm.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/arm/codegen-arm.cc
===================================================================
--- src/arm/codegen-arm.cc (revision 4527)
+++ src/arm/codegen-arm.cc (working copy)
@@ -5245,8 +5245,10 @@
void DeferredReferenceGetNamedValue::Generate() {
- __ DecrementCounter(&Counters::named_load_inline, 1, r1, r2);
- __ IncrementCounter(&Counters::named_load_inline_miss, 1, r1, r2);
+ Register scratch1 = VirtualFrame::scratch0();
+ Register scratch2 = VirtualFrame::scratch1();
+ __ DecrementCounter(&Counters::named_load_inline, 1, scratch1, scratch2);
+ __ IncrementCounter(&Counters::named_load_inline_miss, 1, scratch1, scratch2);
// Setup the registers and call load IC.
// On entry to this deferred code, r0 is assumed to already contain the
@@ -5259,7 +5261,7 @@
__ Call(ic, RelocInfo::CODE_TARGET);
// The call must be followed by a nop(1) instruction to indicate that the
// in-object has been inlined.
- __ nop(PROPERTY_LOAD_INLINED);
+ __ nop(PROPERTY_ACCESS_INLINED);
// Block the constant pool for one more instruction after leaving this
// constant pool block scope to include the branch instruction ending the
@@ -5292,7 +5294,7 @@
__ Call(ic, RelocInfo::CODE_TARGET);
// The call must be followed by a nop instruction to indicate that the
// keyed load has been inlined.
- __ nop(PROPERTY_LOAD_INLINED);
+ __ nop(PROPERTY_ACCESS_INLINED);
// Block the constant pool for one more instruction after leaving this
// constant pool block scope to include the branch instruction ending the
@@ -5302,6 +5304,41 @@
}
+class DeferredReferenceSetKeyedValue: public DeferredCode {
+ public:
+ DeferredReferenceSetKeyedValue() {
+ set_comment("[ DeferredReferenceSetKeyedValue");
+ }
+
+ virtual void Generate();
+};
+
+
+void DeferredReferenceSetKeyedValue::Generate() {
+ Register scratch1 = VirtualFrame::scratch0();
+ Register scratch2 = VirtualFrame::scratch1();
+ __ DecrementCounter(&Counters::keyed_store_inline, 1, scratch1, scratch2);
+ __ IncrementCounter(
+ &Counters::keyed_store_inline_miss, 1, scratch1, scratch2);
+
+ // The rest of the instructions in the deferred code must be together.
+ { Assembler::BlockConstPoolScope block_const_pool(masm_);
+ // Call keyed load IC. It has receiver amd key on the stack and the value to
+ // store in r0.
+ Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+ __ Call(ic, RelocInfo::CODE_TARGET);
+ // The call must be followed by a nop instruction to indicate that the
+ // keyed store has been inlined.
+ __ nop(PROPERTY_ACCESS_INLINED);
+
+ // Block the constant pool for one more instruction after leaving this
+ // constant pool block scope to include the branch instruction ending the
+ // deferred code.
+ __ BlockConstPoolFor(1);
+ }
+}
+
+
void CodeGenerator::EmitNamedLoad(Handle<String> name, bool is_contextual) {
if (is_contextual || scope()->is_global_scope() || loop_nesting() == 0) {
Comment cmnt(masm(), "[ Load from named Property");
@@ -5390,10 +5427,10 @@
__ tst(receiver, Operand(kSmiTagMask));
deferred->Branch(eq);
- // The following instructions are the inlined load keyed property. Parts
- // of this code are patched, so the exact number of instructions generated
- // need to be fixed. Therefore the constant pool is blocked while generating
- // this code.
+ // The following instructions are the part of the inlined load keyed
+ // property code which can be patched. Therefore the exact number of
+ // instructions generated need to be fixed, so the constant pool is blocked
+ // while generating this code.
#ifdef DEBUG
int kInlinedKeyedLoadInstructions = 19;
Label check_inlined_codesize;
@@ -5421,7 +5458,8 @@
__ cmp(scratch2, ip);
deferred->Branch(ne);
- // Check that key is within bounds.
+ // Check that key is within bounds. Use unsigned comparison to handle
+ // negative keys.
__ ldr(scratch2, FieldMemOperand(scratch1, FixedArray::kLengthOffset));
__ cmp(scratch2, Operand(key, ASR, kSmiTagSize));
deferred->Branch(ls); // Unsigned less equal.
@@ -5450,7 +5488,90 @@
}
+void CodeGenerator::EmitKeyedStore(StaticType* key_type) {
+ frame_->AssertIsSpilled();
+ // Generate inlined version of the keyed store if the code is in a loop
+ // and the key is likely to be a smi.
+ if (loop_nesting() > 0 && key_type->IsLikelySmi()) {
+ // Inline the keyed store.
+ Comment cmnt(masm_, "[ Inlined store to keyed property");
+
+ DeferredReferenceSetKeyedValue* deferred =
+ new DeferredReferenceSetKeyedValue();
+
+ // Counter will be decremented in the deferred code. Placed here to avoid
+ // having it in the instruction stream below where patching will occur.
+ __ IncrementCounter(&Counters::keyed_store_inline, 1,
+ frame_->scratch0(), frame_->scratch1());
+
+ // Check that the value is a smi. As this inlined code does not set the
+ // write barrier it is only possible to store smi values.
+ __ tst(r0, Operand(kSmiTagMask));
+ deferred->Branch(ne);
+
+ // Load the key and receiver from the stack.
+ __ ldr(r1, MemOperand(sp, 0));
+ __ ldr(r2, MemOperand(sp, kPointerSize));
+
+ // Check that the key is a smi.
+ __ tst(r1, Operand(kSmiTagMask));
+ deferred->Branch(ne);
+
+ // Check that the receiver is a heap object.
+ __ tst(r2, Operand(kSmiTagMask));
+ deferred->Branch(eq);
+
+ // Check that the receiver is a JSArray.
+ __ CompareObjectType(r2, r3, r3, JS_ARRAY_TYPE);
+ deferred->Branch(ne);
+
+ // Check that the key is within bounds. Both the key and the length of
+ // the JSArray are smis. Use unsigned comparison to handle negative keys.
+ __ ldr(r3, FieldMemOperand(r2, JSArray::kLengthOffset));
+ __ cmp(r3, r1);
+ deferred->Branch(ls); // Unsigned less equal.
+
+ // The following instructions are the part of the inlined store keyed
+ // property code which can be patched. Therefore the exact number of
+ // instructions generated need to be fixed, so the constant pool is blocked
+ // while generating this code.
#ifdef DEBUG
+ int kInlinedKeyedStoreInstructions = 7;
+ Label check_inlined_codesize;
+ masm_->bind(&check_inlined_codesize);
+#endif
+ { Assembler::BlockConstPoolScope block_const_pool(masm_);
+ // Get the elements array from the receiver and check that it
+ // is not a dictionary.
+ __ ldr(r3, FieldMemOperand(r2, JSObject::kElementsOffset));
+ __ ldr(r4, FieldMemOperand(r3, JSObject::kMapOffset));
+ // Read the fixed array map from the constant pool (not from the root
+ // array) so that the value can be patched. When debugging, we patch this
+ // comparison to always fail so that we will hit the IC call in the
+ // deferred code which will allow the debugger to break for fast case
+ // stores.
+ __ mov(r5, Operand(Factory::fixed_array_map()));
+ __ cmp(r4, r5);
+ deferred->Branch(ne);
+
+ // Store the value.
+ __ add(r3, r3, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
+ __ str(r0, MemOperand(r3, r1, LSL,
+ kPointerSizeLog2 - (kSmiTagSize + kSmiShiftSize)));
+
+ // Make sure that the expected number of instructions are generated.
+ ASSERT_EQ(kInlinedKeyedStoreInstructions,
+ masm_->InstructionsGeneratedSince(&check_inlined_codesize));
+ }
+
+ deferred->BindExit();
+ } else {
+ frame()->CallKeyedStoreIC();
+ }
+}
+
+
+#ifdef DEBUG
bool CodeGenerator::HasValidEntryRegisters() { return true; }
#endif
@@ -5563,10 +5684,8 @@
ASSERT(property != NULL);
cgen_->CodeForSourcePosition(property->position());
- // Call IC code.
- Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
- frame->EmitPop(r0); // value
- frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
+ frame->EmitPop(r0); // Value.
+ cgen_->EmitKeyedStore(property->key()->type());
frame->EmitPush(r0);
cgen_->UnloadReference(this);
break;
« no previous file with comments | « src/arm/codegen-arm.h ('k') | src/arm/ic-arm.cc » ('j') | no next file with comments »

Powered by Google App Engine