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

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

Issue 1213623020: Remove separate construct stub for new.target users. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Ported to all architectures. 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/frames.h ('k') | src/mips/builtins-mips.cc » ('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_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 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
98 __ bind(&ok); 98 __ bind(&ok);
99 GenerateTailCallToSharedCode(masm); 99 GenerateTailCallToSharedCode(masm);
100 } 100 }
101 101
102 102
103 static void Generate_Runtime_NewObject(MacroAssembler* masm, 103 static void Generate_Runtime_NewObject(MacroAssembler* masm,
104 bool create_memento, 104 bool create_memento,
105 Register original_constructor, 105 Register original_constructor,
106 Label* count_incremented, 106 Label* count_incremented,
107 Label* allocated) { 107 Label* allocated) {
108 int offset = 0; 108 int offset = kPointerSize;
109 if (create_memento) { 109 if (create_memento) {
110 // Get the cell or allocation site. 110 // Get the cell or allocation site.
111 __ mov(edi, Operand(esp, kPointerSize * 2)); 111 __ mov(edi, Operand(esp, kPointerSize * 3));
112 __ push(edi); 112 __ push(edi);
113 offset = kPointerSize; 113 offset += kPointerSize;
114 } 114 }
115 115
116 // Must restore esi (context) and edi (constructor) before calling 116 // Must restore esi (context) and edi (constructor) before calling
117 // runtime. 117 // runtime.
118 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 118 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
119 __ mov(edi, Operand(esp, offset)); 119 __ mov(edi, Operand(esp, offset));
120 __ push(edi); 120 __ push(edi);
121 __ push(original_constructor); 121 __ push(original_constructor);
122 if (create_memento) { 122 if (create_memento) {
123 __ CallRuntime(Runtime::kNewObjectWithAllocationSite, 3); 123 __ CallRuntime(Runtime::kNewObjectWithAllocationSite, 3);
124 } else { 124 } else {
125 __ CallRuntime(Runtime::kNewObject, 2); 125 __ CallRuntime(Runtime::kNewObject, 2);
126 } 126 }
127 __ mov(ebx, eax); // store result in ebx 127 __ mov(ebx, eax); // store result in ebx
128 128
129 // Runtime_NewObjectWithAllocationSite increments allocation count. 129 // Runtime_NewObjectWithAllocationSite increments allocation count.
130 // Skip the increment. 130 // Skip the increment.
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,
142 bool create_memento) { 141 bool create_memento) {
143 // ----------- S t a t e ------------- 142 // ----------- S t a t e -------------
144 // -- eax: number of arguments 143 // -- eax: number of arguments
145 // -- edi: constructor function 144 // -- edi: constructor function
146 // -- ebx: allocation site or undefined 145 // -- ebx: allocation site or undefined
147 // -- edx: original constructor 146 // -- edx: original constructor
148 // ----------------------------------- 147 // -----------------------------------
149 148
150 // Should never create mementos for api functions. 149 // Should never create mementos for api functions.
151 DCHECK(!is_api_function || !create_memento); 150 DCHECK(!is_api_function || !create_memento);
152 151
153 // Enter a construct frame. 152 // Enter a construct frame.
154 { 153 {
155 FrameScope scope(masm, StackFrame::CONSTRUCT); 154 FrameScope scope(masm, StackFrame::CONSTRUCT);
156 155
157 if (create_memento) { 156 if (create_memento) {
158 __ AssertUndefinedOrAllocationSite(ebx); 157 __ AssertUndefinedOrAllocationSite(ebx);
159 __ push(ebx); 158 __ push(ebx);
160 } 159 }
161 160
162 // Preserve the incoming parameters on the stack. 161 // Preserve the incoming parameters on the stack.
163 __ SmiTag(eax); 162 __ SmiTag(eax);
164 __ push(eax); 163 __ push(eax);
165 __ push(edi); 164 __ push(edi);
166 if (use_new_target) { 165 __ push(edx);
167 __ push(edx);
168 }
169 166
170 __ cmp(edx, edi); 167 __ cmp(edx, edi);
171 Label normal_new; 168 Label normal_new;
172 Label count_incremented; 169 Label count_incremented;
173 Label allocated; 170 Label allocated;
174 __ j(equal, &normal_new); 171 __ j(equal, &normal_new);
175 172
176 // Original constructor and function are different. 173 // Original constructor and function are different.
177 Generate_Runtime_NewObject(masm, create_memento, edx, &count_incremented, 174 Generate_Runtime_NewObject(masm, create_memento, edx, &count_incremented,
178 &allocated); 175 &allocated);
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
386 383
387 // Allocate the new receiver object using the runtime call. 384 // Allocate the new receiver object using the runtime call.
388 __ bind(&rt_call); 385 __ bind(&rt_call);
389 Generate_Runtime_NewObject(masm, create_memento, edi, &count_incremented, 386 Generate_Runtime_NewObject(masm, create_memento, edi, &count_incremented,
390 &allocated); 387 &allocated);
391 // New object allocated. 388 // New object allocated.
392 // ebx: newly allocated object 389 // ebx: newly allocated object
393 __ bind(&allocated); 390 __ bind(&allocated);
394 391
395 if (create_memento) { 392 if (create_memento) {
396 int offset = (use_new_target ? 3 : 2) * kPointerSize; 393 __ mov(ecx, Operand(esp, 3 * kPointerSize));
397 __ mov(ecx, Operand(esp, offset));
398 __ cmp(ecx, masm->isolate()->factory()->undefined_value()); 394 __ cmp(ecx, masm->isolate()->factory()->undefined_value());
399 __ j(equal, &count_incremented); 395 __ j(equal, &count_incremented);
400 // ecx is an AllocationSite. We are creating a memento from it, so we 396 // ecx is an AllocationSite. We are creating a memento from it, so we
401 // need to increment the memento create count. 397 // need to increment the memento create count.
402 __ add(FieldOperand(ecx, AllocationSite::kPretenureCreateCountOffset), 398 __ add(FieldOperand(ecx, AllocationSite::kPretenureCreateCountOffset),
403 Immediate(Smi::FromInt(1))); 399 Immediate(Smi::FromInt(1)));
404 __ bind(&count_incremented); 400 __ bind(&count_incremented);
405 } 401 }
406 402
407 // Restore the parameters. 403 // Restore the parameters.
408 if (use_new_target) { 404 __ pop(edx); // new.target
409 __ pop(edx); // new.target
410 }
411 __ pop(edi); // Constructor function. 405 __ pop(edi); // Constructor function.
412 406
413 // Retrieve smi-tagged arguments count from the stack. 407 // Retrieve smi-tagged arguments count from the stack.
414 __ mov(eax, Operand(esp, 0)); 408 __ mov(eax, Operand(esp, 0));
415 __ SmiUntag(eax); 409 __ SmiUntag(eax);
416 410
417 // Push new.target onto the construct frame. This is stored just below the 411 // Push new.target onto the construct frame. This is stored just below the
418 // receiver on the stack. 412 // receiver on the stack.
419 if (use_new_target) { 413 __ push(edx);
420 __ push(edx);
421 }
422 414
423 // Push the allocated receiver to the stack. We need two copies 415 // Push the allocated receiver to the stack. We need two copies
424 // because we may have to return the original one and the calling 416 // because we may have to return the original one and the calling
425 // conventions dictate that the called function pops the receiver. 417 // conventions dictate that the called function pops the receiver.
426 __ push(ebx); 418 __ push(ebx);
427 __ push(ebx); 419 __ push(ebx);
428 420
429 // Set up pointer to last argument. 421 // Set up pointer to last argument.
430 __ lea(ebx, Operand(ebp, StandardFrameConstants::kCallerSPOffset)); 422 __ lea(ebx, Operand(ebp, StandardFrameConstants::kCallerSPOffset));
431 423
(...skipping 13 matching lines...) Expand all
445 Handle<Code> code = 437 Handle<Code> code =
446 masm->isolate()->builtins()->HandleApiCallConstruct(); 438 masm->isolate()->builtins()->HandleApiCallConstruct();
447 __ call(code, RelocInfo::CODE_TARGET); 439 __ call(code, RelocInfo::CODE_TARGET);
448 } else { 440 } else {
449 ParameterCount actual(eax); 441 ParameterCount actual(eax);
450 __ InvokeFunction(edi, actual, CALL_FUNCTION, 442 __ InvokeFunction(edi, actual, CALL_FUNCTION,
451 NullCallWrapper()); 443 NullCallWrapper());
452 } 444 }
453 445
454 // Store offset of return address for deoptimizer. 446 // Store offset of return address for deoptimizer.
455 // TODO(arv): Remove the "!use_new_target" before supporting optimization 447 if (!is_api_function) {
456 // of functions that reference new.target
457 if (!is_api_function && !use_new_target) {
458 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset()); 448 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset());
459 } 449 }
460 450
461 // Restore context from the frame. 451 // Restore context from the frame.
462 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 452 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
463 453
464 // If the result is an object (in the ECMA sense), we should get rid 454 // If the result is an object (in the ECMA sense), we should get rid
465 // of the receiver and use the result; see ECMA-262 section 13.2.2-7 455 // of the receiver and use the result; see ECMA-262 section 13.2.2-7
466 // on page 74. 456 // on page 74.
467 Label use_receiver, exit; 457 Label use_receiver, exit;
468 458
469 // If the result is a smi, it is *not* an object in the ECMA sense. 459 // If the result is a smi, it is *not* an object in the ECMA sense.
470 __ JumpIfSmi(eax, &use_receiver); 460 __ JumpIfSmi(eax, &use_receiver);
471 461
472 // If the type of the result (stored in its map) is less than 462 // If the type of the result (stored in its map) is less than
473 // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense. 463 // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense.
474 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx); 464 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx);
475 __ j(above_equal, &exit); 465 __ j(above_equal, &exit);
476 466
477 // Throw away the result of the constructor invocation and use the 467 // Throw away the result of the constructor invocation and use the
478 // on-stack receiver as the result. 468 // on-stack receiver as the result.
479 __ bind(&use_receiver); 469 __ bind(&use_receiver);
480 __ mov(eax, Operand(esp, 0)); 470 __ mov(eax, Operand(esp, 0));
481 471
482 // Restore the arguments count and leave the construct frame. The arguments 472 // Restore the arguments count and leave the construct frame. The arguments
483 // count is stored below the reciever and the new.target. 473 // count is stored below the reciever and the new.target.
484 __ bind(&exit); 474 __ bind(&exit);
485 int offset = (use_new_target ? 2 : 1) * kPointerSize; 475 __ mov(ebx, Operand(esp, 2 * kPointerSize));
486 __ mov(ebx, Operand(esp, offset));
487 476
488 // Leave construct frame. 477 // Leave construct frame.
489 } 478 }
490 479
491 // Remove caller arguments from the stack and return. 480 // Remove caller arguments from the stack and return.
492 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); 481 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
493 __ pop(ecx); 482 __ pop(ecx);
494 __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); // 1 ~ receiver 483 __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); // 1 ~ receiver
495 __ push(ecx); 484 __ push(ecx);
496 __ IncrementCounter(masm->isolate()->counters()->constructed_objects(), 1); 485 __ IncrementCounter(masm->isolate()->counters()->constructed_objects(), 1);
497 __ ret(0); 486 __ ret(0);
498 } 487 }
499 488
500 489
501 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { 490 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
502 Generate_JSConstructStubHelper(masm, false, false, FLAG_pretenuring_call_new); 491 Generate_JSConstructStubHelper(masm, false, FLAG_pretenuring_call_new);
503 } 492 }
504 493
505 494
506 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { 495 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) {
507 Generate_JSConstructStubHelper(masm, true, false, false); 496 Generate_JSConstructStubHelper(masm, true, false);
508 } 497 }
509 498
510 499
511 void Builtins::Generate_JSConstructStubNewTarget(MacroAssembler* masm) {
512 Generate_JSConstructStubHelper(masm, false, true, FLAG_pretenuring_call_new);
513 }
514
515
516 void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) { 500 void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) {
517 // ----------- S t a t e ------------- 501 // ----------- S t a t e -------------
518 // -- eax: number of arguments 502 // -- eax: number of arguments
519 // -- edi: constructor function 503 // -- edi: constructor function
520 // -- ebx: allocation site or undefined 504 // -- ebx: allocation site or undefined
521 // -- edx: original constructor 505 // -- edx: original constructor
522 // ----------------------------------- 506 // -----------------------------------
523 507
524 // TODO(dslomov): support pretenuring 508 // TODO(dslomov): support pretenuring
525 CHECK(!FLAG_pretenuring_call_new); 509 CHECK(!FLAG_pretenuring_call_new);
(...skipping 1202 matching lines...) Expand 10 before | Expand all | Expand 10 after
1728 1712
1729 __ bind(&ok); 1713 __ bind(&ok);
1730 __ ret(0); 1714 __ ret(0);
1731 } 1715 }
1732 1716
1733 #undef __ 1717 #undef __
1734 } // namespace internal 1718 } // namespace internal
1735 } // namespace v8 1719 } // namespace v8
1736 1720
1737 #endif // V8_TARGET_ARCH_IA32 1721 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/frames.h ('k') | src/mips/builtins-mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698