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

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

Issue 1203813002: [es6] Make new.target work in functions (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Also adjust the create memento branch Created 5 years, 6 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
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_IA32 7 #if V8_TARGET_ARCH_IA32
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); // Smi-tagged arguments count.
164 165 __ push(edi); // Constructor function.
165 // Push the function to invoke on the stack. 166 if (use_new_target) {
166 __ push(edi); 167 __ push(edx); // new.target
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 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
384 386
385 // Allocate the new receiver object using the runtime call. 387 // Allocate the new receiver object using the runtime call.
386 __ bind(&rt_call); 388 __ bind(&rt_call);
387 Generate_Runtime_NewObject(masm, create_memento, edi, &count_incremented, 389 Generate_Runtime_NewObject(masm, create_memento, edi, &count_incremented,
388 &allocated); 390 &allocated);
389 // New object allocated. 391 // New object allocated.
390 // ebx: newly allocated object 392 // ebx: newly allocated object
391 __ bind(&allocated); 393 __ bind(&allocated);
392 394
393 if (create_memento) { 395 if (create_memento) {
394 __ mov(ecx, Operand(esp, kPointerSize * 2)); 396 int offset = (use_new_target ? 3 : 2) * kPointerSize;
397 __ mov(ecx, Operand(esp, offset));
395 __ cmp(ecx, masm->isolate()->factory()->undefined_value()); 398 __ cmp(ecx, masm->isolate()->factory()->undefined_value());
396 __ j(equal, &count_incremented); 399 __ j(equal, &count_incremented);
397 // ecx is an AllocationSite. We are creating a memento from it, so we 400 // ecx is an AllocationSite. We are creating a memento from it, so we
398 // need to increment the memento create count. 401 // need to increment the memento create count.
399 __ add(FieldOperand(ecx, AllocationSite::kPretenureCreateCountOffset), 402 __ add(FieldOperand(ecx, AllocationSite::kPretenureCreateCountOffset),
400 Immediate(Smi::FromInt(1))); 403 Immediate(Smi::FromInt(1)));
401 __ bind(&count_incremented); 404 __ bind(&count_incremented);
402 } 405 }
403 406
404 // Retrieve the function from the stack. 407 // Restore the parameters.
405 __ pop(edi); 408 if (use_new_target) {
409 __ pop(edx); // new.target
410 }
411 __ pop(edi); // Constructor function.
406 412
407 // Retrieve smi-tagged arguments count from the stack. 413 // Retrieve smi-tagged arguments count from the stack.
408 __ mov(eax, Operand(esp, 0)); 414 __ mov(eax, Operand(esp, 0));
409 __ SmiUntag(eax); 415 __ SmiUntag(eax);
410 416
417 // Push new.target onto the construct frame. This is stored just below the
418 // receiver on the stack.
419 if (use_new_target) {
420 __ push(edx);
421 }
422
411 // Push the allocated receiver to the stack. We need two copies 423 // Push the allocated receiver to the stack. We need two copies
412 // because we may have to return the original one and the calling 424 // because we may have to return the original one and the calling
413 // conventions dictate that the called function pops the receiver. 425 // conventions dictate that the called function pops the receiver.
414 __ push(ebx); 426 __ push(ebx);
415 __ push(ebx); 427 __ push(ebx);
416 428
417 // Set up pointer to last argument. 429 // Set up pointer to last argument.
418 __ lea(ebx, Operand(ebp, StandardFrameConstants::kCallerSPOffset)); 430 __ lea(ebx, Operand(ebp, StandardFrameConstants::kCallerSPOffset));
419 431
420 // Copy arguments and receiver to the expression stack. 432 // Copy arguments and receiver to the expression stack.
(...skipping 12 matching lines...) Expand all
433 Handle<Code> code = 445 Handle<Code> code =
434 masm->isolate()->builtins()->HandleApiCallConstruct(); 446 masm->isolate()->builtins()->HandleApiCallConstruct();
435 __ call(code, RelocInfo::CODE_TARGET); 447 __ call(code, RelocInfo::CODE_TARGET);
436 } else { 448 } else {
437 ParameterCount actual(eax); 449 ParameterCount actual(eax);
438 __ InvokeFunction(edi, actual, CALL_FUNCTION, 450 __ InvokeFunction(edi, actual, CALL_FUNCTION,
439 NullCallWrapper()); 451 NullCallWrapper());
440 } 452 }
441 453
442 // Store offset of return address for deoptimizer. 454 // Store offset of return address for deoptimizer.
443 if (!is_api_function) { 455 // TODO(arv): Remove the "!use_new_target" before supporting optimization
456 // of functions that reference new.target
457 if (!is_api_function && !use_new_target) {
444 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset()); 458 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset());
445 } 459 }
446 460
447 // Restore context from the frame. 461 // Restore context from the frame.
448 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 462 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
449 463
450 // If the result is an object (in the ECMA sense), we should get rid 464 // If the result is an object (in the ECMA sense), we should get rid
451 // of the receiver and use the result; see ECMA-262 section 13.2.2-7 465 // of the receiver and use the result; see ECMA-262 section 13.2.2-7
452 // on page 74. 466 // on page 74.
453 Label use_receiver, exit; 467 Label use_receiver, exit;
454 468
455 // If the result is a smi, it is *not* an object in the ECMA sense. 469 // If the result is a smi, it is *not* an object in the ECMA sense.
456 __ JumpIfSmi(eax, &use_receiver); 470 __ JumpIfSmi(eax, &use_receiver);
457 471
458 // If the type of the result (stored in its map) is less than 472 // If the type of the result (stored in its map) is less than
459 // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense. 473 // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense.
460 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx); 474 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx);
461 __ j(above_equal, &exit); 475 __ j(above_equal, &exit);
462 476
463 // Throw away the result of the constructor invocation and use the 477 // Throw away the result of the constructor invocation and use the
464 // on-stack receiver as the result. 478 // on-stack receiver as the result.
465 __ bind(&use_receiver); 479 __ bind(&use_receiver);
466 __ mov(eax, Operand(esp, 0)); 480 __ mov(eax, Operand(esp, 0));
467 481
468 // Restore the arguments count and leave the construct frame. 482 // Restore the arguments count and leave the construct frame. The arguments
483 // count is stored below the reciever and the new.target.
469 __ bind(&exit); 484 __ bind(&exit);
470 __ mov(ebx, Operand(esp, kPointerSize)); // Get arguments count. 485 int offset = (use_new_target ? 2 : 1) * kPointerSize;
486 __ mov(ebx, Operand(esp, offset));
471 487
472 // Leave construct frame. 488 // Leave construct frame.
473 } 489 }
474 490
475 // Remove caller arguments from the stack and return. 491 // Remove caller arguments from the stack and return.
476 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); 492 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
477 __ pop(ecx); 493 __ pop(ecx);
478 __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); // 1 ~ receiver 494 __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); // 1 ~ receiver
479 __ push(ecx); 495 __ push(ecx);
480 __ IncrementCounter(masm->isolate()->counters()->constructed_objects(), 1); 496 __ IncrementCounter(masm->isolate()->counters()->constructed_objects(), 1);
481 __ ret(0); 497 __ ret(0);
482 } 498 }
483 499
484 500
485 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { 501 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
486 Generate_JSConstructStubHelper(masm, false, FLAG_pretenuring_call_new); 502 Generate_JSConstructStubHelper(masm, false, false, FLAG_pretenuring_call_new);
487 } 503 }
488 504
489 505
490 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { 506 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) {
491 Generate_JSConstructStubHelper(masm, true, false); 507 Generate_JSConstructStubHelper(masm, true, false, false);
492 } 508 }
493 509
494 510
511 void Builtins::Generate_JSConstructStubNewTarget(MacroAssembler* masm) {
512 Generate_JSConstructStubHelper(masm, false, true, FLAG_pretenuring_call_new);
513 }
514
515
495 void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) { 516 void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) {
496 // ----------- S t a t e ------------- 517 // ----------- S t a t e -------------
497 // -- eax: number of arguments 518 // -- eax: number of arguments
498 // -- edi: constructor function 519 // -- edi: constructor function
499 // -- ebx: allocation site or undefined 520 // -- ebx: allocation site or undefined
500 // -- edx: original constructor 521 // -- edx: original constructor
501 // ----------------------------------- 522 // -----------------------------------
502 523
503 // TODO(dslomov): support pretenuring 524 // TODO(dslomov): support pretenuring
504 CHECK(!FLAG_pretenuring_call_new); 525 CHECK(!FLAG_pretenuring_call_new);
(...skipping 1201 matching lines...) Expand 10 before | Expand all | Expand 10 after
1706 1727
1707 __ bind(&ok); 1728 __ bind(&ok);
1708 __ ret(0); 1729 __ ret(0);
1709 } 1730 }
1710 1731
1711 #undef __ 1732 #undef __
1712 } // namespace internal 1733 } // namespace internal
1713 } // namespace v8 1734 } // namespace v8
1714 1735
1715 #endif // V8_TARGET_ARCH_IA32 1736 #endif // V8_TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698