Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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)); | |
|
zra
2013/04/16 23:17:42
Just noticed this. Should this be kSmiTagMask? bot
regis
2013/04/16 23:22:04
You are right. It is a typo on all architectures,
| |
| 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 { | |
| 347 Label size_tag_overflow, done; | |
|
zra
2013/04/16 21:12:29
These labels aren't used.
regis
2013/04/16 21:43:39
Removed. And removed local scope.
| |
| 348 __ LoadImmediate(R1, fixed_size); | |
| 349 __ add(R1, R1, ShifterOperand(R2, LSL, 1)); // R2 is Smi. | |
| 350 ASSERT(kSmiTagShift == 1); | |
| 351 __ bic(R1, R1, ShifterOperand(kObjectAlignment - 1)); | |
| 352 const intptr_t shift = RawObject::kSizeTagBit - kObjectAlignmentLog2; | |
| 353 __ CompareImmediate(R1, RawObject::SizeTag::kMaxSizeTag); | |
| 354 // If no size tag overflow, shift R1 left, else set R1 to zero. | |
| 355 __ mov(R1, ShifterOperand(R1, LSL, shift), LS); | |
| 356 __ mov(R1, ShifterOperand(0), HI); | |
| 357 | |
| 358 // Get the class index and insert it into the tags. | |
| 359 __ LoadImmediate(IP, RawObject::ClassIdTag::encode(kArrayCid)); | |
| 360 __ orr(R1, R1, ShifterOperand(IP)); | |
| 361 __ str(R1, FieldAddress(R0, Array::tags_offset())); | |
| 362 } | |
| 363 | |
| 364 // Initialize all array elements to raw_null. | |
| 365 // R0: new object start as a tagged pointer. | |
| 366 // R7: new object end address. | |
| 367 // R2: Array length as Smi. | |
| 368 __ AddImmediate(R1, R0, Array::data_offset() - kHeapObjectTag); | |
| 369 // R1: iterator which initially points to the start of the variable | |
| 370 // data area to be initialized. | |
| 371 __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null())); | |
| 372 Label loop, test; | |
| 373 __ b(&test); | |
| 374 __ Bind(&loop); | |
| 375 // TODO(cshapiro): StoreIntoObjectNoBarrier | |
| 376 __ str(IP, Address(R1, 0)); | |
| 377 __ AddImmediate(R1, kWordSize); | |
| 378 __ Bind(&test); | |
| 379 __ cmp(R1, ShifterOperand(R7)); | |
| 380 __ b(&loop, NE); | |
| 381 | |
| 382 // Done allocating and initializing the array. | |
| 383 // R0: new object. | |
| 384 // R2: Array length as Smi (preserved for the caller.) | |
| 385 __ Ret(); | |
| 386 } | |
| 387 | |
| 388 // Unable to allocate the array using the fast inline code, just call | |
| 389 // into the runtime. | |
| 390 __ Bind(&slow_case); | |
| 391 // Create a stub frame as we are pushing some objects on the stack before | |
| 392 // calling into the runtime. | |
| 393 __ EnterStubFrame(); | |
| 394 __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null())); | |
| 395 // Setup space on stack for return value. | |
| 396 // Push array length as Smi and element type. | |
| 397 __ PushList((1 << R1) | (1 << R2) | (1 << IP)); | |
| 398 __ CallRuntime(kAllocateArrayRuntimeEntry); | |
| 399 // Pop arguments; result is popped in IP. | |
| 400 __ PopList((1 << R1) | (1 << R2) | (1 << IP)); // R2 is restored. | |
| 401 __ mov(R0, ShifterOperand(IP)); | |
| 402 __ LeaveStubFrame(); | |
| 403 __ Ret(); | |
| 242 } | 404 } |
| 243 | 405 |
| 244 | 406 |
| 407 // Input parameters: | |
| 408 // LR: return address. | |
| 409 // SP: address of last argument. | |
| 410 // R4: Arguments descriptor array. | |
| 411 // Note: The closure object is the first argument to the function being | |
| 412 // called, the stub accesses the closure from this location directly | |
| 413 // when trying to resolve the call. | |
| 245 void StubCode::GenerateCallClosureFunctionStub(Assembler* assembler) { | 414 void StubCode::GenerateCallClosureFunctionStub(Assembler* assembler) { |
| 246 __ Unimplemented("CallClosureFunction stub"); | 415 // Load num_args. |
| 416 __ ldr(R0, FieldAddress(R4, ArgumentsDescriptor::count_offset())); | |
| 417 __ sub(R0, R0, ShifterOperand(Smi::RawValue(1))); | |
| 418 // Load closure object in R1. | |
| 419 __ ldr(R1, Address(SP, R0, LSL, 1)); // R0 (num_args - 1) is a Smi. | |
| 420 | |
| 421 // Verify that R1 is a closure by checking its class. | |
| 422 Label not_closure; | |
| 423 __ LoadImmediate(R8, reinterpret_cast<intptr_t>(Object::null())); | |
| 424 __ cmp(R1, ShifterOperand(R8)); | |
| 425 // Not a closure, but null object. | |
| 426 __ b(¬_closure, EQ); | |
| 427 __ tst(R1, ShifterOperand(kSmiTagMask)); | |
| 428 __ b(¬_closure, EQ); // Not a closure, but a smi. | |
| 429 // Verify that the class of the object is a closure class by checking that | |
| 430 // class.signature_function() is not null. | |
| 431 __ LoadClass(R0, R1, R2); | |
| 432 __ ldr(R0, FieldAddress(R0, Class::signature_function_offset())); | |
| 433 __ cmp(R0, ShifterOperand(R8)); // R8 is raw null. | |
| 434 // Actual class is not a closure class. | |
| 435 __ b(¬_closure, EQ); | |
| 436 | |
| 437 // R0 is just the signature function. Load the actual closure function. | |
| 438 __ ldr(R2, FieldAddress(R1, Closure::function_offset())); | |
| 439 | |
| 440 // Load closure context in CTX; note that CTX has already been preserved. | |
| 441 __ ldr(CTX, FieldAddress(R1, Closure::context_offset())); | |
| 442 | |
| 443 // Load closure function code in EAX. | |
|
zra
2013/04/16 21:12:29
R0?
regis
2013/04/16 21:43:39
Done.
| |
| 444 __ ldr(R0, FieldAddress(R2, Function::code_offset())); | |
| 445 __ cmp(R0, ShifterOperand(R8)); // R8 is raw null. | |
| 446 Label function_compiled; | |
| 447 __ b(&function_compiled, NE); | |
| 448 | |
| 449 // Create a stub frame as we are pushing some objects on the stack before | |
| 450 // calling into the runtime. | |
| 451 __ EnterStubFrame(); | |
| 452 | |
| 453 // Preserve arguments descriptor array and read-only function object argument. | |
| 454 __ PushList((1 << R2) | (1 << R4)); | |
| 455 __ CallRuntime(kCompileFunctionRuntimeEntry); | |
| 456 // Restore arguments descriptor array and read-only function object argument. | |
| 457 __ PopList((1 << R2) | (1 << R4)); | |
| 458 // Restore R0. | |
| 459 __ ldr(R0, FieldAddress(R2, Function::code_offset())); | |
| 460 | |
| 461 // Remove the stub frame as we are about to jump to the closure function. | |
| 462 __ LeaveStubFrame(); | |
| 463 | |
| 464 __ Bind(&function_compiled); | |
| 465 // R0: Code. | |
| 466 // R4: Arguments descriptor array. | |
| 467 __ ldr(R0, FieldAddress(R0, Code::instructions_offset())); | |
| 468 __ AddImmediate(R0, Instructions::HeaderSize() - kHeapObjectTag); | |
| 469 __ bx(R0); | |
| 470 | |
| 471 __ Bind(¬_closure); | |
| 472 // Call runtime to attempt to resolve and invoke a call method on a | |
| 473 // non-closure object, passing the non-closure object and its arguments array, | |
| 474 // returning here. | |
| 475 // If no call method exists, throw a NoSuchMethodError. | |
| 476 // R1: non-closure object. | |
| 477 // R4: arguments descriptor array. | |
| 478 | |
| 479 // Create a stub frame as we are pushing some objects on the stack before | |
| 480 // calling into the runtime. | |
| 481 __ EnterStubFrame(); | |
| 482 | |
| 483 // Setup space on stack for result from error reporting. | |
| 484 __ PushList((1 << R4) | (1 << R8)); // Arguments descriptor and raw null. | |
| 485 | |
| 486 // Load smi-tagged arguments array length, including the non-closure. | |
| 487 __ ldr(R2, FieldAddress(R4, ArgumentsDescriptor::count_offset())); | |
| 488 PushArgumentsArray(assembler); | |
| 489 | |
| 490 // Stack: | |
| 491 // TOS + 0: Argument array. | |
| 492 // TOS + 1: Arguments descriptor array. | |
| 493 // TOS + 2: Place for result from the call. | |
| 494 // TOS + 3: Saved FP of previous frame. | |
| 495 // TOS + 4: Dart code return address | |
| 496 // TOS + 5: PC marker (0 for stub). | |
| 497 // TOS + 6: Last argument of caller. | |
| 498 // .... | |
| 499 __ CallRuntime(kInvokeNonClosureRuntimeEntry); | |
| 500 // Remove arguments. | |
| 501 __ Drop(2); | |
| 502 __ Pop(R0); // Get result into R0. | |
| 503 | |
| 504 // Remove the stub frame as we are about to return. | |
| 505 __ LeaveStubFrame(); | |
| 506 __ Ret(); | |
| 247 } | 507 } |
| 248 | 508 |
| 249 | 509 |
| 250 // Called when invoking Dart code from C++ (VM code). | 510 // Called when invoking Dart code from C++ (VM code). |
| 251 // Input parameters: | 511 // Input parameters: |
| 252 // LR : points to return address. | 512 // LR : points to return address. |
| 253 // R0 : entrypoint of the Dart function to call. | 513 // R0 : entrypoint of the Dart function to call. |
| 254 // R1 : arguments descriptor array. | 514 // R1 : arguments descriptor array. |
| 255 // R2 : arguments array. | 515 // R2 : arguments array. |
| 256 // R3 : new context containing the current isolate pointer. | 516 // R3 : new context containing the current isolate pointer. |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 435 // A new InstantiatedTypeArguments object only needs to be allocated if | 695 // A new InstantiatedTypeArguments object only needs to be allocated if |
| 436 // the instantiator is provided (not kNoInstantiator, but may be null). | 696 // the instantiator is provided (not kNoInstantiator, but may be null). |
| 437 __ CompareImmediate(R0, Smi::RawValue(StubCode::kNoInstantiator)); | 697 __ CompareImmediate(R0, Smi::RawValue(StubCode::kNoInstantiator)); |
| 438 __ AddImmediate(R3, type_args_size, NE); | 698 __ AddImmediate(R3, type_args_size, NE); |
| 439 // R4: potential new object end and, if R4 != R3, potential new | 699 // R4: potential new object end and, if R4 != R3, potential new |
| 440 // InstantiatedTypeArguments object start. | 700 // InstantiatedTypeArguments object start. |
| 441 } | 701 } |
| 442 // Check if the allocation fits into the remaining space. | 702 // Check if the allocation fits into the remaining space. |
| 443 // R2: potential new object start. | 703 // R2: potential new object start. |
| 444 // R3: potential next object start. | 704 // R3: potential next object start. |
| 705 __ LoadImmediate(IP, heap->EndAddress()); | |
| 706 __ cmp(R3, ShifterOperand(IP)); | |
| 445 if (FLAG_use_slow_path) { | 707 if (FLAG_use_slow_path) { |
| 446 __ b(&slow_case); | 708 __ b(&slow_case); |
| 447 } else { | 709 } else { |
| 448 __ LoadImmediate(IP, heap->EndAddress()); | |
| 449 __ cmp(R3, ShifterOperand(IP)); | |
| 450 __ b(&slow_case, CS); // Branch if unsigned higher or equal. | 710 __ b(&slow_case, CS); // Branch if unsigned higher or equal. |
| 451 } | 711 } |
| 452 | 712 |
| 453 // Successfully allocated the object(s), now update top to point to | 713 // Successfully allocated the object(s), now update top to point to |
| 454 // next object start and initialize the object. | 714 // next object start and initialize the object. |
| 455 __ str(R3, Address(R5, 0)); | 715 __ str(R3, Address(R5, 0)); |
| 456 | 716 |
| 457 if (is_cls_parameterized) { | 717 if (is_cls_parameterized) { |
| 458 // Initialize the type arguments field in the object. | 718 // Initialize the type arguments field in the object. |
| 459 // R2: new object start. | 719 // R2: new object start. |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 563 __ CallRuntime(kAllocateObjectRuntimeEntry); // Allocate object. | 823 __ CallRuntime(kAllocateObjectRuntimeEntry); // Allocate object. |
| 564 __ Drop(3); // Pop arguments. | 824 __ Drop(3); // Pop arguments. |
| 565 __ Pop(R0); // Pop result (newly allocated object). | 825 __ Pop(R0); // Pop result (newly allocated object). |
| 566 // R0: new object | 826 // R0: new object |
| 567 // Restore the frame pointer. | 827 // Restore the frame pointer. |
| 568 __ LeaveStubFrame(true); | 828 __ LeaveStubFrame(true); |
| 569 __ Ret(); | 829 __ Ret(); |
| 570 } | 830 } |
| 571 | 831 |
| 572 | 832 |
| 833 // Called for inline allocation of closures. | |
| 834 // Input parameters: | |
| 835 // LR : return address. | |
| 836 // SP + 4 : receiver (null if not an implicit instance closure). | |
| 837 // SP + 0 : type arguments object (null if class is no parameterized). | |
| 573 void StubCode::GenerateAllocationStubForClosure(Assembler* assembler, | 838 void StubCode::GenerateAllocationStubForClosure(Assembler* assembler, |
| 574 const Function& func) { | 839 const Function& func) { |
| 575 __ Unimplemented("AllocateClosure stub"); | 840 ASSERT(func.IsClosureFunction()); |
| 841 const bool is_implicit_static_closure = | |
| 842 func.IsImplicitStaticClosureFunction(); | |
| 843 const bool is_implicit_instance_closure = | |
| 844 func.IsImplicitInstanceClosureFunction(); | |
| 845 const Class& cls = Class::ZoneHandle(func.signature_class()); | |
| 846 const bool has_type_arguments = cls.HasTypeArguments(); | |
| 847 | |
| 848 __ EnterStubFrame(true); // Uses pool pointer to refer to function. | |
| 849 const intptr_t kTypeArgumentsFPOffset = 3 * kWordSize; | |
| 850 const intptr_t kReceiverFPOffset = 4 * kWordSize; | |
| 851 const intptr_t closure_size = Closure::InstanceSize(); | |
| 852 const intptr_t context_size = Context::InstanceSize(1); // Captured receiver. | |
| 853 if (FLAG_inline_alloc && | |
| 854 PageSpace::IsPageAllocatableSize(closure_size + context_size)) { | |
| 855 Label slow_case; | |
| 856 Heap* heap = Isolate::Current()->heap(); | |
| 857 __ LoadImmediate(R5, heap->TopAddress()); | |
| 858 __ ldr(R2, Address(R5, 0)); | |
| 859 __ AddImmediate(R3, R2, closure_size); | |
| 860 if (is_implicit_instance_closure) { | |
| 861 __ mov(R4, ShifterOperand(R3)); // R4: new context address. | |
| 862 __ AddImmediate(R3, context_size); | |
| 863 } | |
| 864 // Check if the allocation fits into the remaining space. | |
| 865 // R2: potential new closure object. | |
| 866 // R3: potential next object start. | |
| 867 // R4: potential new context object (only if is_implicit_closure). | |
| 868 __ LoadImmediate(IP, heap->EndAddress()); | |
| 869 __ cmp(R3, ShifterOperand(IP)); | |
| 870 if (FLAG_use_slow_path) { | |
| 871 __ b(&slow_case); | |
| 872 } else { | |
| 873 __ b(&slow_case, CS); // Branch if unsigned higher or equal. | |
| 874 } | |
| 875 | |
| 876 // Successfully allocated the object, now update top to point to | |
| 877 // next object start and initialize the object. | |
| 878 __ str(R3, Address(R5, 0)); | |
| 879 | |
| 880 // R2: new closure object. | |
| 881 // R4: new context object (only if is_implicit_closure). | |
| 882 // Set the tags. | |
| 883 uword tags = 0; | |
| 884 tags = RawObject::SizeTag::update(closure_size, tags); | |
| 885 tags = RawObject::ClassIdTag::update(cls.id(), tags); | |
| 886 __ LoadImmediate(R0, tags); | |
| 887 __ str(R0, Address(R2, Instance::tags_offset())); | |
| 888 | |
| 889 // Initialize the function field in the object. | |
| 890 // R2: new closure object. | |
| 891 // R4: new context object (only if is_implicit_closure). | |
| 892 __ LoadObject(R0, func); // Load function of closure to be allocated. | |
| 893 __ str(R0, Address(R2, Closure::function_offset())); | |
| 894 | |
| 895 // Setup the context for this closure. | |
| 896 if (is_implicit_static_closure) { | |
| 897 ObjectStore* object_store = Isolate::Current()->object_store(); | |
| 898 ASSERT(object_store != NULL); | |
| 899 const Context& empty_context = | |
| 900 Context::ZoneHandle(object_store->empty_context()); | |
| 901 __ LoadObject(R0, empty_context); | |
| 902 __ str(R0, Address(R2, Closure::context_offset())); | |
| 903 } else if (is_implicit_instance_closure) { | |
| 904 // Initialize the new context capturing the receiver. | |
| 905 const Class& context_class = Class::ZoneHandle(Object::context_class()); | |
| 906 // Set the tags. | |
| 907 uword tags = 0; | |
| 908 tags = RawObject::SizeTag::update(context_size, tags); | |
| 909 tags = RawObject::ClassIdTag::update(context_class.id(), tags); | |
| 910 __ LoadImmediate(R0, tags); | |
| 911 __ str(R0, Address(R4, Context::tags_offset())); | |
| 912 | |
| 913 // Set number of variables field to 1 (for captured receiver). | |
| 914 __ LoadImmediate(R0, 1); | |
| 915 __ str(R0, Address(R4, Context::num_variables_offset())); | |
| 916 | |
| 917 // Set isolate field to isolate of current context. | |
| 918 __ ldr(R0, FieldAddress(CTX, Context::isolate_offset())); | |
| 919 __ str(R0, Address(R4, Context::isolate_offset())); | |
| 920 | |
| 921 // Set the parent to null. | |
| 922 __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null())); | |
| 923 __ str(R0, Address(R4, Context::parent_offset())); | |
| 924 | |
| 925 // Initialize the context variable to the receiver. | |
| 926 __ ldr(R0, Address(FP, kReceiverFPOffset)); | |
| 927 __ str(R0, Address(R4, Context::variable_offset(0))); | |
| 928 | |
| 929 // Set the newly allocated context in the newly allocated closure. | |
| 930 __ add(R1, R4, ShifterOperand(kHeapObjectTag)); | |
| 931 __ str(R1, Address(R2, Closure::context_offset())); | |
| 932 } else { | |
| 933 __ str(CTX, Address(R2, Closure::context_offset())); | |
| 934 } | |
| 935 | |
| 936 // Set the type arguments field in the newly allocated closure. | |
| 937 __ ldr(R0, Address(FP, kTypeArgumentsFPOffset)); | |
| 938 __ str(R0, Address(R2, Closure::type_arguments_offset())); | |
| 939 | |
| 940 // Done allocating and initializing the instance. | |
| 941 // EAX: new object. | |
|
zra
2013/04/16 21:12:29
R0
regis
2013/04/16 21:43:39
Done.
| |
| 942 __ add(R0, R2, ShifterOperand(kHeapObjectTag)); | |
| 943 __ LeaveStubFrame(true); | |
| 944 __ Ret(); | |
| 945 | |
| 946 __ Bind(&slow_case); | |
| 947 } | |
| 948 __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null())); | |
| 949 __ Push(R0); // Setup space on stack for return value. | |
| 950 __ PushObject(func); | |
| 951 if (is_implicit_static_closure) { | |
| 952 __ CallRuntime(kAllocateImplicitStaticClosureRuntimeEntry); | |
| 953 } else { | |
| 954 if (is_implicit_instance_closure) { | |
| 955 __ ldr(R1, Address(FP, kReceiverFPOffset)); | |
| 956 __ Push(R1); // Receiver. | |
| 957 } | |
| 958 // R0: raw null. | |
| 959 if (has_type_arguments) { | |
| 960 __ ldr(R0, Address(FP, kTypeArgumentsFPOffset)); | |
| 961 } | |
| 962 __ Push(R0); // Push type arguments of closure to be allocated or null. | |
| 963 | |
| 964 if (is_implicit_instance_closure) { | |
| 965 __ CallRuntime(kAllocateImplicitInstanceClosureRuntimeEntry); | |
| 966 __ Drop(2); // Pop arguments (type arguments of object and receiver). | |
| 967 } else { | |
| 968 ASSERT(func.IsNonImplicitClosureFunction()); | |
| 969 __ CallRuntime(kAllocateClosureRuntimeEntry); | |
| 970 __ Drop(1); // Pop argument (type arguments of object). | |
| 971 } | |
| 972 } | |
| 973 __ Drop(1); // Pop function object. | |
| 974 __ Pop(R0); | |
| 975 // R0: new object | |
| 976 // Restore the frame pointer. | |
| 977 __ LeaveStubFrame(true); | |
| 978 __ Ret(); | |
| 576 } | 979 } |
| 577 | 980 |
| 578 | 981 |
| 579 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) { | 982 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) { |
| 580 __ Unimplemented("CallNoSuchMethodFunction stub"); | 983 __ Unimplemented("CallNoSuchMethodFunction stub"); |
| 581 } | 984 } |
| 582 | 985 |
| 583 | 986 |
| 584 void StubCode::GenerateOptimizedUsageCounterIncrement(Assembler* assembler) { | 987 void StubCode::GenerateOptimizedUsageCounterIncrement(Assembler* assembler) { |
| 585 __ Unimplemented("OptimizedUsageCounterIncrement stub"); | 988 __ Unimplemented("OptimizedUsageCounterIncrement stub"); |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 690 __ ldr(R1, Address(R6, 0)); // Next class ID. | 1093 __ ldr(R1, Address(R6, 0)); // Next class ID. |
| 691 | 1094 |
| 692 __ Bind(&test); | 1095 __ Bind(&test); |
| 693 __ CompareImmediate(R1, Smi::RawValue(kIllegalCid)); // Done? | 1096 __ CompareImmediate(R1, Smi::RawValue(kIllegalCid)); // Done? |
| 694 __ b(&loop, NE); | 1097 __ b(&loop, NE); |
| 695 | 1098 |
| 696 // IC miss. | 1099 // IC miss. |
| 697 // Restore return address. | 1100 // Restore return address. |
| 698 __ mov(LR, ShifterOperand(R8)); | 1101 __ mov(LR, ShifterOperand(R8)); |
| 699 | 1102 |
| 700 // Compute address of arguments (first read number of arguments from | 1103 // Compute address of arguments. |
| 701 // arguments descriptor array and then compute address on the stack). | |
| 702 // R7: argument_count - 1 (smi). | 1104 // R7: argument_count - 1 (smi). |
| 703 __ add(R7, SP, ShifterOperand(R7, LSL, 1)); // R7 is Smi. | 1105 __ add(R7, SP, ShifterOperand(R7, LSL, 1)); // R7 is Smi. |
| 704 // R7: address of receiver. | 1106 // R7: address of receiver. |
| 705 // Create a stub frame as we are pushing some objects on the stack before | 1107 // Create a stub frame as we are pushing some objects on the stack before |
| 706 // calling into the runtime. | 1108 // calling into the runtime. |
| 707 __ EnterStubFrame(); | 1109 __ EnterStubFrame(); |
| 708 __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null())); | 1110 __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null())); |
| 709 // Preserve IC data object and arguments descriptor array and | 1111 // Preserve IC data object and arguments descriptor array and |
| 710 // setup space on stack for result (target code object). | 1112 // setup space on stack for result (target code object). |
| 711 __ PushList((1 << R0) | (1 << R4) | (1 << R5)); | 1113 __ PushList((1 << R0) | (1 << R4) | (1 << R5)); |
| (...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1083 __ Bind(&reference_compare); | 1485 __ Bind(&reference_compare); |
| 1084 __ cmp(left, ShifterOperand(right)); | 1486 __ cmp(left, ShifterOperand(right)); |
| 1085 __ Bind(&done); | 1487 __ Bind(&done); |
| 1086 __ PopList((1 << R0) | (1 << R1) | (1 << R2)); | 1488 __ PopList((1 << R0) | (1 << R1) | (1 << R2)); |
| 1087 __ Ret(); | 1489 __ Ret(); |
| 1088 } | 1490 } |
| 1089 | 1491 |
| 1090 } // namespace dart | 1492 } // namespace dart |
| 1091 | 1493 |
| 1092 #endif // defined TARGET_ARCH_ARM | 1494 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |