| 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 #if V8_TARGET_ARCH_PPC | 5 #if V8_TARGET_ARCH_PPC |
| 6 | 6 |
| 7 #include "src/codegen.h" | 7 #include "src/codegen.h" |
| 8 #include "src/debug/debug.h" | 8 #include "src/debug/debug.h" |
| 9 #include "src/deoptimizer.h" | 9 #include "src/deoptimizer.h" |
| 10 #include "src/full-codegen/full-codegen.h" | 10 #include "src/full-codegen/full-codegen.h" |
| (...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 343 | 343 |
| 344 CallRuntimePassFunction(masm, Runtime::kTryInstallOptimizedCode); | 344 CallRuntimePassFunction(masm, Runtime::kTryInstallOptimizedCode); |
| 345 GenerateTailCallToReturnedCode(masm); | 345 GenerateTailCallToReturnedCode(masm); |
| 346 | 346 |
| 347 __ bind(&ok); | 347 __ bind(&ok); |
| 348 GenerateTailCallToSharedCode(masm); | 348 GenerateTailCallToSharedCode(masm); |
| 349 } | 349 } |
| 350 | 350 |
| 351 | 351 |
| 352 static void Generate_JSConstructStubHelper(MacroAssembler* masm, | 352 static void Generate_JSConstructStubHelper(MacroAssembler* masm, |
| 353 bool is_api_function) { | 353 bool is_api_function, |
| 354 bool create_implicit_receiver) { |
| 354 // ----------- S t a t e ------------- | 355 // ----------- S t a t e ------------- |
| 355 // -- r3 : number of arguments | 356 // -- r3 : number of arguments |
| 356 // -- r4 : constructor function | 357 // -- r4 : constructor function |
| 357 // -- r5 : allocation site or undefined | 358 // -- r5 : allocation site or undefined |
| 358 // -- r6 : new target | 359 // -- r6 : new target |
| 359 // -- lr : return address | 360 // -- lr : return address |
| 360 // -- sp[...]: constructor arguments | 361 // -- sp[...]: constructor arguments |
| 361 // ----------------------------------- | 362 // ----------------------------------- |
| 362 | 363 |
| 363 Isolate* isolate = masm->isolate(); | 364 Isolate* isolate = masm->isolate(); |
| 364 | 365 |
| 365 // Enter a construct frame. | 366 // Enter a construct frame. |
| 366 { | 367 { |
| 367 FrameAndConstantPoolScope scope(masm, StackFrame::CONSTRUCT); | 368 FrameAndConstantPoolScope scope(masm, StackFrame::CONSTRUCT); |
| 368 | 369 |
| 369 // Preserve the incoming parameters on the stack. | 370 // Preserve the incoming parameters on the stack. |
| 370 __ AssertUndefinedOrAllocationSite(r5, r7); | 371 __ AssertUndefinedOrAllocationSite(r5, r7); |
| 371 __ SmiTag(r3); | |
| 372 __ Push(r5, r3, r4, r6); | |
| 373 | 372 |
| 374 // Try to allocate the object without transitioning into C code. If any of | 373 if (!create_implicit_receiver) { |
| 375 // the preconditions is not met, the code bails out to the runtime call. | 374 // Push new.target onto the construct frame. This is stored just below the |
| 376 Label rt_call, allocated; | 375 // receiver on the stack. |
| 377 if (FLAG_inline_new) { | 376 __ SmiTag(r7, r3, SetRC); |
| 378 // Verify that the new target is a JSFunction. | 377 __ Push(r5, r7, r6); |
| 379 __ CompareObjectType(r6, r8, r7, JS_FUNCTION_TYPE); | 378 __ PushRoot(Heap::kTheHoleValueRootIndex); |
| 380 __ bne(&rt_call); | 379 } else { |
| 380 __ SmiTag(r3); |
| 381 __ Push(r5, r3, r4, r6); |
| 381 | 382 |
| 382 // Load the initial map and verify that it is in fact a map. | 383 // Try to allocate the object without transitioning into C code. If any of |
| 383 // r6: new target | 384 // the preconditions is not met, the code bails out to the runtime call. |
| 384 __ LoadP(r5, | 385 Label rt_call, allocated; |
| 385 FieldMemOperand(r6, JSFunction::kPrototypeOrInitialMapOffset)); | 386 if (FLAG_inline_new) { |
| 386 __ JumpIfSmi(r5, &rt_call); | 387 // Verify that the new target is a JSFunction. |
| 387 __ CompareObjectType(r5, r8, r7, MAP_TYPE); | 388 __ CompareObjectType(r6, r8, r7, JS_FUNCTION_TYPE); |
| 388 __ bne(&rt_call); | 389 __ bne(&rt_call); |
| 389 | 390 |
| 390 // Fall back to runtime if the expected base constructor and base | 391 // Load the initial map and verify that it is in fact a map. |
| 391 // constructor differ. | 392 // r6: new target |
| 392 __ LoadP(r8, FieldMemOperand(r5, Map::kConstructorOrBackPointerOffset)); | 393 __ LoadP(r5, |
| 393 __ cmp(r4, r8); | 394 FieldMemOperand(r6, JSFunction::kPrototypeOrInitialMapOffset)); |
| 394 __ bne(&rt_call); | 395 __ JumpIfSmi(r5, &rt_call); |
| 396 __ CompareObjectType(r5, r8, r7, MAP_TYPE); |
| 397 __ bne(&rt_call); |
| 395 | 398 |
| 396 // Check that the constructor is not constructing a JSFunction (see | 399 // Fall back to runtime if the expected base constructor and base |
| 397 // comments in Runtime_NewObject in runtime.cc). In which case the | 400 // constructor differ. |
| 398 // initial map's instance type would be JS_FUNCTION_TYPE. | 401 __ LoadP(r8, FieldMemOperand(r5, Map::kConstructorOrBackPointerOffset)); |
| 399 // r4: constructor function | 402 __ cmp(r4, r8); |
| 400 // r5: initial map | 403 __ bne(&rt_call); |
| 401 __ CompareInstanceType(r5, r8, JS_FUNCTION_TYPE); | |
| 402 __ beq(&rt_call); | |
| 403 | 404 |
| 404 if (!is_api_function) { | 405 // Check that the constructor is not constructing a JSFunction (see |
| 405 Label allocate; | 406 // comments in Runtime_NewObject in runtime.cc). In which case the |
| 406 MemOperand bit_field3 = FieldMemOperand(r5, Map::kBitField3Offset); | 407 // initial map's instance type would be JS_FUNCTION_TYPE. |
| 407 // Check if slack tracking is enabled. | 408 // r4: constructor function |
| 408 __ lwz(r7, bit_field3); | 409 // r5: initial map |
| 409 __ DecodeField<Map::Counter>(r11, r7); | 410 __ CompareInstanceType(r5, r8, JS_FUNCTION_TYPE); |
| 410 __ cmpi(r11, Operand(Map::kSlackTrackingCounterEnd)); | 411 __ beq(&rt_call); |
| 411 __ blt(&allocate); | |
| 412 // Decrease generous allocation count. | |
| 413 __ Add(r7, r7, -(1 << Map::Counter::kShift), r0); | |
| 414 __ stw(r7, bit_field3); | |
| 415 __ cmpi(r11, Operand(Map::kSlackTrackingCounterEnd)); | |
| 416 __ bne(&allocate); | |
| 417 | 412 |
| 418 __ Push(r4, r5, r5); // r5 = initial map | 413 if (!is_api_function) { |
| 419 __ CallRuntime(Runtime::kFinalizeInstanceSize, 1); | 414 Label allocate; |
| 415 MemOperand bit_field3 = FieldMemOperand(r5, Map::kBitField3Offset); |
| 416 // Check if slack tracking is enabled. |
| 417 __ lwz(r7, bit_field3); |
| 418 __ DecodeField<Map::Counter>(r11, r7); |
| 419 __ cmpi(r11, Operand(Map::kSlackTrackingCounterEnd)); |
| 420 __ blt(&allocate); |
| 421 // Decrease generous allocation count. |
| 422 __ Add(r7, r7, -(1 << Map::Counter::kShift), r0); |
| 423 __ stw(r7, bit_field3); |
| 424 __ cmpi(r11, Operand(Map::kSlackTrackingCounterEnd)); |
| 425 __ bne(&allocate); |
| 420 | 426 |
| 421 __ Pop(r4, r5); | 427 __ Push(r4, r5, r5); // r5 = initial map |
| 428 __ CallRuntime(Runtime::kFinalizeInstanceSize, 1); |
| 422 | 429 |
| 423 __ bind(&allocate); | 430 __ Pop(r4, r5); |
| 431 |
| 432 __ bind(&allocate); |
| 433 } |
| 434 |
| 435 // Now allocate the JSObject on the heap. |
| 436 // r4: constructor function |
| 437 // r5: initial map |
| 438 Label rt_call_reload_new_target; |
| 439 __ lbz(r6, FieldMemOperand(r5, Map::kInstanceSizeOffset)); |
| 440 |
| 441 __ Allocate(r6, r7, r8, r9, &rt_call_reload_new_target, SIZE_IN_WORDS); |
| 442 |
| 443 // Allocated the JSObject, now initialize the fields. Map is set to |
| 444 // initial map and properties and elements are set to empty fixed array. |
| 445 // r4: constructor function |
| 446 // r5: initial map |
| 447 // r6: object size |
| 448 // r7: JSObject (not tagged) |
| 449 __ LoadRoot(r9, Heap::kEmptyFixedArrayRootIndex); |
| 450 __ mr(r8, r7); |
| 451 __ StoreP(r5, MemOperand(r8, JSObject::kMapOffset)); |
| 452 __ StoreP(r9, MemOperand(r8, JSObject::kPropertiesOffset)); |
| 453 __ StoreP(r9, MemOperand(r8, JSObject::kElementsOffset)); |
| 454 __ addi(r8, r8, Operand(JSObject::kElementsOffset + kPointerSize)); |
| 455 |
| 456 __ ShiftLeftImm(r9, r6, Operand(kPointerSizeLog2)); |
| 457 __ add(r9, r7, r9); // End of object. |
| 458 |
| 459 // Fill all the in-object properties with the appropriate filler. |
| 460 // r4: constructor function |
| 461 // r5: initial map |
| 462 // r6: object size |
| 463 // r7: JSObject (not tagged) |
| 464 // r8: First in-object property of JSObject (not tagged) |
| 465 // r9: End of object |
| 466 DCHECK_EQ(3 * kPointerSize, JSObject::kHeaderSize); |
| 467 __ LoadRoot(r10, Heap::kUndefinedValueRootIndex); |
| 468 |
| 469 if (!is_api_function) { |
| 470 Label no_inobject_slack_tracking; |
| 471 |
| 472 // Check if slack tracking is enabled. |
| 473 __ cmpi(r11, Operand(Map::kSlackTrackingCounterEnd)); |
| 474 __ blt(&no_inobject_slack_tracking); |
| 475 |
| 476 // Allocate object with a slack. |
| 477 __ lbz(r3, |
| 478 FieldMemOperand( |
| 479 r5, |
| 480 Map::kInObjectPropertiesOrConstructorFunctionIndexOffset)); |
| 481 __ lbz(r5, FieldMemOperand(r5, Map::kUnusedPropertyFieldsOffset)); |
| 482 __ sub(r3, r3, r5); |
| 483 if (FLAG_debug_code) { |
| 484 __ ShiftLeftImm(r0, r3, Operand(kPointerSizeLog2)); |
| 485 __ add(r0, r8, r0); |
| 486 // r0: offset of first field after pre-allocated fields |
| 487 __ cmp(r0, r9); |
| 488 __ Assert(le, kUnexpectedNumberOfPreAllocatedPropertyFields); |
| 489 } |
| 490 { |
| 491 Label done; |
| 492 __ cmpi(r3, Operand::Zero()); |
| 493 __ beq(&done); |
| 494 __ InitializeNFieldsWithFiller(r8, r3, r10); |
| 495 __ bind(&done); |
| 496 } |
| 497 // To allow for truncation. |
| 498 __ LoadRoot(r10, Heap::kOnePointerFillerMapRootIndex); |
| 499 // Fill the remaining fields with one pointer filler map. |
| 500 |
| 501 __ bind(&no_inobject_slack_tracking); |
| 502 } |
| 503 |
| 504 __ InitializeFieldsWithFiller(r8, r9, r10); |
| 505 |
| 506 // Add the object tag to make the JSObject real, so that we can continue |
| 507 // and jump into the continuation code at any time from now on. |
| 508 __ addi(r7, r7, Operand(kHeapObjectTag)); |
| 509 |
| 510 // Continue with JSObject being successfully allocated |
| 511 // r7: JSObject |
| 512 __ b(&allocated); |
| 513 |
| 514 // Reload the new target and fall-through. |
| 515 __ bind(&rt_call_reload_new_target); |
| 516 __ LoadP(r6, MemOperand(sp, 0 * kPointerSize)); |
| 424 } | 517 } |
| 425 | 518 |
| 426 // Now allocate the JSObject on the heap. | 519 // Allocate the new receiver object using the runtime call. |
| 427 // r4: constructor function | 520 // r4: constructor function |
| 428 // r5: initial map | 521 // r6: new target |
| 429 Label rt_call_reload_new_target; | 522 __ bind(&rt_call); |
| 430 __ lbz(r6, FieldMemOperand(r5, Map::kInstanceSizeOffset)); | 523 __ Push(r4, r6); // constructor function, new target |
| 524 __ CallRuntime(Runtime::kNewObject, 2); |
| 525 __ mr(r7, r3); |
| 431 | 526 |
| 432 __ Allocate(r6, r7, r8, r9, &rt_call_reload_new_target, SIZE_IN_WORDS); | 527 // Receiver for constructor call allocated. |
| 528 // r7: JSObject |
| 529 __ bind(&allocated); |
| 433 | 530 |
| 434 // Allocated the JSObject, now initialize the fields. Map is set to | 531 // Restore the parameters. |
| 435 // initial map and properties and elements are set to empty fixed array. | 532 __ Pop(r4, r6); |
| 436 // r4: constructor function | |
| 437 // r5: initial map | |
| 438 // r6: object size | |
| 439 // r7: JSObject (not tagged) | |
| 440 __ LoadRoot(r9, Heap::kEmptyFixedArrayRootIndex); | |
| 441 __ mr(r8, r7); | |
| 442 __ StoreP(r5, MemOperand(r8, JSObject::kMapOffset)); | |
| 443 __ StoreP(r9, MemOperand(r8, JSObject::kPropertiesOffset)); | |
| 444 __ StoreP(r9, MemOperand(r8, JSObject::kElementsOffset)); | |
| 445 __ addi(r8, r8, Operand(JSObject::kElementsOffset + kPointerSize)); | |
| 446 | 533 |
| 447 __ ShiftLeftImm(r9, r6, Operand(kPointerSizeLog2)); | 534 // Retrieve smi-tagged arguments count from the stack. |
| 448 __ add(r9, r7, r9); // End of object. | 535 __ LoadP(r3, MemOperand(sp)); |
| 536 __ SmiUntag(r3, SetRC); |
| 449 | 537 |
| 450 // Fill all the in-object properties with the appropriate filler. | 538 // Push new.target onto the construct frame. This is stored just below the |
| 451 // r4: constructor function | 539 // receiver on the stack. |
| 452 // r5: initial map | 540 // Push the allocated receiver to the stack. We need two copies |
| 453 // r6: object size | 541 // because we may have to return the original one and the calling |
| 454 // r7: JSObject (not tagged) | 542 // conventions dictate that the called function pops the receiver. |
| 455 // r8: First in-object property of JSObject (not tagged) | 543 __ Push(r6, r7, r7); |
| 456 // r9: End of object | |
| 457 DCHECK_EQ(3 * kPointerSize, JSObject::kHeaderSize); | |
| 458 __ LoadRoot(r10, Heap::kUndefinedValueRootIndex); | |
| 459 | |
| 460 if (!is_api_function) { | |
| 461 Label no_inobject_slack_tracking; | |
| 462 | |
| 463 // Check if slack tracking is enabled. | |
| 464 __ cmpi(r11, Operand(Map::kSlackTrackingCounterEnd)); | |
| 465 __ blt(&no_inobject_slack_tracking); | |
| 466 | |
| 467 // Allocate object with a slack. | |
| 468 __ lbz( | |
| 469 r3, | |
| 470 FieldMemOperand( | |
| 471 r5, Map::kInObjectPropertiesOrConstructorFunctionIndexOffset)); | |
| 472 __ lbz(r5, FieldMemOperand(r5, Map::kUnusedPropertyFieldsOffset)); | |
| 473 __ sub(r3, r3, r5); | |
| 474 if (FLAG_debug_code) { | |
| 475 __ ShiftLeftImm(r0, r3, Operand(kPointerSizeLog2)); | |
| 476 __ add(r0, r8, r0); | |
| 477 // r0: offset of first field after pre-allocated fields | |
| 478 __ cmp(r0, r9); | |
| 479 __ Assert(le, kUnexpectedNumberOfPreAllocatedPropertyFields); | |
| 480 } | |
| 481 { | |
| 482 Label done; | |
| 483 __ cmpi(r3, Operand::Zero()); | |
| 484 __ beq(&done); | |
| 485 __ InitializeNFieldsWithFiller(r8, r3, r10); | |
| 486 __ bind(&done); | |
| 487 } | |
| 488 // To allow for truncation. | |
| 489 __ LoadRoot(r10, Heap::kOnePointerFillerMapRootIndex); | |
| 490 // Fill the remaining fields with one pointer filler map. | |
| 491 | |
| 492 __ bind(&no_inobject_slack_tracking); | |
| 493 } | |
| 494 | |
| 495 __ InitializeFieldsWithFiller(r8, r9, r10); | |
| 496 | |
| 497 // Add the object tag to make the JSObject real, so that we can continue | |
| 498 // and jump into the continuation code at any time from now on. | |
| 499 __ addi(r7, r7, Operand(kHeapObjectTag)); | |
| 500 | |
| 501 // Continue with JSObject being successfully allocated | |
| 502 // r7: JSObject | |
| 503 __ b(&allocated); | |
| 504 | |
| 505 // Reload the new target and fall-through. | |
| 506 __ bind(&rt_call_reload_new_target); | |
| 507 __ LoadP(r6, MemOperand(sp, 0 * kPointerSize)); | |
| 508 } | 544 } |
| 509 | 545 |
| 510 // Allocate the new receiver object using the runtime call. | |
| 511 // r4: constructor function | |
| 512 // r6: new target | |
| 513 __ bind(&rt_call); | |
| 514 __ Push(r4, r6); // constructor function, new target | |
| 515 __ CallRuntime(Runtime::kNewObject, 2); | |
| 516 __ mr(r7, r3); | |
| 517 | |
| 518 // Receiver for constructor call allocated. | |
| 519 // r7: JSObject | |
| 520 __ bind(&allocated); | |
| 521 | |
| 522 // Restore the parameters. | |
| 523 __ Pop(r4, ip); | |
| 524 | |
| 525 // Retrieve smi-tagged arguments count from the stack. | |
| 526 __ LoadP(r6, MemOperand(sp)); | |
| 527 | |
| 528 // Push new.target onto the construct frame. This is stored just below the | |
| 529 // receiver on the stack. | |
| 530 __ Push(ip, r7, r7); | |
| 531 | |
| 532 // Set up pointer to last argument. | 546 // Set up pointer to last argument. |
| 533 __ addi(r5, fp, Operand(StandardFrameConstants::kCallerSPOffset)); | 547 __ addi(r5, fp, Operand(StandardFrameConstants::kCallerSPOffset)); |
| 534 | 548 |
| 535 // Copy arguments and receiver to the expression stack. | 549 // Copy arguments and receiver to the expression stack. |
| 550 // r3: number of arguments |
| 536 // r4: constructor function | 551 // r4: constructor function |
| 537 // r5: address of last argument (caller sp) | 552 // r5: address of last argument (caller sp) |
| 538 // r6: number of arguments (smi-tagged) | 553 // cr0: condition indicating whether r3 is zero |
| 539 // sp[0]: receiver | 554 // sp[0]: receiver |
| 540 // sp[1]: receiver | 555 // sp[1]: receiver |
| 541 // sp[2]: new.target | 556 // sp[2]: new.target |
| 542 // sp[3]: number of arguments (smi-tagged) | 557 // sp[3]: number of arguments (smi-tagged) |
| 543 Label loop, no_args; | 558 Label loop, no_args; |
| 544 __ SmiUntag(r3, r6, SetRC); | |
| 545 __ beq(&no_args, cr0); | 559 __ beq(&no_args, cr0); |
| 546 __ ShiftLeftImm(ip, r3, Operand(kPointerSizeLog2)); | 560 __ ShiftLeftImm(ip, r3, Operand(kPointerSizeLog2)); |
| 547 __ sub(sp, sp, ip); | 561 __ sub(sp, sp, ip); |
| 548 __ mtctr(r3); | 562 __ mtctr(r3); |
| 549 __ bind(&loop); | 563 __ bind(&loop); |
| 550 __ subi(ip, ip, Operand(kPointerSize)); | 564 __ subi(ip, ip, Operand(kPointerSize)); |
| 551 __ LoadPX(r0, MemOperand(r5, ip)); | 565 __ LoadPX(r0, MemOperand(r5, ip)); |
| 552 __ StorePX(r0, MemOperand(sp, ip)); | 566 __ StorePX(r0, MemOperand(sp, ip)); |
| 553 __ bdnz(&loop); | 567 __ bdnz(&loop); |
| 554 __ bind(&no_args); | 568 __ bind(&no_args); |
| 555 | 569 |
| 556 // Call the function. | 570 // Call the function. |
| 557 // r3: number of arguments | 571 // r3: number of arguments |
| 558 // r4: constructor function | 572 // r4: constructor function |
| 559 if (is_api_function) { | 573 if (is_api_function) { |
| 560 __ LoadP(cp, FieldMemOperand(r4, JSFunction::kContextOffset)); | 574 __ LoadP(cp, FieldMemOperand(r4, JSFunction::kContextOffset)); |
| 561 Handle<Code> code = masm->isolate()->builtins()->HandleApiCallConstruct(); | 575 Handle<Code> code = masm->isolate()->builtins()->HandleApiCallConstruct(); |
| 562 __ Call(code, RelocInfo::CODE_TARGET); | 576 __ Call(code, RelocInfo::CODE_TARGET); |
| 563 } else { | 577 } else { |
| 564 ParameterCount actual(r3); | 578 ParameterCount actual(r3); |
| 565 __ InvokeFunction(r4, actual, CALL_FUNCTION, NullCallWrapper()); | 579 __ InvokeFunction(r4, actual, CALL_FUNCTION, NullCallWrapper()); |
| 566 } | 580 } |
| 567 | 581 |
| 568 // Store offset of return address for deoptimizer. | 582 // Store offset of return address for deoptimizer. |
| 569 if (!is_api_function) { | 583 if (create_implicit_receiver && !is_api_function) { |
| 570 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset()); | 584 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset()); |
| 571 } | 585 } |
| 572 | 586 |
| 573 // Restore context from the frame. | 587 // Restore context from the frame. |
| 574 // r3: result | 588 // r3: result |
| 575 // sp[0]: receiver | 589 // sp[0]: receiver |
| 576 // sp[1]: new.target | 590 // sp[1]: new.target |
| 577 // sp[2]: number of arguments (smi-tagged) | 591 // sp[2]: number of arguments (smi-tagged) |
| 578 __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 592 __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 579 | 593 |
| 580 // If the result is an object (in the ECMA sense), we should get rid | 594 if (create_implicit_receiver) { |
| 581 // of the receiver and use the result; see ECMA-262 section 13.2.2-7 | 595 // If the result is an object (in the ECMA sense), we should get rid |
| 582 // on page 74. | 596 // of the receiver and use the result; see ECMA-262 section 13.2.2-7 |
| 583 Label use_receiver, exit; | 597 // on page 74. |
| 598 Label use_receiver, exit; |
| 584 | 599 |
| 585 // 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. |
| 586 // r3: result | 601 // r3: result |
| 587 // sp[0]: receiver | 602 // sp[0]: receiver |
| 588 // sp[1]: new.target | 603 // sp[1]: new.target |
| 589 // sp[2]: number of arguments (smi-tagged) | 604 // sp[2]: number of arguments (smi-tagged) |
| 590 __ JumpIfSmi(r3, &use_receiver); | 605 __ JumpIfSmi(r3, &use_receiver); |
| 591 | 606 |
| 592 // 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 |
| 593 // 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. |
| 594 __ CompareObjectType(r3, r4, r6, FIRST_SPEC_OBJECT_TYPE); | 609 __ CompareObjectType(r3, r4, r6, FIRST_SPEC_OBJECT_TYPE); |
| 595 __ bge(&exit); | 610 __ bge(&exit); |
| 596 | 611 |
| 597 // Throw away the result of the constructor invocation and use the | 612 // Throw away the result of the constructor invocation and use the |
| 598 // on-stack receiver as the result. | 613 // on-stack receiver as the result. |
| 599 __ bind(&use_receiver); | 614 __ bind(&use_receiver); |
| 600 __ LoadP(r3, MemOperand(sp)); | 615 __ LoadP(r3, MemOperand(sp)); |
| 601 | 616 |
| 602 // Remove receiver from the stack, remove caller arguments, and | 617 // Remove receiver from the stack, remove caller arguments, and |
| 603 // return. | 618 // return. |
| 604 __ bind(&exit); | 619 __ bind(&exit); |
| 605 // r3: result | 620 // r3: result |
| 606 // sp[0]: receiver (newly allocated object) | 621 // sp[0]: receiver (newly allocated object) |
| 607 // sp[1]: new.target (new target) | 622 // sp[1]: new.target (new target) |
| 608 // sp[2]: number of arguments (smi-tagged) | 623 // sp[2]: number of arguments (smi-tagged) |
| 609 __ LoadP(r4, MemOperand(sp, 2 * kPointerSize)); | 624 __ LoadP(r4, MemOperand(sp, 2 * kPointerSize)); |
| 625 } else { |
| 626 __ LoadP(r4, MemOperand(sp, kPointerSize)); |
| 627 } |
| 610 | 628 |
| 611 // Leave construct frame. | 629 // Leave construct frame. |
| 612 } | 630 } |
| 613 | 631 |
| 614 __ SmiToPtrArrayOffset(r4, r4); | 632 __ SmiToPtrArrayOffset(r4, r4); |
| 615 __ add(sp, sp, r4); | 633 __ add(sp, sp, r4); |
| 616 __ addi(sp, sp, Operand(kPointerSize)); | 634 __ addi(sp, sp, Operand(kPointerSize)); |
| 617 __ IncrementCounter(isolate->counters()->constructed_objects(), 1, r4, r5); | 635 if (create_implicit_receiver) { |
| 636 __ IncrementCounter(isolate->counters()->constructed_objects(), 1, r4, r5); |
| 637 } |
| 618 __ blr(); | 638 __ blr(); |
| 619 } | 639 } |
| 620 | 640 |
| 621 | 641 |
| 622 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { | 642 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { |
| 623 Generate_JSConstructStubHelper(masm, false); | 643 Generate_JSConstructStubHelper(masm, false, true); |
| 624 } | 644 } |
| 625 | 645 |
| 626 | 646 |
| 627 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { | 647 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { |
| 628 Generate_JSConstructStubHelper(masm, true); | 648 Generate_JSConstructStubHelper(masm, true, true); |
| 629 } | 649 } |
| 630 | 650 |
| 631 | 651 |
| 632 void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) { | 652 void Builtins::Generate_JSBuiltinsConstructStub(MacroAssembler* masm) { |
| 633 // ----------- S t a t e ------------- | 653 Generate_JSConstructStubHelper(masm, false, false); |
| 634 // -- r3 : number of arguments | |
| 635 // -- r4 : constructor function | |
| 636 // -- r5 : allocation site or undefined | |
| 637 // -- r6 : new target | |
| 638 // -- lr : return address | |
| 639 // -- sp[...]: constructor arguments | |
| 640 // ----------------------------------- | |
| 641 | |
| 642 { | |
| 643 FrameAndConstantPoolScope scope(masm, StackFrame::CONSTRUCT); | |
| 644 | |
| 645 __ AssertUndefinedOrAllocationSite(r5, r7); | |
| 646 | |
| 647 // Smi-tagged arguments count. | |
| 648 __ mr(r7, r3); | |
| 649 __ SmiTag(r7, SetRC); | |
| 650 | |
| 651 // receiver is the hole. | |
| 652 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | |
| 653 | |
| 654 // allocation site, smi arguments count, new.target, receiver | |
| 655 __ Push(r5, r7, r6, ip); | |
| 656 | |
| 657 // Set up pointer to last argument. | |
| 658 __ addi(r5, fp, Operand(StandardFrameConstants::kCallerSPOffset)); | |
| 659 | |
| 660 // Copy arguments and receiver to the expression stack. | |
| 661 // r3: number of arguments | |
| 662 // r4: constructor function | |
| 663 // r5: address of last argument (caller sp) | |
| 664 // r7: number of arguments (smi-tagged) | |
| 665 // cr0: compare against zero of arguments | |
| 666 // sp[0]: receiver | |
| 667 // sp[1]: new.target | |
| 668 // sp[2]: number of arguments (smi-tagged) | |
| 669 Label loop, no_args; | |
| 670 __ beq(&no_args, cr0); | |
| 671 __ ShiftLeftImm(ip, r3, Operand(kPointerSizeLog2)); | |
| 672 __ mtctr(r3); | |
| 673 __ bind(&loop); | |
| 674 __ subi(ip, ip, Operand(kPointerSize)); | |
| 675 __ LoadPX(r0, MemOperand(r5, ip)); | |
| 676 __ push(r0); | |
| 677 __ bdnz(&loop); | |
| 678 __ bind(&no_args); | |
| 679 | |
| 680 // Call the function. | |
| 681 // r3: number of arguments | |
| 682 // r4: constructor function | |
| 683 ParameterCount actual(r3); | |
| 684 __ InvokeFunction(r4, actual, CALL_FUNCTION, NullCallWrapper()); | |
| 685 | |
| 686 // Restore context from the frame. | |
| 687 // r3: result | |
| 688 // sp[0]: number of arguments (smi-tagged) | |
| 689 __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | |
| 690 // Get arguments count, skipping over new.target. | |
| 691 __ LoadP(r4, MemOperand(sp, kPointerSize)); | |
| 692 | |
| 693 // Leave construct frame. | |
| 694 } | |
| 695 | |
| 696 __ SmiToPtrArrayOffset(r4, r4); | |
| 697 __ add(sp, sp, r4); | |
| 698 __ addi(sp, sp, Operand(kPointerSize)); | |
| 699 __ blr(); | |
| 700 } | 654 } |
| 701 | 655 |
| 702 | 656 |
| 703 enum IsTagged { kArgcIsSmiTagged, kArgcIsUntaggedInt }; | 657 enum IsTagged { kArgcIsSmiTagged, kArgcIsUntaggedInt }; |
| 704 | 658 |
| 705 | 659 |
| 706 // Clobbers r5; preserves all other registers. | 660 // Clobbers r5; preserves all other registers. |
| 707 static void Generate_CheckStackOverflow(MacroAssembler* masm, Register argc, | 661 static void Generate_CheckStackOverflow(MacroAssembler* masm, Register argc, |
| 708 IsTagged argc_is_tagged) { | 662 IsTagged argc_is_tagged) { |
| 709 // Check the stack for overflow. We are not trying to catch | 663 // Check the stack for overflow. We are not trying to catch |
| (...skipping 1215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1925 __ bkpt(0); | 1879 __ bkpt(0); |
| 1926 } | 1880 } |
| 1927 } | 1881 } |
| 1928 | 1882 |
| 1929 | 1883 |
| 1930 #undef __ | 1884 #undef __ |
| 1931 } // namespace internal | 1885 } // namespace internal |
| 1932 } // namespace v8 | 1886 } // namespace v8 |
| 1933 | 1887 |
| 1934 #endif // V8_TARGET_ARCH_PPC | 1888 #endif // V8_TARGET_ARCH_PPC |
| OLD | NEW |