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

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

Issue 1217083004: X87: [es6] Make new.target work in functions. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: 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 | « no previous file | 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 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_X87 7 #if V8_TARGET_ARCH_X87
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 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
131 if (create_memento) { 131 if (create_memento) {
132 __ jmp(count_incremented); 132 __ jmp(count_incremented);
133 } else { 133 } else {
134 __ jmp(allocated); 134 __ jmp(allocated);
135 } 135 }
136 } 136 }
137 137
138 138
139 static void Generate_JSConstructStubHelper(MacroAssembler* masm, 139 static void Generate_JSConstructStubHelper(MacroAssembler* masm,
140 bool is_api_function, 140 bool is_api_function,
141 bool use_new_target,
141 bool create_memento) { 142 bool create_memento) {
142 // ----------- S t a t e ------------- 143 // ----------- S t a t e -------------
143 // -- eax: number of arguments 144 // -- eax: number of arguments
144 // -- edi: constructor function 145 // -- edi: constructor function
145 // -- ebx: allocation site or undefined 146 // -- ebx: allocation site or undefined
146 // -- edx: original constructor 147 // -- edx: original constructor
147 // ----------------------------------- 148 // -----------------------------------
148 149
149 // Should never create mementos for api functions. 150 // Should never create mementos for api functions.
150 DCHECK(!is_api_function || !create_memento); 151 DCHECK(!is_api_function || !create_memento);
151 152
152 // Enter a construct frame. 153 // Enter a construct frame.
153 { 154 {
154 FrameScope scope(masm, StackFrame::CONSTRUCT); 155 FrameScope scope(masm, StackFrame::CONSTRUCT);
155 156
156 if (create_memento) { 157 if (create_memento) {
157 __ AssertUndefinedOrAllocationSite(ebx); 158 __ AssertUndefinedOrAllocationSite(ebx);
158 __ push(ebx); 159 __ push(ebx);
159 } 160 }
160 161
161 // Store a smi-tagged arguments count on the stack. 162 // Preserve the incoming parameters on the stack.
162 __ SmiTag(eax); 163 __ SmiTag(eax);
163 __ push(eax); 164 __ push(eax);
164
165 // Push the function to invoke on the stack.
166 __ push(edi); 165 __ push(edi);
166 if (use_new_target) {
167 __ push(edx);
168 }
167 169
168 __ cmp(edx, edi); 170 __ cmp(edx, edi);
169 Label normal_new; 171 Label normal_new;
170 Label count_incremented; 172 Label count_incremented;
171 Label allocated; 173 Label allocated;
172 __ j(equal, &normal_new); 174 __ j(equal, &normal_new);
173 175
174 // Original constructor and function are different. 176 // Original constructor and function are different.
175 Generate_Runtime_NewObject(masm, create_memento, edx, &count_incremented, 177 Generate_Runtime_NewObject(masm, create_memento, edx, &count_incremented,
176 &allocated); 178 &allocated);
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after
392 394
393 // Allocate the new receiver object using the runtime call. 395 // Allocate the new receiver object using the runtime call.
394 __ bind(&rt_call); 396 __ bind(&rt_call);
395 Generate_Runtime_NewObject(masm, create_memento, edi, &count_incremented, 397 Generate_Runtime_NewObject(masm, create_memento, edi, &count_incremented,
396 &allocated); 398 &allocated);
397 // New object allocated. 399 // New object allocated.
398 // ebx: newly allocated object 400 // ebx: newly allocated object
399 __ bind(&allocated); 401 __ bind(&allocated);
400 402
401 if (create_memento) { 403 if (create_memento) {
402 __ mov(ecx, Operand(esp, kPointerSize * 2)); 404 int offset = (use_new_target ? 3 : 2) * kPointerSize;
405 __ mov(ecx, Operand(esp, offset));
403 __ cmp(ecx, masm->isolate()->factory()->undefined_value()); 406 __ cmp(ecx, masm->isolate()->factory()->undefined_value());
404 __ j(equal, &count_incremented); 407 __ j(equal, &count_incremented);
405 // ecx is an AllocationSite. We are creating a memento from it, so we 408 // ecx is an AllocationSite. We are creating a memento from it, so we
406 // need to increment the memento create count. 409 // need to increment the memento create count.
407 __ add(FieldOperand(ecx, AllocationSite::kPretenureCreateCountOffset), 410 __ add(FieldOperand(ecx, AllocationSite::kPretenureCreateCountOffset),
408 Immediate(Smi::FromInt(1))); 411 Immediate(Smi::FromInt(1)));
409 __ bind(&count_incremented); 412 __ bind(&count_incremented);
410 } 413 }
411 414
412 // Retrieve the function from the stack. 415 // Restore the parameters.
413 __ pop(edi); 416 if (use_new_target) {
417 __ pop(edx); // new.target
418 }
419 __ pop(edi); // Constructor function.
414 420
415 // Retrieve smi-tagged arguments count from the stack. 421 // Retrieve smi-tagged arguments count from the stack.
416 __ mov(eax, Operand(esp, 0)); 422 __ mov(eax, Operand(esp, 0));
417 __ SmiUntag(eax); 423 __ SmiUntag(eax);
418 424
425 // Push new.target onto the construct frame. This is stored just below the
426 // receiver on the stack.
427 if (use_new_target) {
428 __ push(edx);
429 }
430
419 // Push the allocated receiver to the stack. We need two copies 431 // Push the allocated receiver to the stack. We need two copies
420 // because we may have to return the original one and the calling 432 // because we may have to return the original one and the calling
421 // conventions dictate that the called function pops the receiver. 433 // conventions dictate that the called function pops the receiver.
422 __ push(ebx); 434 __ push(ebx);
423 __ push(ebx); 435 __ push(ebx);
424 436
425 // Set up pointer to last argument. 437 // Set up pointer to last argument.
426 __ lea(ebx, Operand(ebp, StandardFrameConstants::kCallerSPOffset)); 438 __ lea(ebx, Operand(ebp, StandardFrameConstants::kCallerSPOffset));
427 439
428 // Copy arguments and receiver to the expression stack. 440 // Copy arguments and receiver to the expression stack.
(...skipping 12 matching lines...) Expand all
441 Handle<Code> code = 453 Handle<Code> code =
442 masm->isolate()->builtins()->HandleApiCallConstruct(); 454 masm->isolate()->builtins()->HandleApiCallConstruct();
443 __ call(code, RelocInfo::CODE_TARGET); 455 __ call(code, RelocInfo::CODE_TARGET);
444 } else { 456 } else {
445 ParameterCount actual(eax); 457 ParameterCount actual(eax);
446 __ InvokeFunction(edi, actual, CALL_FUNCTION, 458 __ InvokeFunction(edi, actual, CALL_FUNCTION,
447 NullCallWrapper()); 459 NullCallWrapper());
448 } 460 }
449 461
450 // Store offset of return address for deoptimizer. 462 // Store offset of return address for deoptimizer.
451 if (!is_api_function) { 463 // TODO(arv): Remove the "!use_new_target" before supporting optimization
464 // of functions that reference new.target
465 if (!is_api_function && !use_new_target) {
452 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset()); 466 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset());
453 } 467 }
454 468
455 // Restore context from the frame. 469 // Restore context from the frame.
456 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 470 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
457 471
458 // If the result is an object (in the ECMA sense), we should get rid 472 // If the result is an object (in the ECMA sense), we should get rid
459 // of the receiver and use the result; see ECMA-262 section 13.2.2-7 473 // of the receiver and use the result; see ECMA-262 section 13.2.2-7
460 // on page 74. 474 // on page 74.
461 Label use_receiver, exit; 475 Label use_receiver, exit;
462 476
463 // If the result is a smi, it is *not* an object in the ECMA sense. 477 // If the result is a smi, it is *not* an object in the ECMA sense.
464 __ JumpIfSmi(eax, &use_receiver); 478 __ JumpIfSmi(eax, &use_receiver);
465 479
466 // If the type of the result (stored in its map) is less than 480 // If the type of the result (stored in its map) is less than
467 // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense. 481 // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense.
468 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx); 482 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx);
469 __ j(above_equal, &exit); 483 __ j(above_equal, &exit);
470 484
471 // Throw away the result of the constructor invocation and use the 485 // Throw away the result of the constructor invocation and use the
472 // on-stack receiver as the result. 486 // on-stack receiver as the result.
473 __ bind(&use_receiver); 487 __ bind(&use_receiver);
474 __ mov(eax, Operand(esp, 0)); 488 __ mov(eax, Operand(esp, 0));
475 489
476 // Restore the arguments count and leave the construct frame. 490 // Restore the arguments count and leave the construct frame. The arguments
491 // count is stored below the reciever and the new.target.
477 __ bind(&exit); 492 __ bind(&exit);
478 __ mov(ebx, Operand(esp, kPointerSize)); // Get arguments count. 493 int offset = (use_new_target ? 2 : 1) * kPointerSize;
494 __ mov(ebx, Operand(esp, offset));
479 495
480 // Leave construct frame. 496 // Leave construct frame.
481 } 497 }
482 498
483 // Remove caller arguments from the stack and return. 499 // Remove caller arguments from the stack and return.
484 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); 500 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
485 __ pop(ecx); 501 __ pop(ecx);
486 __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); // 1 ~ receiver 502 __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); // 1 ~ receiver
487 __ push(ecx); 503 __ push(ecx);
488 __ IncrementCounter(masm->isolate()->counters()->constructed_objects(), 1); 504 __ IncrementCounter(masm->isolate()->counters()->constructed_objects(), 1);
489 __ ret(0); 505 __ ret(0);
490 } 506 }
491 507
492 508
493 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { 509 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
494 Generate_JSConstructStubHelper(masm, false, FLAG_pretenuring_call_new); 510 Generate_JSConstructStubHelper(masm, false, false, FLAG_pretenuring_call_new);
495 } 511 }
496 512
497 513
498 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { 514 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) {
499 Generate_JSConstructStubHelper(masm, true, false); 515 Generate_JSConstructStubHelper(masm, true, false, false);
500 } 516 }
501 517
502 518
519 void Builtins::Generate_JSConstructStubNewTarget(MacroAssembler* masm) {
520 Generate_JSConstructStubHelper(masm, false, true, FLAG_pretenuring_call_new);
521 }
522
523
503 void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) { 524 void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) {
504 // ----------- S t a t e ------------- 525 // ----------- S t a t e -------------
505 // -- eax: number of arguments 526 // -- eax: number of arguments
506 // -- edi: constructor function 527 // -- edi: constructor function
507 // -- ebx: allocation site or undefined 528 // -- ebx: allocation site or undefined
508 // -- edx: original constructor 529 // -- edx: original constructor
509 // ----------------------------------- 530 // -----------------------------------
510 531
511 // TODO(dslomov): support pretenuring 532 // TODO(dslomov): support pretenuring
512 CHECK(!FLAG_pretenuring_call_new); 533 CHECK(!FLAG_pretenuring_call_new);
(...skipping 1203 matching lines...) Expand 10 before | Expand all | Expand 10 after
1716 1737
1717 __ bind(&ok); 1738 __ bind(&ok);
1718 __ ret(0); 1739 __ ret(0);
1719 } 1740 }
1720 1741
1721 #undef __ 1742 #undef __
1722 } // namespace internal 1743 } // namespace internal
1723 } // namespace v8 1744 } // namespace v8
1724 1745
1725 #endif // V8_TARGET_ARCH_X87 1746 #endif // V8_TARGET_ARCH_X87
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698