Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(209)

Unified Diff: runtime/vm/stub_code_arm64.cc

Issue 254673007: More stubs and instructions for arm64. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/simulator_arm64.cc ('k') | runtime/vm/unit_test.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/stub_code_arm64.cc
===================================================================
--- runtime/vm/stub_code_arm64.cc (revision 35551)
+++ runtime/vm/stub_code_arm64.cc (working copy)
@@ -379,8 +379,143 @@
}
+// Called for inline allocation of arrays.
+// Input parameters:
+// LR: return address.
+// R2: array length as Smi.
+// R1: array element type (either NULL or an instantiated type).
+// NOTE: R2 cannot be clobbered here as the caller relies on it being saved.
+// The newly allocated object is returned in R0.
void StubCode::GenerateAllocateArrayStub(Assembler* assembler) {
- __ Stop("GenerateAllocateArrayStub");
+ Label slow_case;
+ if (FLAG_inline_alloc) {
+ // Compute the size to be allocated, it is based on the array length
+ // and is computed as:
+ // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)).
+ // Assert that length is a Smi.
+ __ tsti(R2, kSmiTagMask);
+ if (FLAG_use_slow_path) {
+ __ b(&slow_case);
+ } else {
+ __ b(&slow_case, NE);
+ }
+ __ LoadFieldFromOffset(R8, CTX, Context::isolate_offset());
+ __ LoadFromOffset(R8, R8, Isolate::heap_offset());
+ __ LoadFromOffset(R8, R8, Heap::new_space_offset());
+
+ // Calculate and align allocation size.
+ // Load new object start and calculate next object start.
+ // R1: array element type.
+ // R2: array length as Smi.
+ // R8: points to new space object.
+ __ LoadFromOffset(R0, R8, Scavenger::top_offset());
+ intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1;
+ __ LoadImmediate(R3, fixed_size, kNoPP);
+ __ add(R3, R3, Operand(R2, LSL, 2)); // R2 is Smi.
+ ASSERT(kSmiTagShift == 1);
+ __ andi(R3, R3, ~(kObjectAlignment - 1));
+ __ add(R7, R3, Operand(R0));
+
+ // Check if the allocation fits into the remaining space.
+ // R0: potential new object start.
+ // R1: array element type.
+ // R2: array length as Smi.
+ // R3: array size.
+ // R7: potential next object start.
+ // R8: points to new space object.
+ __ LoadFromOffset(TMP, R8, Scavenger::end_offset());
+ __ CompareRegisters(R7, TMP);
+ __ b(&slow_case, CS); // Branch if unsigned higher or equal.
+
+ // Successfully allocated the object(s), now update top to point to
+ // next object start and initialize the object.
+ // R0: potential new object start.
+ // R3: array size.
+ // R7: potential next object start.
+ // R8: Points to new space object.
+ __ StoreToOffset(R7, R8, Scavenger::top_offset());
+ __ add(R0, R0, Operand(kHeapObjectTag));
+ __ UpdateAllocationStatsWithSize(kArrayCid, R3, R8, kNoPP);
+
+ // R0: new object start as a tagged pointer.
+ // R1: array element type.
+ // R2: array length as Smi.
+ // R3: array size.
+ // R7: new object end address.
+
+ // Store the type argument field.
+ __ StoreIntoObjectNoBarrier(
+ R0,
+ FieldAddress(R0, Array::type_arguments_offset()),
+ R1);
+
+ // Set the length field.
+ __ StoreIntoObjectNoBarrier(
+ R0,
+ FieldAddress(R0, Array::length_offset()),
+ R2);
+
+ // Calculate the size tag.
+ // R0: new object start as a tagged pointer.
+ // R2: array length as Smi.
+ // R3: array size.
+ // R7: new object end address.
+ const intptr_t shift = RawObject::kSizeTagBit - kObjectAlignmentLog2;
+ __ CompareImmediate(R3, RawObject::SizeTag::kMaxSizeTag, kNoPP);
+ // If no size tag overflow, shift R1 left, else set R1 to zero.
+ __ Lsl(TMP, R3, shift);
+ __ csel(R1, TMP, R1, LS);
+ __ csel(R1, ZR, R1, HI);
+
+ // Get the class index and insert it into the tags.
+ __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(kArrayCid), kNoPP);
+ __ orr(R1, R1, Operand(TMP));
+ __ StoreFieldToOffset(R1, R0, Array::tags_offset());
+
+ // Initialize all array elements to raw_null.
+ // R0: new object start as a tagged pointer.
+ // R7: new object end address.
+ // R2: array length as Smi.
+ __ AddImmediate(R1, R0, Array::data_offset() - kHeapObjectTag, kNoPP);
+ // R1: iterator which initially points to the start of the variable
+ // data area to be initialized.
+ __ LoadObject(TMP, Object::null_object(), PP);
+ Label loop, done;
+ __ Bind(&loop);
+ // TODO(cshapiro): StoreIntoObjectNoBarrier
+ __ CompareRegisters(R1, R7);
+ __ b(&done, CS);
+ __ str(TMP, Address(R1)); // Store if unsigned lower.
+ __ AddImmediate(R1, R1, kWordSize, kNoPP);
+ __ b(&loop); // Loop until R1 == R7.
+ __ Bind(&done);
+
+ // Done allocating and initializing the array.
+ // R0: new object.
+ // R2: array length as Smi (preserved for the caller.)
+ __ ret();
+ }
+
+ // Unable to allocate the array using the fast inline code, just call
+ // into the runtime.
+ __ Bind(&slow_case);
+ // Create a stub frame as we are pushing some objects on the stack before
+ // calling into the runtime.
+ __ EnterStubFrame();
+ __ LoadObject(TMP, Object::null_object(), PP);
+ // Setup space on stack for return value.
+ // Push array length as Smi and element type.
+ __ Push(TMP);
+ __ Push(R2);
+ __ Push(R1);
+ __ CallRuntime(kAllocateArrayRuntimeEntry, 2);
+ // Pop arguments; result is popped in IP.
+ __ Pop(R1);
+ __ Pop(R2);
+ __ Pop(TMP);
+ __ mov(R0, TMP);
+ __ LeaveStubFrame();
+ __ ret();
}
@@ -535,8 +670,126 @@
}
+// Called for inline allocation of contexts.
+// Input:
+// R1: number of context variables.
+// Output:
+// R0: new allocated RawContext object.
void StubCode::GenerateAllocateContextStub(Assembler* assembler) {
- __ Stop("GenerateAllocateContextStub");
+ if (FLAG_inline_alloc) {
+ const Class& context_class = Class::ZoneHandle(Object::context_class());
+ Label slow_case;
+ Heap* heap = Isolate::Current()->heap();
+ // First compute the rounded instance size.
+ // R1: number of context variables.
+ intptr_t fixed_size = sizeof(RawContext) + kObjectAlignment - 1;
+ __ LoadImmediate(R2, fixed_size, kNoPP);
+ __ add(R2, R2, Operand(R1, LSL, 3));
+ ASSERT(kSmiTagShift == 1);
+ __ andi(R2, R2, ~(kObjectAlignment - 1));
+
+ // Now allocate the object.
+ // R1: number of context variables.
+ // R2: object size.
+ __ LoadImmediate(R5, heap->TopAddress(), kNoPP);
+ __ ldr(R0, Address(R5));
+ __ add(R3, R2, Operand(R0));
+ // Check if the allocation fits into the remaining space.
+ // R0: potential new object.
+ // R1: number of context variables.
+ // R2: object size.
+ // R3: potential next object start.
+ __ LoadImmediate(TMP, heap->EndAddress(), kNoPP);
+ __ ldr(TMP, Address(TMP));
+ __ CompareRegisters(R3, TMP);
+ if (FLAG_use_slow_path) {
+ __ b(&slow_case);
+ } else {
+ __ b(&slow_case, CS); // Branch if unsigned higher or equal.
+ }
+
+ // Successfully allocated the object, now update top to point to
+ // next object start and initialize the object.
+ // R0: new object.
+ // R1: number of context variables.
+ // R2: object size.
+ // R3: next object start.
+ __ str(R3, Address(R5));
+ __ add(R0, R0, Operand(kHeapObjectTag));
+ __ UpdateAllocationStatsWithSize(context_class.id(), R2, R5, kNoPP);
+
+ // Calculate the size tag.
+ // R0: new object.
+ // R1: number of context variables.
+ // R2: object size.
+ const intptr_t shift = RawObject::kSizeTagBit - kObjectAlignmentLog2;
+ __ CompareImmediate(R2, RawObject::SizeTag::kMaxSizeTag, kNoPP);
+ // If no size tag overflow, shift R2 left, else set R2 to zero.
+ __ Lsl(TMP, R2, shift);
+ __ csel(R2, TMP, R2, LS);
+ __ csel(R2, ZR, R2, HI);
+
+ // Get the class index and insert it into the tags.
+ // R2: size and bit tags.
+ __ LoadImmediate(
+ TMP, RawObject::ClassIdTag::encode(context_class.id()), kNoPP);
+ __ orr(R2, R2, Operand(TMP));
+ __ StoreFieldToOffset(R2, R0, Context::tags_offset());
+
+ // Setup up number of context variables field.
+ // R0: new object.
+ // R1: number of context variables as integer value (not object).
+ __ StoreFieldToOffset(R1, R0, Context::num_variables_offset());
+
+ // Setup isolate field.
+ // Load Isolate pointer from Context structure into R2.
+ // R0: new object.
+ // R1: number of context variables.
+ __ LoadFieldFromOffset(R2, CTX, Context::isolate_offset());
+ // R2: isolate, not an object.
+ __ StoreFieldToOffset(R2, R0, Context::isolate_offset());
+
+ // Setup the parent field.
+ // R0: new object.
+ // R1: number of context variables.
+ __ LoadObject(R2, Object::null_object(), PP);
+ __ StoreFieldToOffset(R2, R0, Context::parent_offset());
+
+ // Initialize the context variables.
+ // R0: new object.
+ // R1: number of context variables.
+ // R2: raw null.
+ Label loop, done;
+ __ AddImmediate(
+ R3, R0, Context::variable_offset(0) - kHeapObjectTag, kNoPP);
+ __ Bind(&loop);
+ __ subs(R1, R1, Operand(1));
+ __ b(&done, MI);
+ __ str(R2, Address(R3, R1, UXTX, Address::Scaled));
+ __ b(&loop, NE); // Loop if R1 not zero.
+ __ Bind(&done);
+
+ // Done allocating and initializing the context.
+ // R0: new object.
+ __ ret();
+
+ __ Bind(&slow_case);
+ }
+ // Create a stub frame as we are pushing some objects on the stack before
+ // calling into the runtime.
+ __ EnterStubFrame();
+ // Setup space on stack for return value.
+ __ LoadObject(R2, Object::null_object(), PP);
+ __ SmiTag(R1);
+ __ Push(R2);
+ __ Push(R1);
+ __ CallRuntime(kAllocateContextRuntimeEntry, 1); // Allocate context.
+ __ Drop(1); // Pop number of context variables argument.
+ __ Pop(R0); // Pop the new context object.
+ // R0: new object
+ // Restore the frame pointer.
+ __ LeaveStubFrame();
+ __ ret();
}
@@ -978,7 +1231,9 @@
void StubCode::GenerateThreeArgsCheckInlineCacheStub(Assembler* assembler) {
- __ Stop("GenerateThreeArgsCheckInlineCacheStub");
+ GenerateUsageCounterIncrement(assembler, R6);
+ GenerateNArgsCheckInlineCacheStub(
+ assembler, 3, kInlineCacheMissHandlerThreeArgsRuntimeEntry);
}
« no previous file with comments | « runtime/vm/simulator_arm64.cc ('k') | runtime/vm/unit_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698