OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_PPC | 7 #if V8_TARGET_ARCH_PPC |
8 | 8 |
9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
10 #include "src/debug.h" | 10 #include "src/debug.h" |
(...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
300 __ bge(&ok); | 300 __ bge(&ok); |
301 | 301 |
302 CallRuntimePassFunction(masm, Runtime::kTryInstallOptimizedCode); | 302 CallRuntimePassFunction(masm, Runtime::kTryInstallOptimizedCode); |
303 GenerateTailCallToReturnedCode(masm); | 303 GenerateTailCallToReturnedCode(masm); |
304 | 304 |
305 __ bind(&ok); | 305 __ bind(&ok); |
306 GenerateTailCallToSharedCode(masm); | 306 GenerateTailCallToSharedCode(masm); |
307 } | 307 } |
308 | 308 |
309 | 309 |
310 static void Generate_Runtime_NewObject(MacroAssembler* masm, | |
311 bool create_memento, | |
312 Register original_constructor, | |
313 Label* count_incremented, | |
314 Label* allocated) { | |
315 // ----------- S t a t e ------------- | |
316 // -- r4: argument for Runtime_NewObject | |
317 // ----------------------------------- | |
318 Register result = r7; | |
319 | |
320 if (create_memento) { | |
321 // Get the cell or allocation site. | |
322 __ LoadP(r5, MemOperand(sp, 3 * kPointerSize)); | |
323 __ Push(r5, r4, original_constructor); | |
324 __ CallRuntime(Runtime::kNewObjectWithAllocationSite, 3); | |
325 __ mr(result, r3); | |
326 // Runtime_NewObjectWithAllocationSite increments allocation count. | |
327 // Skip the increment. | |
328 __ b(count_incremented); | |
329 } else { | |
330 __ Push(r4, original_constructor); | |
331 __ CallRuntime(Runtime::kNewObject, 2); | |
332 __ mr(result, r3); | |
333 __ b(allocated); | |
334 } | |
335 } | |
336 | |
337 | |
338 static void Generate_JSConstructStubHelper(MacroAssembler* masm, | 310 static void Generate_JSConstructStubHelper(MacroAssembler* masm, |
339 bool is_api_function, | 311 bool is_api_function, |
340 bool create_memento) { | 312 bool create_memento) { |
341 // ----------- S t a t e ------------- | 313 // ----------- S t a t e ------------- |
342 // -- r3 : number of arguments | 314 // -- r3 : number of arguments |
343 // -- r4 : constructor function | 315 // -- r4 : constructor function |
344 // -- r5 : allocation site or undefined | 316 // -- r5 : allocation site or undefined |
345 // -- r6 : original constructor | 317 // -- r6 : original constructor |
346 // -- lr : return address | 318 // -- lr : return address |
347 // -- sp[...]: constructor arguments | 319 // -- sp[...]: constructor arguments |
(...skipping 10 matching lines...) Expand all Loading... |
358 | 330 |
359 if (create_memento) { | 331 if (create_memento) { |
360 __ AssertUndefinedOrAllocationSite(r5, r7); | 332 __ AssertUndefinedOrAllocationSite(r5, r7); |
361 __ push(r5); | 333 __ push(r5); |
362 } | 334 } |
363 | 335 |
364 // Preserve the incoming parameters on the stack. | 336 // Preserve the incoming parameters on the stack. |
365 __ SmiTag(r3); | 337 __ SmiTag(r3); |
366 __ Push(r3, r4, r6); | 338 __ Push(r3, r4, r6); |
367 | 339 |
368 Label rt_call, allocated, normal_new, count_incremented; | |
369 __ cmp(r4, r6); | |
370 __ beq(&normal_new); | |
371 | |
372 // Original constructor and function are different. | |
373 Generate_Runtime_NewObject(masm, create_memento, r6, &count_incremented, | |
374 &allocated); | |
375 __ bind(&normal_new); | |
376 | |
377 // Try to allocate the object without transitioning into C code. If any of | 340 // Try to allocate the object without transitioning into C code. If any of |
378 // the preconditions is not met, the code bails out to the runtime call. | 341 // the preconditions is not met, the code bails out to the runtime call. |
| 342 Label rt_call, allocated; |
379 if (FLAG_inline_new) { | 343 if (FLAG_inline_new) { |
380 ExternalReference debug_step_in_fp = | 344 ExternalReference debug_step_in_fp = |
381 ExternalReference::debug_step_in_fp_address(isolate); | 345 ExternalReference::debug_step_in_fp_address(isolate); |
382 __ mov(r5, Operand(debug_step_in_fp)); | 346 __ mov(r5, Operand(debug_step_in_fp)); |
383 __ LoadP(r5, MemOperand(r5)); | 347 __ LoadP(r5, MemOperand(r5)); |
384 __ cmpi(r5, Operand::Zero()); | 348 __ cmpi(r5, Operand::Zero()); |
385 __ bne(&rt_call); | 349 __ bne(&rt_call); |
386 | 350 |
| 351 // Fall back to runtime if the original constructor and function differ. |
| 352 __ cmp(r4, r6); |
| 353 __ bne(&rt_call); |
| 354 |
387 // Load the initial map and verify that it is in fact a map. | 355 // Load the initial map and verify that it is in fact a map. |
388 // r4: constructor function | 356 // r4: constructor function |
389 __ LoadP(r5, | 357 __ LoadP(r5, |
390 FieldMemOperand(r4, JSFunction::kPrototypeOrInitialMapOffset)); | 358 FieldMemOperand(r4, JSFunction::kPrototypeOrInitialMapOffset)); |
391 __ JumpIfSmi(r5, &rt_call); | 359 __ JumpIfSmi(r5, &rt_call); |
392 __ CompareObjectType(r5, r6, r7, MAP_TYPE); | 360 __ CompareObjectType(r5, r8, r7, MAP_TYPE); |
393 __ bne(&rt_call); | 361 __ bne(&rt_call); |
394 | 362 |
395 // Check that the constructor is not constructing a JSFunction (see | 363 // Check that the constructor is not constructing a JSFunction (see |
396 // comments in Runtime_NewObject in runtime.cc). In which case the | 364 // comments in Runtime_NewObject in runtime.cc). In which case the |
397 // initial map's instance type would be JS_FUNCTION_TYPE. | 365 // initial map's instance type would be JS_FUNCTION_TYPE. |
398 // r4: constructor function | 366 // r4: constructor function |
399 // r5: initial map | 367 // r5: initial map |
400 __ CompareInstanceType(r5, r6, JS_FUNCTION_TYPE); | 368 __ CompareInstanceType(r5, r8, JS_FUNCTION_TYPE); |
401 __ beq(&rt_call); | 369 __ beq(&rt_call); |
402 | 370 |
403 if (!is_api_function) { | 371 if (!is_api_function) { |
404 Label allocate; | 372 Label allocate; |
405 MemOperand bit_field3 = FieldMemOperand(r5, Map::kBitField3Offset); | 373 MemOperand bit_field3 = FieldMemOperand(r5, Map::kBitField3Offset); |
406 // Check if slack tracking is enabled. | 374 // Check if slack tracking is enabled. |
407 __ lwz(r7, bit_field3); | 375 __ lwz(r7, bit_field3); |
408 __ DecodeField<Map::Counter>(r11, r7); | 376 __ DecodeField<Map::Counter>(r11, r7); |
409 __ cmpi(r11, Operand(Map::kSlackTrackingCounterEnd)); | 377 __ cmpi(r11, Operand(Map::kSlackTrackingCounterEnd)); |
410 __ blt(&allocate); | 378 __ blt(&allocate); |
411 // Decrease generous allocation count. | 379 // Decrease generous allocation count. |
412 __ Add(r7, r7, -(1 << Map::Counter::kShift), r0); | 380 __ Add(r7, r7, -(1 << Map::Counter::kShift), r0); |
413 __ stw(r7, bit_field3); | 381 __ stw(r7, bit_field3); |
414 __ cmpi(r11, Operand(Map::kSlackTrackingCounterEnd)); | 382 __ cmpi(r11, Operand(Map::kSlackTrackingCounterEnd)); |
415 __ bne(&allocate); | 383 __ bne(&allocate); |
416 | 384 |
417 __ push(r4); | 385 __ push(r4); |
418 | 386 |
419 __ Push(r5, r4); // r4 = constructor | 387 __ Push(r5, r4); // r4 = constructor |
420 __ CallRuntime(Runtime::kFinalizeInstanceSize, 1); | 388 __ CallRuntime(Runtime::kFinalizeInstanceSize, 1); |
421 | 389 |
422 __ Pop(r4, r5); | 390 __ Pop(r4, r5); |
423 | 391 |
424 __ bind(&allocate); | 392 __ bind(&allocate); |
425 } | 393 } |
426 | 394 |
427 // Now allocate the JSObject on the heap. | 395 // Now allocate the JSObject on the heap. |
428 // r4: constructor function | 396 // r4: constructor function |
429 // r5: initial map | 397 // r5: initial map |
| 398 Label rt_call_reload_new_target; |
430 __ lbz(r6, FieldMemOperand(r5, Map::kInstanceSizeOffset)); | 399 __ lbz(r6, FieldMemOperand(r5, Map::kInstanceSizeOffset)); |
431 if (create_memento) { | 400 if (create_memento) { |
432 __ addi(r6, r6, Operand(AllocationMemento::kSize / kPointerSize)); | 401 __ addi(r6, r6, Operand(AllocationMemento::kSize / kPointerSize)); |
433 } | 402 } |
434 | 403 |
435 __ Allocate(r6, r7, r8, r9, &rt_call, SIZE_IN_WORDS); | 404 __ Allocate(r6, r7, r8, r9, &rt_call_reload_new_target, SIZE_IN_WORDS); |
436 | 405 |
437 // Allocated the JSObject, now initialize the fields. Map is set to | 406 // Allocated the JSObject, now initialize the fields. Map is set to |
438 // initial map and properties and elements are set to empty fixed array. | 407 // initial map and properties and elements are set to empty fixed array. |
439 // r4: constructor function | 408 // r4: constructor function |
440 // r5: initial map | 409 // r5: initial map |
441 // r6: object size (including memento if create_memento) | 410 // r6: object size (including memento if create_memento) |
442 // r7: JSObject (not tagged) | 411 // r7: JSObject (not tagged) |
443 __ LoadRoot(r9, Heap::kEmptyFixedArrayRootIndex); | 412 __ LoadRoot(r9, Heap::kEmptyFixedArrayRootIndex); |
444 __ mr(r8, r7); | 413 __ mr(r8, r7); |
445 __ StoreP(r5, MemOperand(r8, JSObject::kMapOffset)); | 414 __ StoreP(r5, MemOperand(r8, JSObject::kMapOffset)); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
510 __ InitializeFieldsWithFiller(r8, r9, r10); | 479 __ InitializeFieldsWithFiller(r8, r9, r10); |
511 } | 480 } |
512 | 481 |
513 // Add the object tag to make the JSObject real, so that we can continue | 482 // Add the object tag to make the JSObject real, so that we can continue |
514 // and jump into the continuation code at any time from now on. | 483 // and jump into the continuation code at any time from now on. |
515 __ addi(r7, r7, Operand(kHeapObjectTag)); | 484 __ addi(r7, r7, Operand(kHeapObjectTag)); |
516 | 485 |
517 // Continue with JSObject being successfully allocated | 486 // Continue with JSObject being successfully allocated |
518 // r7: JSObject | 487 // r7: JSObject |
519 __ b(&allocated); | 488 __ b(&allocated); |
| 489 |
| 490 // Reload the original constructor and fall-through. |
| 491 __ bind(&rt_call_reload_new_target); |
| 492 __ LoadP(r6, MemOperand(sp, 0 * kPointerSize)); |
520 } | 493 } |
521 | 494 |
522 // Allocate the new receiver object using the runtime call. | 495 // Allocate the new receiver object using the runtime call. |
523 // r4: constructor function | 496 // r4: constructor function |
| 497 // r6: original constructor |
524 __ bind(&rt_call); | 498 __ bind(&rt_call); |
525 Generate_Runtime_NewObject(masm, create_memento, r4, &count_incremented, | 499 if (create_memento) { |
526 &allocated); | 500 // Get the cell or allocation site. |
| 501 __ LoadP(r5, MemOperand(sp, 3 * kPointerSize)); |
| 502 __ Push(r5, r4, r6); |
| 503 __ CallRuntime(Runtime::kNewObjectWithAllocationSite, 3); |
| 504 } else { |
| 505 __ Push(r4, r6); |
| 506 __ CallRuntime(Runtime::kNewObject, 2); |
| 507 } |
| 508 __ mr(r7, r3); |
| 509 |
| 510 // Runtime_NewObjectWithAllocationSite increments allocation count. |
| 511 // Skip the increment. |
| 512 Label count_incremented; |
| 513 if (create_memento) { |
| 514 __ b(&count_incremented); |
| 515 } |
527 | 516 |
528 // Receiver for constructor call allocated. | 517 // Receiver for constructor call allocated. |
529 // r7: JSObject | 518 // r7: JSObject |
530 __ bind(&allocated); | 519 __ bind(&allocated); |
531 | 520 |
532 if (create_memento) { | 521 if (create_memento) { |
533 __ LoadP(r5, MemOperand(sp, 3 * kPointerSize)); | 522 __ LoadP(r5, MemOperand(sp, 3 * kPointerSize)); |
534 __ LoadRoot(r8, Heap::kUndefinedValueRootIndex); | 523 __ LoadRoot(r8, Heap::kUndefinedValueRootIndex); |
535 __ cmp(r5, r8); | 524 __ cmp(r5, r8); |
536 __ beq(&count_incremented); | 525 __ beq(&count_incremented); |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
603 // sp[2]: number of arguments (smi-tagged) | 592 // sp[2]: number of arguments (smi-tagged) |
604 __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 593 __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
605 | 594 |
606 // If the result is an object (in the ECMA sense), we should get rid | 595 // If the result is an object (in the ECMA sense), we should get rid |
607 // of the receiver and use the result; see ECMA-262 section 13.2.2-7 | 596 // of the receiver and use the result; see ECMA-262 section 13.2.2-7 |
608 // on page 74. | 597 // on page 74. |
609 Label use_receiver, exit; | 598 Label use_receiver, exit; |
610 | 599 |
611 // If the result is a smi, it is *not* an object in the ECMA sense. | 600 // If the result is a smi, it is *not* an object in the ECMA sense. |
612 // r3: result | 601 // r3: result |
613 // sp[0]: receiver (newly allocated object) | 602 // sp[0]: receiver |
614 // sp[1]: new.target | 603 // sp[1]: new.target |
615 // sp[2]: number of arguments (smi-tagged) | 604 // sp[2]: number of arguments (smi-tagged) |
616 __ JumpIfSmi(r3, &use_receiver); | 605 __ JumpIfSmi(r3, &use_receiver); |
617 | 606 |
618 // If the type of the result (stored in its map) is less than | 607 // If the type of the result (stored in its map) is less than |
619 // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense. | 608 // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense. |
620 __ CompareObjectType(r3, r4, r6, FIRST_SPEC_OBJECT_TYPE); | 609 __ CompareObjectType(r3, r4, r6, FIRST_SPEC_OBJECT_TYPE); |
621 __ bge(&exit); | 610 __ bge(&exit); |
622 | 611 |
623 // Throw away the result of the constructor invocation and use the | 612 // Throw away the result of the constructor invocation and use the |
(...skipping 1172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1796 __ bkpt(0); | 1785 __ bkpt(0); |
1797 } | 1786 } |
1798 } | 1787 } |
1799 | 1788 |
1800 | 1789 |
1801 #undef __ | 1790 #undef __ |
1802 } // namespace internal | 1791 } // namespace internal |
1803 } // namespace v8 | 1792 } // namespace v8 |
1804 | 1793 |
1805 #endif // V8_TARGET_ARCH_PPC | 1794 #endif // V8_TARGET_ARCH_PPC |
OLD | NEW |