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

Side by Side Diff: runtime/vm/stub_code_arm.cc

Issue 14153004: Implement missing features to run Hello world! on simulated ARM. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/intrinsifier_mips.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/globals.h" 5 #include "vm/globals.h"
6 #if defined(TARGET_ARCH_ARM) 6 #if defined(TARGET_ARCH_ARM)
7 7
8 #include "vm/assembler.h" 8 #include "vm/assembler.h"
9 #include "vm/code_generator.h" 9 #include "vm/code_generator.h"
10 #include "vm/compiler.h"
10 #include "vm/dart_entry.h" 11 #include "vm/dart_entry.h"
11 #include "vm/flow_graph_compiler.h" 12 #include "vm/flow_graph_compiler.h"
12 #include "vm/instructions.h" 13 #include "vm/instructions.h"
14 #include "vm/object_store.h"
13 #include "vm/stack_frame.h" 15 #include "vm/stack_frame.h"
14 #include "vm/stub_code.h" 16 #include "vm/stub_code.h"
15 17
16 #define __ assembler-> 18 #define __ assembler->
17 19
18 namespace dart { 20 namespace dart {
19 21
20 DEFINE_FLAG(bool, inline_alloc, true, "Inline allocation of objects."); 22 DEFINE_FLAG(bool, inline_alloc, true, "Inline allocation of objects.");
21 DEFINE_FLAG(bool, use_slow_path, false, 23 DEFINE_FLAG(bool, use_slow_path, false,
22 "Set to true for debugging & verifying the slow paths."); 24 "Set to true for debugging & verifying the slow paths.");
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
210 __ AddImmediate(R0, R0, Instructions::HeaderSize() - kHeapObjectTag); 212 __ AddImmediate(R0, R0, Instructions::HeaderSize() - kHeapObjectTag);
211 __ bx(R0); 213 __ bx(R0);
212 } 214 }
213 215
214 216
215 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { 217 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) {
216 __ Unimplemented("FixCallersTarget stub"); 218 __ Unimplemented("FixCallersTarget stub");
217 } 219 }
218 220
219 221
222 // Input parameters:
223 // R2: Smi-tagged argument count, may be zero.
224 // FP[kLastParamSlotIndex]: Last argument.
225 static void PushArgumentsArray(Assembler* assembler) {
226 // Allocate array to store arguments of caller.
227 __ LoadImmediate(R1, reinterpret_cast<intptr_t>(Object::null()));
228 // R1: Null element type for raw Array.
229 // R2: Smi-tagged argument count, may be zero.
230 __ BranchLink(&StubCode::AllocateArrayLabel());
231 // R0: newly allocated array.
232 // R2: Smi-tagged argument count, may be zero (was preserved by the stub).
233 __ Push(R0); // Array is in R0 and on top of stack.
234 __ add(R1, FP, ShifterOperand(R2, LSL, 1));
235 __ AddImmediate(R1, (kLastParamSlotIndex - 1) * kWordSize);
236 __ AddImmediate(R3, R0, Array::data_offset() - kHeapObjectTag);
237 Label loop, loop_condition;
238 __ b(&loop_condition);
239 __ Bind(&loop);
240 __ ldr(IP, Address(R1, 0));
241 __ str(IP, Address(R3, 0));
242 __ AddImmediate(R1, -kWordSize);
243 __ AddImmediate(R3, kWordSize);
244 __ Bind(&loop_condition);
245 __ subs(R2, R2, ShifterOperand(Smi::RawValue(1))); // R2 is Smi.
246 __ b(&loop, PL);
247 }
248
249
220 void StubCode::GenerateInstanceFunctionLookupStub(Assembler* assembler) { 250 void StubCode::GenerateInstanceFunctionLookupStub(Assembler* assembler) {
221 __ Unimplemented("InstanceFunctionLookup stub"); 251 __ Unimplemented("InstanceFunctionLookup stub");
222 } 252 }
223 253
224 254
225 void StubCode::GenerateDeoptimizeLazyStub(Assembler* assembler) { 255 void StubCode::GenerateDeoptimizeLazyStub(Assembler* assembler) {
226 __ Unimplemented("DeoptimizeLazy stub"); 256 __ Unimplemented("DeoptimizeLazy stub");
227 } 257 }
228 258
229 259
230 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { 260 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) {
231 __ Unimplemented("Deoptimize stub"); 261 __ Unimplemented("Deoptimize stub");
232 } 262 }
233 263
234 264
235 void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) { 265 void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) {
236 __ Unimplemented("MegamorphicMiss stub"); 266 __ Unimplemented("MegamorphicMiss stub");
237 } 267 }
238 268
239 269
270 // Called for inline allocation of arrays.
271 // Input parameters:
272 // LR: return address.
273 // R2: Array length as Smi.
274 // R1: array element type (either NULL or an instantiated type).
275 // NOTE: R2 cannot be clobbered here as the caller relies on it being saved.
276 // The newly allocated object is returned in R0.
240 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { 277 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) {
241 __ Unimplemented("AllocateArray stub"); 278 Label slow_case;
279 if (FLAG_inline_alloc) {
280 // Compute the size to be allocated, it is based on the array length
281 // and is computed as:
282 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)).
283 // Assert that length is a Smi.
284 __ tst(R2, ShifterOperand(kSmiTagSize));
285 if (FLAG_use_slow_path) {
286 __ b(&slow_case);
287 } else {
288 __ b(&slow_case, NE);
289 }
290 __ ldr(R8, FieldAddress(CTX, Context::isolate_offset()));
291 __ LoadFromOffset(kLoadWord, R8, R8, Isolate::heap_offset());
292 __ LoadFromOffset(kLoadWord, R8, R8, Heap::new_space_offset());
293
294 // Calculate and align allocation size.
295 // Load new object start and calculate next object start.
296 // R1: array element type.
297 // R2: Array length as Smi.
298 // R8: Points to new space object.
299 __ LoadFromOffset(kLoadWord, R0, R8, Scavenger::top_offset());
300 intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1;
301 __ LoadImmediate(R7, fixed_size);
302 __ add(R7, R7, ShifterOperand(R2, LSL, 1)); // R2 is Smi.
303 ASSERT(kSmiTagShift == 1);
304 __ bic(R7, R7, ShifterOperand(kObjectAlignment - 1));
305 __ add(R7, R7, ShifterOperand(R0));
306
307 // Check if the allocation fits into the remaining space.
308 // R0: potential new object start.
309 // R1: array element type.
310 // R2: Array length as Smi.
311 // R7: potential next object start.
312 // R8: Points to new space object.
313 __ LoadFromOffset(kLoadWord, IP, R8, Scavenger::end_offset());
314 __ cmp(R7, ShifterOperand(IP));
315 __ b(&slow_case, CS); // Branch if unsigned higher or equal.
316
317 // Successfully allocated the object(s), now update top to point to
318 // next object start and initialize the object.
319 // R0: potential new object start.
320 // R7: potential next object start.
321 // R8: Points to new space object.
322 __ StoreToOffset(kStoreWord, R7, R8, Scavenger::top_offset());
323 __ add(R0, R0, ShifterOperand(kHeapObjectTag));
324
325 // R0: new object start as a tagged pointer.
326 // R1: array element type.
327 // R2: Array length as Smi.
328 // R7: new object end address.
329
330 // Store the type argument field.
331 __ StoreIntoObjectNoBarrier(
332 R0,
333 FieldAddress(R0, Array::type_arguments_offset()),
334 R1);
335
336 // Set the length field.
337 __ StoreIntoObjectNoBarrier(
338 R0,
339 FieldAddress(R0, Array::length_offset()),
340 R2);
341
342 // Calculate the size tag.
343 // R0: new object start as a tagged pointer.
344 // R2: Array length as Smi.
345 // R7: new object end address.
346 __ LoadImmediate(R1, fixed_size);
347 __ add(R1, R1, ShifterOperand(R2, LSL, 1)); // R2 is Smi.
348 ASSERT(kSmiTagShift == 1);
349 __ bic(R1, R1, ShifterOperand(kObjectAlignment - 1));
350 const intptr_t shift = RawObject::kSizeTagBit - kObjectAlignmentLog2;
351 __ CompareImmediate(R1, RawObject::SizeTag::kMaxSizeTag);
352 // If no size tag overflow, shift R1 left, else set R1 to zero.
353 __ mov(R1, ShifterOperand(R1, LSL, shift), LS);
354 __ mov(R1, ShifterOperand(0), HI);
355
356 // Get the class index and insert it into the tags.
357 __ LoadImmediate(IP, RawObject::ClassIdTag::encode(kArrayCid));
358 __ orr(R1, R1, ShifterOperand(IP));
359 __ str(R1, FieldAddress(R0, Array::tags_offset()));
360
361 // Initialize all array elements to raw_null.
362 // R0: new object start as a tagged pointer.
363 // R7: new object end address.
364 // R2: Array length as Smi.
365 __ AddImmediate(R1, R0, Array::data_offset() - kHeapObjectTag);
366 // R1: iterator which initially points to the start of the variable
367 // data area to be initialized.
368 __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null()));
369 Label loop, test;
370 __ b(&test);
371 __ Bind(&loop);
372 // TODO(cshapiro): StoreIntoObjectNoBarrier
373 __ str(IP, Address(R1, 0));
374 __ AddImmediate(R1, kWordSize);
375 __ Bind(&test);
376 __ cmp(R1, ShifterOperand(R7));
377 __ b(&loop, NE);
378
379 // Done allocating and initializing the array.
380 // R0: new object.
381 // R2: Array length as Smi (preserved for the caller.)
382 __ Ret();
383 }
384
385 // Unable to allocate the array using the fast inline code, just call
386 // into the runtime.
387 __ Bind(&slow_case);
388 // Create a stub frame as we are pushing some objects on the stack before
389 // calling into the runtime.
390 __ EnterStubFrame();
391 __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null()));
392 // Setup space on stack for return value.
393 // Push array length as Smi and element type.
394 __ PushList((1 << R1) | (1 << R2) | (1 << IP));
395 __ CallRuntime(kAllocateArrayRuntimeEntry);
396 // Pop arguments; result is popped in IP.
397 __ PopList((1 << R1) | (1 << R2) | (1 << IP)); // R2 is restored.
398 __ mov(R0, ShifterOperand(IP));
399 __ LeaveStubFrame();
400 __ Ret();
242 } 401 }
243 402
244 403
404 // Input parameters:
405 // LR: return address.
406 // SP: address of last argument.
407 // R4: Arguments descriptor array.
408 // Note: The closure object is the first argument to the function being
409 // called, the stub accesses the closure from this location directly
410 // when trying to resolve the call.
245 void StubCode::GenerateCallClosureFunctionStub(Assembler* assembler) { 411 void StubCode::GenerateCallClosureFunctionStub(Assembler* assembler) {
246 __ Unimplemented("CallClosureFunction stub"); 412 // Load num_args.
413 __ ldr(R0, FieldAddress(R4, ArgumentsDescriptor::count_offset()));
414 __ sub(R0, R0, ShifterOperand(Smi::RawValue(1)));
415 // Load closure object in R1.
416 __ ldr(R1, Address(SP, R0, LSL, 1)); // R0 (num_args - 1) is a Smi.
417
418 // Verify that R1 is a closure by checking its class.
419 Label not_closure;
420 __ LoadImmediate(R8, reinterpret_cast<intptr_t>(Object::null()));
421 __ cmp(R1, ShifterOperand(R8));
422 // Not a closure, but null object.
423 __ b(&not_closure, EQ);
424 __ tst(R1, ShifterOperand(kSmiTagMask));
425 __ b(&not_closure, EQ); // Not a closure, but a smi.
426 // Verify that the class of the object is a closure class by checking that
427 // class.signature_function() is not null.
428 __ LoadClass(R0, R1, R2);
429 __ ldr(R0, FieldAddress(R0, Class::signature_function_offset()));
430 __ cmp(R0, ShifterOperand(R8)); // R8 is raw null.
431 // Actual class is not a closure class.
432 __ b(&not_closure, EQ);
433
434 // R0 is just the signature function. Load the actual closure function.
435 __ ldr(R2, FieldAddress(R1, Closure::function_offset()));
436
437 // Load closure context in CTX; note that CTX has already been preserved.
438 __ ldr(CTX, FieldAddress(R1, Closure::context_offset()));
439
440 // Load closure function code in R0.
441 __ ldr(R0, FieldAddress(R2, Function::code_offset()));
442 __ cmp(R0, ShifterOperand(R8)); // R8 is raw null.
443 Label function_compiled;
444 __ b(&function_compiled, NE);
445
446 // Create a stub frame as we are pushing some objects on the stack before
447 // calling into the runtime.
448 __ EnterStubFrame();
449
450 // Preserve arguments descriptor array and read-only function object argument.
451 __ PushList((1 << R2) | (1 << R4));
452 __ CallRuntime(kCompileFunctionRuntimeEntry);
453 // Restore arguments descriptor array and read-only function object argument.
454 __ PopList((1 << R2) | (1 << R4));
455 // Restore R0.
456 __ ldr(R0, FieldAddress(R2, Function::code_offset()));
457
458 // Remove the stub frame as we are about to jump to the closure function.
459 __ LeaveStubFrame();
460
461 __ Bind(&function_compiled);
462 // R0: Code.
463 // R4: Arguments descriptor array.
464 __ ldr(R0, FieldAddress(R0, Code::instructions_offset()));
465 __ AddImmediate(R0, Instructions::HeaderSize() - kHeapObjectTag);
466 __ bx(R0);
467
468 __ Bind(&not_closure);
469 // Call runtime to attempt to resolve and invoke a call method on a
470 // non-closure object, passing the non-closure object and its arguments array,
471 // returning here.
472 // If no call method exists, throw a NoSuchMethodError.
473 // R1: non-closure object.
474 // R4: arguments descriptor array.
475
476 // Create a stub frame as we are pushing some objects on the stack before
477 // calling into the runtime.
478 __ EnterStubFrame();
479
480 // Setup space on stack for result from error reporting.
481 __ PushList((1 << R4) | (1 << R8)); // Arguments descriptor and raw null.
482
483 // Load smi-tagged arguments array length, including the non-closure.
484 __ ldr(R2, FieldAddress(R4, ArgumentsDescriptor::count_offset()));
485 PushArgumentsArray(assembler);
486
487 // Stack:
488 // TOS + 0: Argument array.
489 // TOS + 1: Arguments descriptor array.
490 // TOS + 2: Place for result from the call.
491 // TOS + 3: Saved FP of previous frame.
492 // TOS + 4: Dart code return address
493 // TOS + 5: PC marker (0 for stub).
494 // TOS + 6: Last argument of caller.
495 // ....
496 __ CallRuntime(kInvokeNonClosureRuntimeEntry);
497 // Remove arguments.
498 __ Drop(2);
499 __ Pop(R0); // Get result into R0.
500
501 // Remove the stub frame as we are about to return.
502 __ LeaveStubFrame();
503 __ Ret();
247 } 504 }
248 505
249 506
250 // Called when invoking Dart code from C++ (VM code). 507 // Called when invoking Dart code from C++ (VM code).
251 // Input parameters: 508 // Input parameters:
252 // LR : points to return address. 509 // LR : points to return address.
253 // R0 : entrypoint of the Dart function to call. 510 // R0 : entrypoint of the Dart function to call.
254 // R1 : arguments descriptor array. 511 // R1 : arguments descriptor array.
255 // R2 : arguments array. 512 // R2 : arguments array.
256 // R3 : new context containing the current isolate pointer. 513 // R3 : new context containing the current isolate pointer.
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
435 // A new InstantiatedTypeArguments object only needs to be allocated if 692 // A new InstantiatedTypeArguments object only needs to be allocated if
436 // the instantiator is provided (not kNoInstantiator, but may be null). 693 // the instantiator is provided (not kNoInstantiator, but may be null).
437 __ CompareImmediate(R0, Smi::RawValue(StubCode::kNoInstantiator)); 694 __ CompareImmediate(R0, Smi::RawValue(StubCode::kNoInstantiator));
438 __ AddImmediate(R3, type_args_size, NE); 695 __ AddImmediate(R3, type_args_size, NE);
439 // R4: potential new object end and, if R4 != R3, potential new 696 // R4: potential new object end and, if R4 != R3, potential new
440 // InstantiatedTypeArguments object start. 697 // InstantiatedTypeArguments object start.
441 } 698 }
442 // Check if the allocation fits into the remaining space. 699 // Check if the allocation fits into the remaining space.
443 // R2: potential new object start. 700 // R2: potential new object start.
444 // R3: potential next object start. 701 // R3: potential next object start.
702 __ LoadImmediate(IP, heap->EndAddress());
703 __ cmp(R3, ShifterOperand(IP));
445 if (FLAG_use_slow_path) { 704 if (FLAG_use_slow_path) {
446 __ b(&slow_case); 705 __ b(&slow_case);
447 } else { 706 } else {
448 __ LoadImmediate(IP, heap->EndAddress());
449 __ cmp(R3, ShifterOperand(IP));
450 __ b(&slow_case, CS); // Branch if unsigned higher or equal. 707 __ b(&slow_case, CS); // Branch if unsigned higher or equal.
451 } 708 }
452 709
453 // Successfully allocated the object(s), now update top to point to 710 // Successfully allocated the object(s), now update top to point to
454 // next object start and initialize the object. 711 // next object start and initialize the object.
455 __ str(R3, Address(R5, 0)); 712 __ str(R3, Address(R5, 0));
456 713
457 if (is_cls_parameterized) { 714 if (is_cls_parameterized) {
458 // Initialize the type arguments field in the object. 715 // Initialize the type arguments field in the object.
459 // R2: new object start. 716 // R2: new object start.
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
532 __ Bind(&done); 789 __ Bind(&done);
533 } 790 }
534 if (is_cls_parameterized) { 791 if (is_cls_parameterized) {
535 // R1: new object type arguments. 792 // R1: new object type arguments.
536 // Set the type arguments in the new object. 793 // Set the type arguments in the new object.
537 __ StoreToOffset(kStoreWord, R1, R2, cls.type_arguments_field_offset()); 794 __ StoreToOffset(kStoreWord, R1, R2, cls.type_arguments_field_offset());
538 } 795 }
539 // Done allocating and initializing the instance. 796 // Done allocating and initializing the instance.
540 // R2: new object still missing its heap tag. 797 // R2: new object still missing its heap tag.
541 __ add(R0, R2, ShifterOperand(kHeapObjectTag)); 798 __ add(R0, R2, ShifterOperand(kHeapObjectTag));
799 // R0: new object.
542 __ Ret(); 800 __ Ret();
543 801
544 __ Bind(&slow_case); 802 __ Bind(&slow_case);
545 } 803 }
546 if (is_cls_parameterized) { 804 if (is_cls_parameterized) {
547 __ ldm(IA, SP, (1 << R0) | (1 << R1)); 805 __ ldm(IA, SP, (1 << R0) | (1 << R1));
548 } 806 }
549 // Create a stub frame as we are pushing some objects on the stack before 807 // Create a stub frame as we are pushing some objects on the stack before
550 // calling into the runtime. 808 // calling into the runtime.
551 __ EnterStubFrame(true); // Uses pool pointer to pass cls to runtime. 809 __ EnterStubFrame(true); // Uses pool pointer to pass cls to runtime.
(...skipping 11 matching lines...) Expand all
563 __ CallRuntime(kAllocateObjectRuntimeEntry); // Allocate object. 821 __ CallRuntime(kAllocateObjectRuntimeEntry); // Allocate object.
564 __ Drop(3); // Pop arguments. 822 __ Drop(3); // Pop arguments.
565 __ Pop(R0); // Pop result (newly allocated object). 823 __ Pop(R0); // Pop result (newly allocated object).
566 // R0: new object 824 // R0: new object
567 // Restore the frame pointer. 825 // Restore the frame pointer.
568 __ LeaveStubFrame(true); 826 __ LeaveStubFrame(true);
569 __ Ret(); 827 __ Ret();
570 } 828 }
571 829
572 830
831 // Called for inline allocation of closures.
832 // Input parameters:
833 // LR : return address.
834 // SP + 4 : receiver (null if not an implicit instance closure).
835 // SP + 0 : type arguments object (null if class is no parameterized).
573 void StubCode::GenerateAllocationStubForClosure(Assembler* assembler, 836 void StubCode::GenerateAllocationStubForClosure(Assembler* assembler,
574 const Function& func) { 837 const Function& func) {
575 __ Unimplemented("AllocateClosure stub"); 838 ASSERT(func.IsClosureFunction());
839 const bool is_implicit_static_closure =
840 func.IsImplicitStaticClosureFunction();
841 const bool is_implicit_instance_closure =
842 func.IsImplicitInstanceClosureFunction();
843 const Class& cls = Class::ZoneHandle(func.signature_class());
844 const bool has_type_arguments = cls.HasTypeArguments();
845
846 __ EnterStubFrame(true); // Uses pool pointer to refer to function.
847 const intptr_t kTypeArgumentsFPOffset = 3 * kWordSize;
848 const intptr_t kReceiverFPOffset = 4 * kWordSize;
849 const intptr_t closure_size = Closure::InstanceSize();
850 const intptr_t context_size = Context::InstanceSize(1); // Captured receiver.
851 if (FLAG_inline_alloc &&
852 PageSpace::IsPageAllocatableSize(closure_size + context_size)) {
853 Label slow_case;
854 Heap* heap = Isolate::Current()->heap();
855 __ LoadImmediate(R5, heap->TopAddress());
856 __ ldr(R2, Address(R5, 0));
857 __ AddImmediate(R3, R2, closure_size);
858 if (is_implicit_instance_closure) {
859 __ mov(R4, ShifterOperand(R3)); // R4: new context address.
860 __ AddImmediate(R3, context_size);
861 }
862 // Check if the allocation fits into the remaining space.
863 // R2: potential new closure object.
864 // R3: potential next object start.
865 // R4: potential new context object (only if is_implicit_closure).
866 __ LoadImmediate(IP, heap->EndAddress());
867 __ cmp(R3, ShifterOperand(IP));
868 if (FLAG_use_slow_path) {
869 __ b(&slow_case);
870 } else {
871 __ b(&slow_case, CS); // Branch if unsigned higher or equal.
872 }
873
874 // Successfully allocated the object, now update top to point to
875 // next object start and initialize the object.
876 __ str(R3, Address(R5, 0));
877
878 // R2: new closure object.
879 // R4: new context object (only if is_implicit_closure).
880 // Set the tags.
881 uword tags = 0;
882 tags = RawObject::SizeTag::update(closure_size, tags);
883 tags = RawObject::ClassIdTag::update(cls.id(), tags);
884 __ LoadImmediate(R0, tags);
885 __ str(R0, Address(R2, Instance::tags_offset()));
886
887 // Initialize the function field in the object.
888 // R2: new closure object.
889 // R4: new context object (only if is_implicit_closure).
890 __ LoadObject(R0, func); // Load function of closure to be allocated.
891 __ str(R0, Address(R2, Closure::function_offset()));
892
893 // Setup the context for this closure.
894 if (is_implicit_static_closure) {
895 ObjectStore* object_store = Isolate::Current()->object_store();
896 ASSERT(object_store != NULL);
897 const Context& empty_context =
898 Context::ZoneHandle(object_store->empty_context());
899 __ LoadObject(R0, empty_context);
900 __ str(R0, Address(R2, Closure::context_offset()));
901 } else if (is_implicit_instance_closure) {
902 // Initialize the new context capturing the receiver.
903 const Class& context_class = Class::ZoneHandle(Object::context_class());
904 // Set the tags.
905 uword tags = 0;
906 tags = RawObject::SizeTag::update(context_size, tags);
907 tags = RawObject::ClassIdTag::update(context_class.id(), tags);
908 __ LoadImmediate(R0, tags);
909 __ str(R0, Address(R4, Context::tags_offset()));
910
911 // Set number of variables field to 1 (for captured receiver).
912 __ LoadImmediate(R0, 1);
913 __ str(R0, Address(R4, Context::num_variables_offset()));
914
915 // Set isolate field to isolate of current context.
916 __ ldr(R0, FieldAddress(CTX, Context::isolate_offset()));
917 __ str(R0, Address(R4, Context::isolate_offset()));
918
919 // Set the parent to null.
920 __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null()));
921 __ str(R0, Address(R4, Context::parent_offset()));
922
923 // Initialize the context variable to the receiver.
924 __ ldr(R0, Address(FP, kReceiverFPOffset));
925 __ str(R0, Address(R4, Context::variable_offset(0)));
926
927 // Set the newly allocated context in the newly allocated closure.
928 __ add(R1, R4, ShifterOperand(kHeapObjectTag));
929 __ str(R1, Address(R2, Closure::context_offset()));
930 } else {
931 __ str(CTX, Address(R2, Closure::context_offset()));
932 }
933
934 // Set the type arguments field in the newly allocated closure.
935 __ ldr(R0, Address(FP, kTypeArgumentsFPOffset));
936 __ str(R0, Address(R2, Closure::type_arguments_offset()));
937
938 // Done allocating and initializing the instance.
939 // R2: new object still missing its heap tag.
940 __ add(R0, R2, ShifterOperand(kHeapObjectTag));
941 // R0: new object.
942 __ LeaveStubFrame(true);
943 __ Ret();
944
945 __ Bind(&slow_case);
946 }
947 __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null()));
948 __ Push(R0); // Setup space on stack for return value.
949 __ PushObject(func);
950 if (is_implicit_static_closure) {
951 __ CallRuntime(kAllocateImplicitStaticClosureRuntimeEntry);
952 } else {
953 if (is_implicit_instance_closure) {
954 __ ldr(R1, Address(FP, kReceiverFPOffset));
955 __ Push(R1); // Receiver.
956 }
957 // R0: raw null.
958 if (has_type_arguments) {
959 __ ldr(R0, Address(FP, kTypeArgumentsFPOffset));
960 }
961 __ Push(R0); // Push type arguments of closure to be allocated or null.
962
963 if (is_implicit_instance_closure) {
964 __ CallRuntime(kAllocateImplicitInstanceClosureRuntimeEntry);
965 __ Drop(2); // Pop arguments (type arguments of object and receiver).
966 } else {
967 ASSERT(func.IsNonImplicitClosureFunction());
968 __ CallRuntime(kAllocateClosureRuntimeEntry);
969 __ Drop(1); // Pop argument (type arguments of object).
970 }
971 }
972 __ Drop(1); // Pop function object.
973 __ Pop(R0);
974 // R0: new object
975 // Restore the frame pointer.
976 __ LeaveStubFrame(true);
977 __ Ret();
576 } 978 }
577 979
578 980
579 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) { 981 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) {
580 __ Unimplemented("CallNoSuchMethodFunction stub"); 982 __ Unimplemented("CallNoSuchMethodFunction stub");
581 } 983 }
582 984
583 985
584 void StubCode::GenerateOptimizedUsageCounterIncrement(Assembler* assembler) { 986 void StubCode::GenerateOptimizedUsageCounterIncrement(Assembler* assembler) {
585 __ Unimplemented("OptimizedUsageCounterIncrement stub"); 987 __ Unimplemented("OptimizedUsageCounterIncrement stub");
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
690 __ ldr(R1, Address(R6, 0)); // Next class ID. 1092 __ ldr(R1, Address(R6, 0)); // Next class ID.
691 1093
692 __ Bind(&test); 1094 __ Bind(&test);
693 __ CompareImmediate(R1, Smi::RawValue(kIllegalCid)); // Done? 1095 __ CompareImmediate(R1, Smi::RawValue(kIllegalCid)); // Done?
694 __ b(&loop, NE); 1096 __ b(&loop, NE);
695 1097
696 // IC miss. 1098 // IC miss.
697 // Restore return address. 1099 // Restore return address.
698 __ mov(LR, ShifterOperand(R8)); 1100 __ mov(LR, ShifterOperand(R8));
699 1101
700 // Compute address of arguments (first read number of arguments from 1102 // Compute address of arguments.
701 // arguments descriptor array and then compute address on the stack).
702 // R7: argument_count - 1 (smi). 1103 // R7: argument_count - 1 (smi).
703 __ add(R7, SP, ShifterOperand(R7, LSL, 1)); // R7 is Smi. 1104 __ add(R7, SP, ShifterOperand(R7, LSL, 1)); // R7 is Smi.
704 // R7: address of receiver. 1105 // R7: address of receiver.
705 // Create a stub frame as we are pushing some objects on the stack before 1106 // Create a stub frame as we are pushing some objects on the stack before
706 // calling into the runtime. 1107 // calling into the runtime.
707 __ EnterStubFrame(); 1108 __ EnterStubFrame();
708 __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null())); 1109 __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null()));
709 // Preserve IC data object and arguments descriptor array and 1110 // Preserve IC data object and arguments descriptor array and
710 // setup space on stack for result (target code object). 1111 // setup space on stack for result (target code object).
711 __ PushList((1 << R0) | (1 << R4) | (1 << R5)); 1112 __ PushList((1 << R0) | (1 << R4) | (1 << R5));
(...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after
1083 __ Bind(&reference_compare); 1484 __ Bind(&reference_compare);
1084 __ cmp(left, ShifterOperand(right)); 1485 __ cmp(left, ShifterOperand(right));
1085 __ Bind(&done); 1486 __ Bind(&done);
1086 __ PopList((1 << R0) | (1 << R1) | (1 << R2)); 1487 __ PopList((1 << R0) | (1 << R1) | (1 << R2));
1087 __ Ret(); 1488 __ Ret();
1088 } 1489 }
1089 1490
1090 } // namespace dart 1491 } // namespace dart
1091 1492
1092 #endif // defined TARGET_ARCH_ARM 1493 #endif // defined TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « runtime/vm/intrinsifier_mips.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698