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

Side by Side Diff: src/x64/builtins-x64.cc

Issue 1203813002: [es6] Make new.target work in functions (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Add test again. It got lost in last patchset Created 5 years, 5 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
« no previous file with comments | « src/scopes.cc ('k') | test/mjsunit/harmony/new-target.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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_X64 7 #if V8_TARGET_ARCH_X64
8 8
9 #include "src/code-factory.h" 9 #include "src/code-factory.h"
10 #include "src/codegen.h" 10 #include "src/codegen.h"
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
129 if (create_memento) { 129 if (create_memento) {
130 __ jmp(count_incremented); 130 __ jmp(count_incremented);
131 } else { 131 } else {
132 __ jmp(allocated); 132 __ jmp(allocated);
133 } 133 }
134 } 134 }
135 135
136 136
137 static void Generate_JSConstructStubHelper(MacroAssembler* masm, 137 static void Generate_JSConstructStubHelper(MacroAssembler* masm,
138 bool is_api_function, 138 bool is_api_function,
139 bool use_new_target,
139 bool create_memento) { 140 bool create_memento) {
140 // ----------- S t a t e ------------- 141 // ----------- S t a t e -------------
141 // -- rax: number of arguments 142 // -- rax: number of arguments
142 // -- rdi: constructor function 143 // -- rdi: constructor function
143 // -- rbx: allocation site or undefined 144 // -- rbx: allocation site or undefined
144 // -- rdx: original constructor 145 // -- rdx: original constructor
145 // ----------------------------------- 146 // -----------------------------------
146 147
147 // Should never create mementos for api functions. 148 // Should never create mementos for api functions.
148 DCHECK(!is_api_function || !create_memento); 149 DCHECK(!is_api_function || !create_memento);
149 150
150 // Enter a construct frame. 151 // Enter a construct frame.
151 { 152 {
152 FrameScope scope(masm, StackFrame::CONSTRUCT); 153 FrameScope scope(masm, StackFrame::CONSTRUCT);
153 154
154 if (create_memento) { 155 if (create_memento) {
155 __ AssertUndefinedOrAllocationSite(rbx); 156 __ AssertUndefinedOrAllocationSite(rbx);
156 __ Push(rbx); 157 __ Push(rbx);
157 } 158 }
158 159
159 // Store a smi-tagged arguments count on the stack. 160 // Preserve the incoming parameters on the stack.
160 __ Integer32ToSmi(rax, rax); 161 __ Integer32ToSmi(rax, rax);
161 __ Push(rax); 162 __ Push(rax);
162
163 // Push the function to invoke on the stack.
164 __ Push(rdi); 163 __ Push(rdi);
164 if (use_new_target) {
165 __ Push(rdx);
166 }
165 167
166 Label rt_call, normal_new, allocated, count_incremented; 168 Label rt_call, normal_new, allocated, count_incremented;
167 __ cmpp(rdx, rdi); 169 __ cmpp(rdx, rdi);
168 __ j(equal, &normal_new); 170 __ j(equal, &normal_new);
169 171
170 Generate_Runtime_NewObject(masm, create_memento, rdx, &count_incremented, 172 Generate_Runtime_NewObject(masm, create_memento, rdx, &count_incremented,
171 &allocated); 173 &allocated);
172 174
173 __ bind(&normal_new); 175 __ bind(&normal_new);
174 // Try to allocate the object without transitioning into C code. If any of 176 // Try to allocate the object without transitioning into C code. If any of
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
381 // rdi: function (constructor) 383 // rdi: function (constructor)
382 __ bind(&rt_call); 384 __ bind(&rt_call);
383 Generate_Runtime_NewObject(masm, create_memento, rdi, &count_incremented, 385 Generate_Runtime_NewObject(masm, create_memento, rdi, &count_incremented,
384 &allocated); 386 &allocated);
385 387
386 // New object allocated. 388 // New object allocated.
387 // rbx: newly allocated object 389 // rbx: newly allocated object
388 __ bind(&allocated); 390 __ bind(&allocated);
389 391
390 if (create_memento) { 392 if (create_memento) {
391 __ movp(rcx, Operand(rsp, kPointerSize*2)); 393 int offset = (use_new_target ? 3 : 2) * kPointerSize;
394 __ movp(rcx, Operand(rsp, offset));
392 __ Cmp(rcx, masm->isolate()->factory()->undefined_value()); 395 __ Cmp(rcx, masm->isolate()->factory()->undefined_value());
393 __ j(equal, &count_incremented); 396 __ j(equal, &count_incremented);
394 // rcx is an AllocationSite. We are creating a memento from it, so we 397 // rcx is an AllocationSite. We are creating a memento from it, so we
395 // need to increment the memento create count. 398 // need to increment the memento create count.
396 __ SmiAddConstant( 399 __ SmiAddConstant(
397 FieldOperand(rcx, AllocationSite::kPretenureCreateCountOffset), 400 FieldOperand(rcx, AllocationSite::kPretenureCreateCountOffset),
398 Smi::FromInt(1)); 401 Smi::FromInt(1));
399 __ bind(&count_incremented); 402 __ bind(&count_incremented);
400 } 403 }
401 404
402 // Retrieve the function from the stack. 405 // Restore the parameters.
406 if (use_new_target) {
407 __ Pop(rdx);
408 }
403 __ Pop(rdi); 409 __ Pop(rdi);
404 410
405 // Retrieve smi-tagged arguments count from the stack. 411 // Retrieve smi-tagged arguments count from the stack.
406 __ movp(rax, Operand(rsp, 0)); 412 __ movp(rax, Operand(rsp, 0));
407 __ SmiToInteger32(rax, rax); 413 __ SmiToInteger32(rax, rax);
408 414
415 // Push new.target onto the construct frame. This is stored just below the
416 // receiver on the stack.
417 if (use_new_target) {
418 __ Push(rdx);
419 }
420
409 // Push the allocated receiver to the stack. We need two copies 421 // Push the allocated receiver to the stack. We need two copies
410 // because we may have to return the original one and the calling 422 // because we may have to return the original one and the calling
411 // conventions dictate that the called function pops the receiver. 423 // conventions dictate that the called function pops the receiver.
412 __ Push(rbx); 424 __ Push(rbx);
413 __ Push(rbx); 425 __ Push(rbx);
414 426
415 // Set up pointer to last argument. 427 // Set up pointer to last argument.
416 __ leap(rbx, Operand(rbp, StandardFrameConstants::kCallerSPOffset)); 428 __ leap(rbx, Operand(rbp, StandardFrameConstants::kCallerSPOffset));
417 429
418 // Copy arguments and receiver to the expression stack. 430 // Copy arguments and receiver to the expression stack.
(...skipping 11 matching lines...) Expand all
430 __ movp(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); 442 __ movp(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
431 Handle<Code> code = 443 Handle<Code> code =
432 masm->isolate()->builtins()->HandleApiCallConstruct(); 444 masm->isolate()->builtins()->HandleApiCallConstruct();
433 __ Call(code, RelocInfo::CODE_TARGET); 445 __ Call(code, RelocInfo::CODE_TARGET);
434 } else { 446 } else {
435 ParameterCount actual(rax); 447 ParameterCount actual(rax);
436 __ InvokeFunction(rdi, actual, CALL_FUNCTION, NullCallWrapper()); 448 __ InvokeFunction(rdi, actual, CALL_FUNCTION, NullCallWrapper());
437 } 449 }
438 450
439 // Store offset of return address for deoptimizer. 451 // Store offset of return address for deoptimizer.
440 if (!is_api_function) { 452 // TODO(arv): Remove the "!use_new_target" before supporting optimization
453 // of functions that reference new.target
454 if (!is_api_function && !use_new_target) {
441 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset()); 455 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset());
442 } 456 }
443 457
444 // Restore context from the frame. 458 // Restore context from the frame.
445 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 459 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
446 460
447 // If the result is an object (in the ECMA sense), we should get rid 461 // If the result is an object (in the ECMA sense), we should get rid
448 // of the receiver and use the result; see ECMA-262 section 13.2.2-7 462 // of the receiver and use the result; see ECMA-262 section 13.2.2-7
449 // on page 74. 463 // on page 74.
450 Label use_receiver, exit; 464 Label use_receiver, exit;
451 // If the result is a smi, it is *not* an object in the ECMA sense. 465 // If the result is a smi, it is *not* an object in the ECMA sense.
452 __ JumpIfSmi(rax, &use_receiver); 466 __ JumpIfSmi(rax, &use_receiver);
453 467
454 // If the type of the result (stored in its map) is less than 468 // If the type of the result (stored in its map) is less than
455 // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense. 469 // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense.
456 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); 470 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
457 __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rcx); 471 __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rcx);
458 __ j(above_equal, &exit); 472 __ j(above_equal, &exit);
459 473
460 // Throw away the result of the constructor invocation and use the 474 // Throw away the result of the constructor invocation and use the
461 // on-stack receiver as the result. 475 // on-stack receiver as the result.
462 __ bind(&use_receiver); 476 __ bind(&use_receiver);
463 __ movp(rax, Operand(rsp, 0)); 477 __ movp(rax, Operand(rsp, 0));
464 478
465 // Restore the arguments count and leave the construct frame. 479 // Restore the arguments count and leave the construct frame. The arguments
480 // count is stored below the reciever and the new.target.
466 __ bind(&exit); 481 __ bind(&exit);
467 __ movp(rbx, Operand(rsp, kPointerSize)); // Get arguments count. 482 int offset = (use_new_target ? 2 : 1) * kPointerSize;
483 __ movp(rbx, Operand(rsp, offset));
468 484
469 // Leave construct frame. 485 // Leave construct frame.
470 } 486 }
471 487
472 // Remove caller arguments from the stack and return. 488 // Remove caller arguments from the stack and return.
473 __ PopReturnAddressTo(rcx); 489 __ PopReturnAddressTo(rcx);
474 SmiIndex index = masm->SmiToIndex(rbx, rbx, kPointerSizeLog2); 490 SmiIndex index = masm->SmiToIndex(rbx, rbx, kPointerSizeLog2);
475 __ leap(rsp, Operand(rsp, index.reg, index.scale, 1 * kPointerSize)); 491 __ leap(rsp, Operand(rsp, index.reg, index.scale, 1 * kPointerSize));
476 __ PushReturnAddressFrom(rcx); 492 __ PushReturnAddressFrom(rcx);
477 Counters* counters = masm->isolate()->counters(); 493 Counters* counters = masm->isolate()->counters();
478 __ IncrementCounter(counters->constructed_objects(), 1); 494 __ IncrementCounter(counters->constructed_objects(), 1);
479 __ ret(0); 495 __ ret(0);
480 } 496 }
481 497
482 498
483 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { 499 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
484 Generate_JSConstructStubHelper(masm, false, FLAG_pretenuring_call_new); 500 Generate_JSConstructStubHelper(masm, false, false, FLAG_pretenuring_call_new);
485 } 501 }
486 502
487 503
488 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { 504 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) {
489 Generate_JSConstructStubHelper(masm, true, false); 505 Generate_JSConstructStubHelper(masm, true, false, false);
490 } 506 }
491 507
492 508
509 void Builtins::Generate_JSConstructStubNewTarget(MacroAssembler* masm) {
510 Generate_JSConstructStubHelper(masm, false, true, FLAG_pretenuring_call_new);
511 }
512
513
493 void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) { 514 void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) {
494 // ----------- S t a t e ------------- 515 // ----------- S t a t e -------------
495 // -- rax: number of arguments 516 // -- rax: number of arguments
496 // -- rdi: constructor function 517 // -- rdi: constructor function
497 // -- rbx: allocation site or undefined 518 // -- rbx: allocation site or undefined
498 // -- rdx: original constructor 519 // -- rdx: original constructor
499 // ----------------------------------- 520 // -----------------------------------
500 // TODO(dslomov): support pretenuring 521 // TODO(dslomov): support pretenuring
501 CHECK(!FLAG_pretenuring_call_new); 522 CHECK(!FLAG_pretenuring_call_new);
502 523
(...skipping 1280 matching lines...) Expand 10 before | Expand all | Expand 10 after
1783 __ ret(0); 1804 __ ret(0);
1784 } 1805 }
1785 1806
1786 1807
1787 #undef __ 1808 #undef __
1788 1809
1789 } // namespace internal 1810 } // namespace internal
1790 } // namespace v8 1811 } // namespace v8
1791 1812
1792 #endif // V8_TARGET_ARCH_X64 1813 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/scopes.cc ('k') | test/mjsunit/harmony/new-target.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698