OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
103 RelocInfo::CODE_TARGET); | 103 RelocInfo::CODE_TARGET); |
104 } | 104 } |
105 | 105 |
106 | 106 |
107 static void Generate_JSConstructStubHelper(MacroAssembler* masm, | 107 static void Generate_JSConstructStubHelper(MacroAssembler* masm, |
108 bool is_api_function, | 108 bool is_api_function, |
109 bool count_constructions) { | 109 bool count_constructions) { |
110 // Should never count constructions for api objects. | 110 // Should never count constructions for api objects. |
111 ASSERT(!is_api_function || !count_constructions); | 111 ASSERT(!is_api_function || !count_constructions); |
112 | 112 |
113 // Enter a construct frame. | 113 // Enter a construct frame. |
114 __ EnterConstructFrame(); | 114 { |
| 115 FrameScope scope(masm, StackFrame::CONSTRUCT); |
115 | 116 |
116 // Store a smi-tagged arguments count on the stack. | 117 // Store a smi-tagged arguments count on the stack. |
117 __ Integer32ToSmi(rax, rax); | 118 __ Integer32ToSmi(rax, rax); |
118 __ push(rax); | 119 __ push(rax); |
119 | 120 |
120 // Push the function to invoke on the stack. | 121 // Push the function to invoke on the stack. |
121 __ push(rdi); | 122 __ push(rdi); |
122 | 123 |
123 // Try to allocate the object without transitioning into C code. If any of the | 124 // Try to allocate the object without transitioning into C code. If any of |
124 // preconditions is not met, the code bails out to the runtime call. | 125 // the preconditions is not met, the code bails out to the runtime call. |
125 Label rt_call, allocated; | 126 Label rt_call, allocated; |
126 if (FLAG_inline_new) { | 127 if (FLAG_inline_new) { |
127 Label undo_allocation; | 128 Label undo_allocation; |
128 | 129 |
129 #ifdef ENABLE_DEBUGGER_SUPPORT | 130 #ifdef ENABLE_DEBUGGER_SUPPORT |
130 ExternalReference debug_step_in_fp = | 131 ExternalReference debug_step_in_fp = |
131 ExternalReference::debug_step_in_fp_address(masm->isolate()); | 132 ExternalReference::debug_step_in_fp_address(masm->isolate()); |
132 __ movq(kScratchRegister, debug_step_in_fp); | 133 __ movq(kScratchRegister, debug_step_in_fp); |
133 __ cmpq(Operand(kScratchRegister, 0), Immediate(0)); | 134 __ cmpq(Operand(kScratchRegister, 0), Immediate(0)); |
134 __ j(not_equal, &rt_call); | 135 __ j(not_equal, &rt_call); |
135 #endif | 136 #endif |
136 | 137 |
137 // Verified that the constructor is a JSFunction. | 138 // Verified that the constructor is a JSFunction. |
138 // Load the initial map and verify that it is in fact a map. | 139 // Load the initial map and verify that it is in fact a map. |
139 // rdi: constructor | 140 // rdi: constructor |
140 __ movq(rax, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset)); | 141 __ movq(rax, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset)); |
141 // Will both indicate a NULL and a Smi | 142 // Will both indicate a NULL and a Smi |
142 ASSERT(kSmiTag == 0); | 143 ASSERT(kSmiTag == 0); |
143 __ JumpIfSmi(rax, &rt_call); | 144 __ JumpIfSmi(rax, &rt_call); |
144 // rdi: constructor | 145 // rdi: constructor |
145 // rax: initial map (if proven valid below) | 146 // rax: initial map (if proven valid below) |
146 __ CmpObjectType(rax, MAP_TYPE, rbx); | 147 __ CmpObjectType(rax, MAP_TYPE, rbx); |
147 __ j(not_equal, &rt_call); | 148 __ j(not_equal, &rt_call); |
148 | 149 |
149 // Check that the constructor is not constructing a JSFunction (see comments | 150 // Check that the constructor is not constructing a JSFunction (see |
150 // in Runtime_NewObject in runtime.cc). In which case the initial map's | 151 // comments in Runtime_NewObject in runtime.cc). In which case the initial |
151 // instance type would be JS_FUNCTION_TYPE. | 152 // map's instance type would be JS_FUNCTION_TYPE. |
152 // rdi: constructor | 153 // rdi: constructor |
153 // rax: initial map | 154 // rax: initial map |
154 __ CmpInstanceType(rax, JS_FUNCTION_TYPE); | 155 __ CmpInstanceType(rax, JS_FUNCTION_TYPE); |
155 __ j(equal, &rt_call); | 156 __ j(equal, &rt_call); |
156 | 157 |
157 if (count_constructions) { | 158 if (count_constructions) { |
158 Label allocate; | 159 Label allocate; |
159 // Decrease generous allocation count. | 160 // Decrease generous allocation count. |
160 __ movq(rcx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); | 161 __ movq(rcx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); |
161 __ decb(FieldOperand(rcx, SharedFunctionInfo::kConstructionCountOffset)); | 162 __ decb(FieldOperand(rcx, |
| 163 SharedFunctionInfo::kConstructionCountOffset)); |
162 __ j(not_zero, &allocate); | 164 __ j(not_zero, &allocate); |
163 | 165 |
164 __ push(rax); | 166 __ push(rax); |
165 __ push(rdi); | 167 __ push(rdi); |
166 | 168 |
167 __ push(rdi); // constructor | 169 __ push(rdi); // constructor |
168 // The call will replace the stub, so the countdown is only done once. | 170 // The call will replace the stub, so the countdown is only done once. |
169 __ CallRuntime(Runtime::kFinalizeInstanceSize, 1); | 171 __ CallRuntime(Runtime::kFinalizeInstanceSize, 1); |
170 | 172 |
171 __ pop(rdi); | 173 __ pop(rdi); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
206 __ lea(rcx, Operand(rbx, JSObject::kHeaderSize)); | 208 __ lea(rcx, Operand(rbx, JSObject::kHeaderSize)); |
207 __ jmp(&entry); | 209 __ jmp(&entry); |
208 __ bind(&loop); | 210 __ bind(&loop); |
209 __ movq(Operand(rcx, 0), rdx); | 211 __ movq(Operand(rcx, 0), rdx); |
210 __ addq(rcx, Immediate(kPointerSize)); | 212 __ addq(rcx, Immediate(kPointerSize)); |
211 __ bind(&entry); | 213 __ bind(&entry); |
212 __ cmpq(rcx, rdi); | 214 __ cmpq(rcx, rdi); |
213 __ j(less, &loop); | 215 __ j(less, &loop); |
214 } | 216 } |
215 | 217 |
216 // Add the object tag to make the JSObject real, so that we can continue and | 218 // Add the object tag to make the JSObject real, so that we can continue |
217 // jump into the continuation code at any time from now on. Any failures | 219 // and jump into the continuation code at any time from now on. Any |
218 // need to undo the allocation, so that the heap is in a consistent state | 220 // failures need to undo the allocation, so that the heap is in a |
219 // and verifiable. | 221 // consistent state and verifiable. |
220 // rax: initial map | 222 // rax: initial map |
221 // rbx: JSObject | 223 // rbx: JSObject |
222 // rdi: start of next object | 224 // rdi: start of next object |
223 __ or_(rbx, Immediate(kHeapObjectTag)); | 225 __ or_(rbx, Immediate(kHeapObjectTag)); |
224 | 226 |
225 // Check if a non-empty properties array is needed. | 227 // Check if a non-empty properties array is needed. |
226 // Allocate and initialize a FixedArray if it is. | 228 // Allocate and initialize a FixedArray if it is. |
227 // rax: initial map | 229 // rax: initial map |
228 // rbx: JSObject | 230 // rbx: JSObject |
229 // rdi: start of next object | 231 // rdi: start of next object |
230 // Calculate total properties described map. | 232 // Calculate total properties described map. |
231 __ movzxbq(rdx, FieldOperand(rax, Map::kUnusedPropertyFieldsOffset)); | 233 __ movzxbq(rdx, FieldOperand(rax, Map::kUnusedPropertyFieldsOffset)); |
232 __ movzxbq(rcx, FieldOperand(rax, Map::kPreAllocatedPropertyFieldsOffset)); | 234 __ movzxbq(rcx, |
| 235 FieldOperand(rax, Map::kPreAllocatedPropertyFieldsOffset)); |
233 __ addq(rdx, rcx); | 236 __ addq(rdx, rcx); |
234 // Calculate unused properties past the end of the in-object properties. | 237 // Calculate unused properties past the end of the in-object properties. |
235 __ movzxbq(rcx, FieldOperand(rax, Map::kInObjectPropertiesOffset)); | 238 __ movzxbq(rcx, FieldOperand(rax, Map::kInObjectPropertiesOffset)); |
236 __ subq(rdx, rcx); | 239 __ subq(rdx, rcx); |
237 // Done if no extra properties are to be allocated. | 240 // Done if no extra properties are to be allocated. |
238 __ j(zero, &allocated); | 241 __ j(zero, &allocated); |
239 __ Assert(positive, "Property allocation count failed."); | 242 __ Assert(positive, "Property allocation count failed."); |
240 | 243 |
241 // Scale the number of elements by pointer size and add the header for | 244 // Scale the number of elements by pointer size and add the header for |
242 // FixedArrays to the start of the next object calculation from above. | 245 // FixedArrays to the start of the next object calculation from above. |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
367 __ j(above_equal, &exit); | 370 __ j(above_equal, &exit); |
368 | 371 |
369 // Throw away the result of the constructor invocation and use the | 372 // Throw away the result of the constructor invocation and use the |
370 // on-stack receiver as the result. | 373 // on-stack receiver as the result. |
371 __ bind(&use_receiver); | 374 __ bind(&use_receiver); |
372 __ movq(rax, Operand(rsp, 0)); | 375 __ movq(rax, Operand(rsp, 0)); |
373 | 376 |
374 // Restore the arguments count and leave the construct frame. | 377 // Restore the arguments count and leave the construct frame. |
375 __ bind(&exit); | 378 __ bind(&exit); |
376 __ movq(rbx, Operand(rsp, kPointerSize)); // get arguments count | 379 __ movq(rbx, Operand(rsp, kPointerSize)); // get arguments count |
377 __ LeaveConstructFrame(); | 380 |
| 381 // Leave the construct frame. |
| 382 } |
378 | 383 |
379 // Remove caller arguments from the stack and return. | 384 // Remove caller arguments from the stack and return. |
380 __ pop(rcx); | 385 __ pop(rcx); |
381 SmiIndex index = masm->SmiToIndex(rbx, rbx, kPointerSizeLog2); | 386 SmiIndex index = masm->SmiToIndex(rbx, rbx, kPointerSizeLog2); |
382 __ lea(rsp, Operand(rsp, index.reg, index.scale, 1 * kPointerSize)); | 387 __ lea(rsp, Operand(rsp, index.reg, index.scale, 1 * kPointerSize)); |
383 __ push(rcx); | 388 __ push(rcx); |
384 Counters* counters = masm->isolate()->counters(); | 389 Counters* counters = masm->isolate()->counters(); |
385 __ IncrementCounter(counters->constructed_objects(), 1); | 390 __ IncrementCounter(counters->constructed_objects(), 1); |
386 __ ret(0); | 391 __ ret(0); |
387 } | 392 } |
(...skipping 17 matching lines...) Expand all Loading... |
405 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, | 410 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, |
406 bool is_construct) { | 411 bool is_construct) { |
407 // Expects five C++ function parameters. | 412 // Expects five C++ function parameters. |
408 // - Address entry (ignored) | 413 // - Address entry (ignored) |
409 // - JSFunction* function ( | 414 // - JSFunction* function ( |
410 // - Object* receiver | 415 // - Object* receiver |
411 // - int argc | 416 // - int argc |
412 // - Object*** argv | 417 // - Object*** argv |
413 // (see Handle::Invoke in execution.cc). | 418 // (see Handle::Invoke in execution.cc). |
414 | 419 |
| 420 // Open a C++ scope for the FrameScope. |
| 421 { |
415 // Platform specific argument handling. After this, the stack contains | 422 // Platform specific argument handling. After this, the stack contains |
416 // an internal frame and the pushed function and receiver, and | 423 // an internal frame and the pushed function and receiver, and |
417 // register rax and rbx holds the argument count and argument array, | 424 // register rax and rbx holds the argument count and argument array, |
418 // while rdi holds the function pointer and rsi the context. | 425 // while rdi holds the function pointer and rsi the context. |
| 426 |
419 #ifdef _WIN64 | 427 #ifdef _WIN64 |
420 // MSVC parameters in: | 428 // MSVC parameters in: |
421 // rcx : entry (ignored) | 429 // rcx : entry (ignored) |
422 // rdx : function | 430 // rdx : function |
423 // r8 : receiver | 431 // r8 : receiver |
424 // r9 : argc | 432 // r9 : argc |
425 // [rsp+0x20] : argv | 433 // [rsp+0x20] : argv |
426 | 434 |
427 // Clear the context before we push it when entering the JS frame. | 435 // Clear the context before we push it when entering the internal frame. |
428 __ Set(rsi, 0); | 436 __ Set(rsi, 0); |
429 __ EnterInternalFrame(); | 437 // Enter an internal frame. |
| 438 FrameScope scope(masm, StackFrame::INTERNAL); |
430 | 439 |
431 // Load the function context into rsi. | 440 // Load the function context into rsi. |
432 __ movq(rsi, FieldOperand(rdx, JSFunction::kContextOffset)); | 441 __ movq(rsi, FieldOperand(rdx, JSFunction::kContextOffset)); |
433 | 442 |
434 // Push the function and the receiver onto the stack. | 443 // Push the function and the receiver onto the stack. |
435 __ push(rdx); | 444 __ push(rdx); |
436 __ push(r8); | 445 __ push(r8); |
437 | 446 |
438 // Load the number of arguments and setup pointer to the arguments. | 447 // Load the number of arguments and setup pointer to the arguments. |
439 __ movq(rax, r9); | 448 __ movq(rax, r9); |
440 // Load the previous frame pointer to access C argument on stack | 449 // Load the previous frame pointer to access C argument on stack |
441 __ movq(kScratchRegister, Operand(rbp, 0)); | 450 __ movq(kScratchRegister, Operand(rbp, 0)); |
442 __ movq(rbx, Operand(kScratchRegister, EntryFrameConstants::kArgvOffset)); | 451 __ movq(rbx, Operand(kScratchRegister, EntryFrameConstants::kArgvOffset)); |
443 // Load the function pointer into rdi. | 452 // Load the function pointer into rdi. |
444 __ movq(rdi, rdx); | 453 __ movq(rdi, rdx); |
445 #else // _WIN64 | 454 #else // _WIN64 |
446 // GCC parameters in: | 455 // GCC parameters in: |
447 // rdi : entry (ignored) | 456 // rdi : entry (ignored) |
448 // rsi : function | 457 // rsi : function |
449 // rdx : receiver | 458 // rdx : receiver |
450 // rcx : argc | 459 // rcx : argc |
451 // r8 : argv | 460 // r8 : argv |
452 | 461 |
453 __ movq(rdi, rsi); | 462 __ movq(rdi, rsi); |
454 // rdi : function | 463 // rdi : function |
455 | 464 |
456 // Clear the context before we push it when entering the JS frame. | 465 // Clear the context before we push it when entering the internal frame. |
457 __ Set(rsi, 0); | 466 __ Set(rsi, 0); |
458 // Enter an internal frame. | 467 // Enter an internal frame. |
459 __ EnterInternalFrame(); | 468 FrameScope scope(masm, StackFrame::INTERNAL); |
460 | 469 |
461 // Push the function and receiver and setup the context. | 470 // Push the function and receiver and setup the context. |
462 __ push(rdi); | 471 __ push(rdi); |
463 __ push(rdx); | 472 __ push(rdx); |
464 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); | 473 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); |
465 | 474 |
466 // Load the number of arguments and setup pointer to the arguments. | 475 // Load the number of arguments and setup pointer to the arguments. |
467 __ movq(rax, rcx); | 476 __ movq(rax, rcx); |
468 __ movq(rbx, r8); | 477 __ movq(rbx, r8); |
469 #endif // _WIN64 | 478 #endif // _WIN64 |
(...skipping 26 matching lines...) Expand all Loading... |
496 if (is_construct) { | 505 if (is_construct) { |
497 // Expects rdi to hold function pointer. | 506 // Expects rdi to hold function pointer. |
498 __ Call(masm->isolate()->builtins()->JSConstructCall(), | 507 __ Call(masm->isolate()->builtins()->JSConstructCall(), |
499 RelocInfo::CODE_TARGET); | 508 RelocInfo::CODE_TARGET); |
500 } else { | 509 } else { |
501 ParameterCount actual(rax); | 510 ParameterCount actual(rax); |
502 // Function must be in rdi. | 511 // Function must be in rdi. |
503 __ InvokeFunction(rdi, actual, CALL_FUNCTION, | 512 __ InvokeFunction(rdi, actual, CALL_FUNCTION, |
504 NullCallWrapper(), CALL_AS_METHOD); | 513 NullCallWrapper(), CALL_AS_METHOD); |
505 } | 514 } |
506 | 515 // Exit the internal frame. Notice that this also removes the empty |
507 // Exit the JS frame. Notice that this also removes the empty | |
508 // context and the function left on the stack by the code | 516 // context and the function left on the stack by the code |
509 // invocation. | 517 // invocation. |
510 __ LeaveInternalFrame(); | 518 } |
| 519 |
511 // TODO(X64): Is argument correct? Is there a receiver to remove? | 520 // TODO(X64): Is argument correct? Is there a receiver to remove? |
512 __ ret(1 * kPointerSize); // remove receiver | 521 __ ret(1 * kPointerSize); // Remove receiver. |
513 } | 522 } |
514 | 523 |
515 | 524 |
516 void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) { | 525 void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) { |
517 Generate_JSEntryTrampolineHelper(masm, false); | 526 Generate_JSEntryTrampolineHelper(masm, false); |
518 } | 527 } |
519 | 528 |
520 | 529 |
521 void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) { | 530 void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) { |
522 Generate_JSEntryTrampolineHelper(masm, true); | 531 Generate_JSEntryTrampolineHelper(masm, true); |
523 } | 532 } |
524 | 533 |
525 | 534 |
526 void Builtins::Generate_LazyCompile(MacroAssembler* masm) { | 535 void Builtins::Generate_LazyCompile(MacroAssembler* masm) { |
527 // Enter an internal frame. | 536 // Enter an internal frame. |
528 __ EnterInternalFrame(); | 537 { |
| 538 FrameScope scope(masm, StackFrame::INTERNAL); |
529 | 539 |
530 // Push a copy of the function onto the stack. | 540 // Push a copy of the function onto the stack. |
531 __ push(rdi); | 541 __ push(rdi); |
532 // Push call kind information. | 542 // Push call kind information. |
533 __ push(rcx); | 543 __ push(rcx); |
534 | 544 |
535 __ push(rdi); // Function is also the parameter to the runtime call. | 545 __ push(rdi); // Function is also the parameter to the runtime call. |
536 __ CallRuntime(Runtime::kLazyCompile, 1); | 546 __ CallRuntime(Runtime::kLazyCompile, 1); |
537 | 547 |
538 // Restore call kind information. | 548 // Restore call kind information. |
539 __ pop(rcx); | 549 __ pop(rcx); |
540 // Restore receiver. | 550 // Restore receiver. |
541 __ pop(rdi); | 551 __ pop(rdi); |
542 | 552 |
543 // Tear down temporary frame. | 553 // Tear down internal frame. |
544 __ LeaveInternalFrame(); | 554 } |
545 | 555 |
546 // Do a tail-call of the compiled function. | 556 // Do a tail-call of the compiled function. |
547 __ lea(rax, FieldOperand(rax, Code::kHeaderSize)); | 557 __ lea(rax, FieldOperand(rax, Code::kHeaderSize)); |
548 __ jmp(rax); | 558 __ jmp(rax); |
549 } | 559 } |
550 | 560 |
551 | 561 |
552 void Builtins::Generate_LazyRecompile(MacroAssembler* masm) { | 562 void Builtins::Generate_LazyRecompile(MacroAssembler* masm) { |
553 // Enter an internal frame. | 563 // Enter an internal frame. |
554 __ EnterInternalFrame(); | 564 { |
| 565 FrameScope scope(masm, StackFrame::INTERNAL); |
555 | 566 |
556 // Push a copy of the function onto the stack. | 567 // Push a copy of the function onto the stack. |
557 __ push(rdi); | 568 __ push(rdi); |
558 // Push call kind information. | 569 // Push call kind information. |
559 __ push(rcx); | 570 __ push(rcx); |
560 | 571 |
561 __ push(rdi); // Function is also the parameter to the runtime call. | 572 __ push(rdi); // Function is also the parameter to the runtime call. |
562 __ CallRuntime(Runtime::kLazyRecompile, 1); | 573 __ CallRuntime(Runtime::kLazyRecompile, 1); |
563 | 574 |
564 // Restore call kind information. | 575 // Restore call kind information. |
565 __ pop(rcx); | 576 __ pop(rcx); |
566 // Restore function. | 577 // Restore function. |
567 __ pop(rdi); | 578 __ pop(rdi); |
568 | 579 |
569 // Tear down temporary frame. | 580 // Tear down internal frame. |
570 __ LeaveInternalFrame(); | 581 } |
571 | 582 |
572 // Do a tail-call of the compiled function. | 583 // Do a tail-call of the compiled function. |
573 __ lea(rax, FieldOperand(rax, Code::kHeaderSize)); | 584 __ lea(rax, FieldOperand(rax, Code::kHeaderSize)); |
574 __ jmp(rax); | 585 __ jmp(rax); |
575 } | 586 } |
576 | 587 |
577 | 588 |
578 static void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm, | 589 static void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm, |
579 Deoptimizer::BailoutType type) { | 590 Deoptimizer::BailoutType type) { |
580 // Enter an internal frame. | 591 // Enter an internal frame. |
581 __ EnterInternalFrame(); | 592 { |
| 593 FrameScope scope(masm, StackFrame::INTERNAL); |
582 | 594 |
583 // Pass the deoptimization type to the runtime system. | 595 // Pass the deoptimization type to the runtime system. |
584 __ Push(Smi::FromInt(static_cast<int>(type))); | 596 __ Push(Smi::FromInt(static_cast<int>(type))); |
585 | 597 |
586 __ CallRuntime(Runtime::kNotifyDeoptimized, 1); | 598 __ CallRuntime(Runtime::kNotifyDeoptimized, 1); |
587 // Tear down temporary frame. | 599 // Tear down internal frame. |
588 __ LeaveInternalFrame(); | 600 } |
589 | 601 |
590 // Get the full codegen state from the stack and untag it. | 602 // Get the full codegen state from the stack and untag it. |
591 __ SmiToInteger32(rcx, Operand(rsp, 1 * kPointerSize)); | 603 __ SmiToInteger32(rcx, Operand(rsp, 1 * kPointerSize)); |
592 | 604 |
593 // Switch on the state. | 605 // Switch on the state. |
594 Label not_no_registers, not_tos_rax; | 606 Label not_no_registers, not_tos_rax; |
595 __ cmpq(rcx, Immediate(FullCodeGenerator::NO_REGISTERS)); | 607 __ cmpq(rcx, Immediate(FullCodeGenerator::NO_REGISTERS)); |
596 __ j(not_equal, ¬_no_registers, Label::kNear); | 608 __ j(not_equal, ¬_no_registers, Label::kNear); |
597 __ ret(1 * kPointerSize); // Remove state. | 609 __ ret(1 * kPointerSize); // Remove state. |
598 | 610 |
(...skipping 16 matching lines...) Expand all Loading... |
615 Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::LAZY); | 627 Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::LAZY); |
616 } | 628 } |
617 | 629 |
618 | 630 |
619 void Builtins::Generate_NotifyOSR(MacroAssembler* masm) { | 631 void Builtins::Generate_NotifyOSR(MacroAssembler* masm) { |
620 // For now, we are relying on the fact that Runtime::NotifyOSR | 632 // For now, we are relying on the fact that Runtime::NotifyOSR |
621 // doesn't do any garbage collection which allows us to save/restore | 633 // doesn't do any garbage collection which allows us to save/restore |
622 // the registers without worrying about which of them contain | 634 // the registers without worrying about which of them contain |
623 // pointers. This seems a bit fragile. | 635 // pointers. This seems a bit fragile. |
624 __ Pushad(); | 636 __ Pushad(); |
625 __ EnterInternalFrame(); | 637 { |
626 __ CallRuntime(Runtime::kNotifyOSR, 0); | 638 FrameScope scope(masm, StackFrame::INTERNAL); |
627 __ LeaveInternalFrame(); | 639 __ CallRuntime(Runtime::kNotifyOSR, 0); |
| 640 } |
628 __ Popad(); | 641 __ Popad(); |
629 __ ret(0); | 642 __ ret(0); |
630 } | 643 } |
631 | 644 |
632 | 645 |
633 void Builtins::Generate_FunctionCall(MacroAssembler* masm) { | 646 void Builtins::Generate_FunctionCall(MacroAssembler* masm) { |
634 // Stack Layout: | 647 // Stack Layout: |
635 // rsp[0]: Return address | 648 // rsp[0]: Return address |
636 // rsp[1]: Argument n | 649 // rsp[1]: Argument n |
637 // rsp[2]: Argument n-1 | 650 // rsp[2]: Argument n-1 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
687 __ j(equal, &use_global_receiver); | 700 __ j(equal, &use_global_receiver); |
688 __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex); | 701 __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex); |
689 __ j(equal, &use_global_receiver); | 702 __ j(equal, &use_global_receiver); |
690 | 703 |
691 STATIC_ASSERT(LAST_JS_OBJECT_TYPE + 1 == LAST_TYPE); | 704 STATIC_ASSERT(LAST_JS_OBJECT_TYPE + 1 == LAST_TYPE); |
692 STATIC_ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); | 705 STATIC_ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); |
693 __ CmpObjectType(rbx, FIRST_JS_OBJECT_TYPE, rcx); | 706 __ CmpObjectType(rbx, FIRST_JS_OBJECT_TYPE, rcx); |
694 __ j(above_equal, &shift_arguments); | 707 __ j(above_equal, &shift_arguments); |
695 | 708 |
696 __ bind(&convert_to_object); | 709 __ bind(&convert_to_object); |
697 __ EnterInternalFrame(); // In order to preserve argument count. | 710 { |
| 711 // Enter an internal frame in order to preserve argument count. |
| 712 FrameScope scope(masm, StackFrame::INTERNAL); |
698 __ Integer32ToSmi(rax, rax); | 713 __ Integer32ToSmi(rax, rax); |
699 __ push(rax); | 714 __ push(rax); |
700 | 715 |
701 __ push(rbx); | 716 __ push(rbx); |
702 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); | 717 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); |
703 __ movq(rbx, rax); | 718 __ movq(rbx, rax); |
704 | 719 |
705 __ pop(rax); | 720 __ pop(rax); |
706 __ SmiToInteger32(rax, rax); | 721 __ SmiToInteger32(rax, rax); |
707 __ LeaveInternalFrame(); | 722 } |
| 723 |
708 // Restore the function to rdi. | 724 // Restore the function to rdi. |
709 __ movq(rdi, Operand(rsp, rax, times_pointer_size, 1 * kPointerSize)); | 725 __ movq(rdi, Operand(rsp, rax, times_pointer_size, 1 * kPointerSize)); |
710 __ jmp(&patch_receiver, Label::kNear); | 726 __ jmp(&patch_receiver, Label::kNear); |
711 | 727 |
712 // Use the global receiver object from the called function as the | 728 // Use the global receiver object from the called function as the |
713 // receiver. | 729 // receiver. |
714 __ bind(&use_global_receiver); | 730 __ bind(&use_global_receiver); |
715 const int kGlobalIndex = | 731 const int kGlobalIndex = |
716 Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; | 732 Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; |
717 __ movq(rbx, FieldOperand(rsi, kGlobalIndex)); | 733 __ movq(rbx, FieldOperand(rsi, kGlobalIndex)); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
780 NullCallWrapper(), CALL_AS_METHOD); | 796 NullCallWrapper(), CALL_AS_METHOD); |
781 } | 797 } |
782 | 798 |
783 | 799 |
784 void Builtins::Generate_FunctionApply(MacroAssembler* masm) { | 800 void Builtins::Generate_FunctionApply(MacroAssembler* masm) { |
785 // Stack at entry: | 801 // Stack at entry: |
786 // rsp: return address | 802 // rsp: return address |
787 // rsp+8: arguments | 803 // rsp+8: arguments |
788 // rsp+16: receiver ("this") | 804 // rsp+16: receiver ("this") |
789 // rsp+24: function | 805 // rsp+24: function |
790 __ EnterInternalFrame(); | 806 { |
| 807 FrameScope scope(masm, StackFrame::INTERNAL); |
791 // Stack frame: | 808 // Stack frame: |
792 // rbp: Old base pointer | 809 // rbp: Old base pointer |
793 // rbp[1]: return address | 810 // rbp[1]: return address |
794 // rbp[2]: function arguments | 811 // rbp[2]: function arguments |
795 // rbp[3]: receiver | 812 // rbp[3]: receiver |
796 // rbp[4]: function | 813 // rbp[4]: function |
797 static const int kArgumentsOffset = 2 * kPointerSize; | 814 static const int kArgumentsOffset = 2 * kPointerSize; |
798 static const int kReceiverOffset = 3 * kPointerSize; | 815 static const int kReceiverOffset = 3 * kPointerSize; |
799 static const int kFunctionOffset = 4 * kPointerSize; | 816 static const int kFunctionOffset = 4 * kPointerSize; |
800 __ push(Operand(rbp, kFunctionOffset)); | 817 __ push(Operand(rbp, kFunctionOffset)); |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
913 __ cmpq(rax, Operand(rbp, kLimitOffset)); | 930 __ cmpq(rax, Operand(rbp, kLimitOffset)); |
914 __ j(not_equal, &loop); | 931 __ j(not_equal, &loop); |
915 | 932 |
916 // Invoke the function. | 933 // Invoke the function. |
917 ParameterCount actual(rax); | 934 ParameterCount actual(rax); |
918 __ SmiToInteger32(rax, rax); | 935 __ SmiToInteger32(rax, rax); |
919 __ movq(rdi, Operand(rbp, kFunctionOffset)); | 936 __ movq(rdi, Operand(rbp, kFunctionOffset)); |
920 __ InvokeFunction(rdi, actual, CALL_FUNCTION, | 937 __ InvokeFunction(rdi, actual, CALL_FUNCTION, |
921 NullCallWrapper(), CALL_AS_METHOD); | 938 NullCallWrapper(), CALL_AS_METHOD); |
922 | 939 |
923 __ LeaveInternalFrame(); | 940 // Leave internal frame. |
| 941 } |
924 __ ret(3 * kPointerSize); // remove function, receiver, and arguments | 942 __ ret(3 * kPointerSize); // remove function, receiver, and arguments |
925 } | 943 } |
926 | 944 |
927 | 945 |
928 // Number of empty elements to allocate for an empty array. | 946 // Number of empty elements to allocate for an empty array. |
929 static const int kPreallocatedArrayElements = 4; | 947 static const int kPreallocatedArrayElements = 4; |
930 | 948 |
931 | 949 |
932 // Allocate an empty JSArray. The allocated array is put into the result | 950 // Allocate an empty JSArray. The allocated array is put into the result |
933 // register. If the parameter initial_capacity is larger than zero an elements | 951 // register. If the parameter initial_capacity is larger than zero an elements |
(...skipping 539 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1473 // should perform a stack guard check so we can get interrupts while | 1491 // should perform a stack guard check so we can get interrupts while |
1474 // waiting for on-stack replacement. | 1492 // waiting for on-stack replacement. |
1475 __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); | 1493 __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); |
1476 __ movq(rcx, FieldOperand(rax, JSFunction::kSharedFunctionInfoOffset)); | 1494 __ movq(rcx, FieldOperand(rax, JSFunction::kSharedFunctionInfoOffset)); |
1477 __ movq(rcx, FieldOperand(rcx, SharedFunctionInfo::kCodeOffset)); | 1495 __ movq(rcx, FieldOperand(rcx, SharedFunctionInfo::kCodeOffset)); |
1478 __ cmpb(rbx, FieldOperand(rcx, Code::kAllowOSRAtLoopNestingLevelOffset)); | 1496 __ cmpb(rbx, FieldOperand(rcx, Code::kAllowOSRAtLoopNestingLevelOffset)); |
1479 __ j(greater, &stack_check); | 1497 __ j(greater, &stack_check); |
1480 | 1498 |
1481 // Pass the function to optimize as the argument to the on-stack | 1499 // Pass the function to optimize as the argument to the on-stack |
1482 // replacement runtime function. | 1500 // replacement runtime function. |
1483 __ EnterInternalFrame(); | 1501 { |
| 1502 FrameScope scope(masm, StackFrame::INTERNAL); |
1484 __ push(rax); | 1503 __ push(rax); |
1485 __ CallRuntime(Runtime::kCompileForOnStackReplacement, 1); | 1504 __ CallRuntime(Runtime::kCompileForOnStackReplacement, 1); |
1486 __ LeaveInternalFrame(); | 1505 } |
1487 | 1506 |
1488 // If the result was -1 it means that we couldn't optimize the | 1507 // If the result was -1 it means that we couldn't optimize the |
1489 // function. Just return and continue in the unoptimized version. | 1508 // function. Just return and continue in the unoptimized version. |
1490 Label skip; | 1509 Label skip; |
1491 __ SmiCompare(rax, Smi::FromInt(-1)); | 1510 __ SmiCompare(rax, Smi::FromInt(-1)); |
1492 __ j(not_equal, &skip, Label::kNear); | 1511 __ j(not_equal, &skip, Label::kNear); |
1493 __ ret(0); | 1512 __ ret(0); |
1494 | 1513 |
1495 // If we decide not to perform on-stack replacement we perform a | 1514 // If we decide not to perform on-stack replacement we perform a |
1496 // stack guard check to enable interrupts. | 1515 // stack guard check to enable interrupts. |
1497 __ bind(&stack_check); | 1516 __ bind(&stack_check); |
1498 Label ok; | 1517 Label ok; |
1499 __ CompareRoot(rsp, Heap::kStackLimitRootIndex); | 1518 __ CompareRoot(rsp, Heap::kStackLimitRootIndex); |
1500 __ j(above_equal, &ok, Label::kNear); | 1519 __ j(above_equal, &ok, Label::kNear); |
1501 | 1520 |
1502 StackCheckStub stub; | 1521 StackCheckStub stub; |
1503 __ TailCallStub(&stub); | 1522 __ TailCallStub(&stub); |
1504 __ Abort("Unreachable code: returned from tail call."); | 1523 if (FLAG_debug_code) { |
| 1524 __ Abort("Unreachable code: returned from tail call."); |
| 1525 } |
1505 __ bind(&ok); | 1526 __ bind(&ok); |
1506 __ ret(0); | 1527 __ ret(0); |
1507 | 1528 |
1508 __ bind(&skip); | 1529 __ bind(&skip); |
1509 // Untag the AST id and push it on the stack. | 1530 // Untag the AST id and push it on the stack. |
1510 __ SmiToInteger32(rax, rax); | 1531 __ SmiToInteger32(rax, rax); |
1511 __ push(rax); | 1532 __ push(rax); |
1512 | 1533 |
1513 // Generate the code for doing the frame-to-frame translation using | 1534 // Generate the code for doing the frame-to-frame translation using |
1514 // the deoptimizer infrastructure. | 1535 // the deoptimizer infrastructure. |
1515 Deoptimizer::EntryGenerator generator(masm, Deoptimizer::OSR); | 1536 Deoptimizer::EntryGenerator generator(masm, Deoptimizer::OSR); |
1516 generator.Generate(); | 1537 generator.Generate(); |
1517 } | 1538 } |
1518 | 1539 |
1519 | 1540 |
1520 #undef __ | 1541 #undef __ |
1521 | 1542 |
1522 } } // namespace v8::internal | 1543 } } // namespace v8::internal |
1523 | 1544 |
1524 #endif // V8_TARGET_ARCH_X64 | 1545 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |