Chromium Code Reviews| Index: runtime/vm/stub_code_arm.cc |
| =================================================================== |
| --- runtime/vm/stub_code_arm.cc (revision 21596) |
| +++ runtime/vm/stub_code_arm.cc (working copy) |
| @@ -281,7 +281,7 @@ |
| // and is computed as: |
| // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)). |
| // Assert that length is a Smi. |
| - __ tst(R2, ShifterOperand(kSmiTagSize)); |
| + __ tst(R2, ShifterOperand(kSmiTagMask)); |
| if (FLAG_use_slow_path) { |
| __ b(&slow_case); |
| } else { |
| @@ -608,8 +608,119 @@ |
| } |
| +// Called for inline allocation of contexts. |
| +// Input: |
| +// R1: number of context variables. |
| +// Output: |
| +// R0: new allocated RawContext object. |
| void StubCode::GenerateAllocateContextStub(Assembler* assembler) { |
| - __ Unimplemented("AllocateContext stub"); |
| + 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); |
| + __ add(R2, R2, ShifterOperand(R1, LSL, 2)); |
| + ASSERT(kSmiTagShift == 1); |
| + __ bic(R2, R2, ShifterOperand(kObjectAlignment - 1)); |
| + |
| + // Now allocate the object. |
| + // R1: number of context variables. |
| + // R2: object size. |
| + __ LoadImmediate(R5, heap->TopAddress()); |
| + __ ldr(R0, Address(R5, 0)); |
| + __ add(R3, R2, ShifterOperand(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(IP, heap->EndAddress()); |
| + __ ldr(IP, Address(IP, 0)); |
| + __ cmp(R3, ShifterOperand(IP)); |
| + 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, 0)); |
| + __ add(R0, R0, ShifterOperand(kHeapObjectTag)); |
| + |
| + // 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); |
| + // If no size tag overflow, shift R2 left, else set R2 to zero. |
| + __ mov(R2, ShifterOperand(R2, LSL, shift), LS); |
| + __ mov(R2, ShifterOperand(0), HI); |
| + |
| + // Get the class index and insert it into the tags. |
| + // R2: size and bit tags. |
| + __ LoadImmediate(IP, RawObject::ClassIdTag::encode(context_class.id())); |
| + __ orr(R2, R2, ShifterOperand(IP)); |
| + __ str(R2, FieldAddress(R0, Context::tags_offset())); |
| + |
| + // Setup up number of context variables field. |
| + // R0: new object. |
| + // R1: number of context variables as integer value (not object). |
| + __ str(R1, FieldAddress(R0, Context::num_variables_offset())); |
| + |
| + // Setup isolate field. |
| + // Load Isolate pointer from Context structure into R2. |
| + // R0: new object. |
| + // R1: number of context variables. |
| + __ ldr(R2, FieldAddress(CTX, Context::isolate_offset())); |
| + // R2: Isolate, not an object. |
| + __ str(R2, FieldAddress(R0, Context::isolate_offset())); |
| + |
| + // Setup the parent field. |
| + // R0: new object. |
| + // R1: number of context variables. |
| + __ LoadImmediate(R2, reinterpret_cast<intptr_t>(Object::null())); |
| + __ str(R2, FieldAddress(R0, Context::parent_offset())); |
| + |
| + // Initialize the context variables. |
| + // R0: new object. |
| + // R1: number of context variables. |
| + // R2: raw null. |
| + Label loop; |
| + __ AddImmediate(R3, R0, Context::variable_offset(0) - kHeapObjectTag); |
| + __ Bind(&loop); |
| + __ subs(R1, R1, ShifterOperand(1)); |
| + __ str(R2, Address(R3, R1, LSL, 2), PL); // Store if R1 positive or zero. |
| + __ b(&loop, NE); // Loop if R1 not zero. |
| + |
| + // 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. |
| + __ LoadImmediate(R2, reinterpret_cast<intptr_t>(Object::null())); |
| + __ SmiTag(R1); |
| + __ PushList((1 << R1) | (1 << R2)); |
| + __ CallRuntime(kAllocateContextRuntimeEntry); // 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(); |
| } |
| @@ -700,6 +811,7 @@ |
| // R2: potential new object start. |
| // R3: potential next object start. |
| __ LoadImmediate(IP, heap->EndAddress()); |
| + __ ldr(IP, Address(IP, 0)); |
|
zra
2013/04/17 15:01:27
Same mistake on MIPS side. I'll fix in my next CL.
|
| __ cmp(R3, ShifterOperand(IP)); |
| if (FLAG_use_slow_path) { |
| __ b(&slow_case); |
| @@ -864,6 +976,7 @@ |
| // R3: potential next object start. |
| // R4: potential new context object (only if is_implicit_closure). |
| __ LoadImmediate(IP, heap->EndAddress()); |
| + __ ldr(IP, Address(IP, 0)); |
|
zra
2013/04/17 15:01:27
here, too.
|
| __ cmp(R3, ShifterOperand(IP)); |
| if (FLAG_use_slow_path) { |
| __ b(&slow_case); |