OLD | NEW |
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 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 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
299 #ifdef DEBUG | 299 #ifdef DEBUG |
300 if (strlen(FLAG_stop_at) > 0 && | 300 if (strlen(FLAG_stop_at) > 0 && |
301 function->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { | 301 function->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { |
302 frame_->SpillAll(); | 302 frame_->SpillAll(); |
303 __ int3(); | 303 __ int3(); |
304 } | 304 } |
305 #endif | 305 #endif |
306 | 306 |
307 // New scope to get automatic timing calculation. | 307 // New scope to get automatic timing calculation. |
308 { // NOLINT | 308 { // NOLINT |
309 HistogramTimerScope codegen_timer(&Counters::code_generation); | 309 HistogramTimerScope codegen_timer(&COUNTER(code_generation)); |
310 CodeGenState state(this); | 310 CodeGenState state(this); |
311 | 311 |
312 // Entry: | 312 // Entry: |
313 // Stack: receiver, arguments, return address. | 313 // Stack: receiver, arguments, return address. |
314 // rbp: caller's frame pointer | 314 // rbp: caller's frame pointer |
315 // rsp: stack pointer | 315 // rsp: stack pointer |
316 // rdi: called JS function | 316 // rdi: called JS function |
317 // rsi: callee's context | 317 // rsi: callee's context |
318 allocator_->Initialize(); | 318 allocator_->Initialize(); |
319 frame_->Enter(); | 319 frame_->Enter(); |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
461 | 461 |
462 // Code generation state must be reset. | 462 // Code generation state must be reset. |
463 ASSERT(state_ == NULL); | 463 ASSERT(state_ == NULL); |
464 ASSERT(loop_nesting() == 0); | 464 ASSERT(loop_nesting() == 0); |
465 ASSERT(!function_return_is_shadowed_); | 465 ASSERT(!function_return_is_shadowed_); |
466 function_return_.Unuse(); | 466 function_return_.Unuse(); |
467 DeleteFrame(); | 467 DeleteFrame(); |
468 | 468 |
469 // Process any deferred code using the register allocator. | 469 // Process any deferred code using the register allocator. |
470 if (!HasStackOverflow()) { | 470 if (!HasStackOverflow()) { |
471 HistogramTimerScope deferred_timer(&Counters::deferred_code_generation); | 471 HistogramTimerScope deferred_timer(&COUNTER(deferred_code_generation)); |
472 JumpTarget::set_compiling_deferred_code(true); | 472 JumpTarget::set_compiling_deferred_code(true); |
473 ProcessDeferred(); | 473 ProcessDeferred(); |
474 JumpTarget::set_compiling_deferred_code(false); | 474 JumpTarget::set_compiling_deferred_code(false); |
475 } | 475 } |
476 | 476 |
477 // There is no need to delete the register allocator, it is a | 477 // There is no need to delete the register allocator, it is a |
478 // stack-allocated local. | 478 // stack-allocated local. |
479 allocator_ = NULL; | 479 allocator_ = NULL; |
480 scope_ = NULL; | 480 scope_ = NULL; |
481 } | 481 } |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
578 // macro because the macro sometimes uses macro expansion to turn | 578 // macro because the macro sometimes uses macro expansion to turn |
579 // into something that can't return a value. This is encountered | 579 // into something that can't return a value. This is encountered |
580 // when doing generated code coverage tests. | 580 // when doing generated code coverage tests. |
581 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(patch_site()); | 581 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(patch_site()); |
582 // Here we use masm_-> instead of the __ macro because this is the | 582 // Here we use masm_-> instead of the __ macro because this is the |
583 // instruction that gets patched and coverage code gets in the way. | 583 // instruction that gets patched and coverage code gets in the way. |
584 // TODO(X64): Consider whether it's worth switching the test to a | 584 // TODO(X64): Consider whether it's worth switching the test to a |
585 // 7-byte NOP with non-zero immediate (0f 1f 80 xxxxxxxx) which won't | 585 // 7-byte NOP with non-zero immediate (0f 1f 80 xxxxxxxx) which won't |
586 // be generated normally. | 586 // be generated normally. |
587 masm_->testl(rax, Immediate(-delta_to_patch_site)); | 587 masm_->testl(rax, Immediate(-delta_to_patch_site)); |
588 __ IncrementCounter(&Counters::keyed_load_inline_miss, 1); | 588 __ IncrementCounter(&COUNTER(keyed_load_inline_miss), 1); |
589 | 589 |
590 if (!dst_.is(rax)) __ movq(dst_, rax); | 590 if (!dst_.is(rax)) __ movq(dst_, rax); |
591 __ pop(key_); | 591 __ pop(key_); |
592 __ pop(receiver_); | 592 __ pop(receiver_); |
593 } | 593 } |
594 | 594 |
595 | 595 |
596 class DeferredReferenceSetKeyedValue: public DeferredCode { | 596 class DeferredReferenceSetKeyedValue: public DeferredCode { |
597 public: | 597 public: |
598 DeferredReferenceSetKeyedValue(Register value, | 598 DeferredReferenceSetKeyedValue(Register value, |
599 Register key, | 599 Register key, |
600 Register receiver) | 600 Register receiver) |
601 : value_(value), key_(key), receiver_(receiver) { | 601 : value_(value), key_(key), receiver_(receiver) { |
602 set_comment("[ DeferredReferenceSetKeyedValue"); | 602 set_comment("[ DeferredReferenceSetKeyedValue"); |
603 } | 603 } |
604 | 604 |
605 virtual void Generate(); | 605 virtual void Generate(); |
606 | 606 |
607 Label* patch_site() { return &patch_site_; } | 607 Label* patch_site() { return &patch_site_; } |
608 | 608 |
609 private: | 609 private: |
610 Register value_; | 610 Register value_; |
611 Register key_; | 611 Register key_; |
612 Register receiver_; | 612 Register receiver_; |
613 Label patch_site_; | 613 Label patch_site_; |
614 }; | 614 }; |
615 | 615 |
616 | 616 |
617 void DeferredReferenceSetKeyedValue::Generate() { | 617 void DeferredReferenceSetKeyedValue::Generate() { |
618 __ IncrementCounter(&Counters::keyed_store_inline_miss, 1); | 618 __ IncrementCounter(&COUNTER(keyed_store_inline_miss), 1); |
619 // Push receiver and key arguments on the stack. | 619 // Push receiver and key arguments on the stack. |
620 __ push(receiver_); | 620 __ push(receiver_); |
621 __ push(key_); | 621 __ push(key_); |
622 // Move value argument to eax as expected by the IC stub. | 622 // Move value argument to eax as expected by the IC stub. |
623 if (!value_.is(rax)) __ movq(rax, value_); | 623 if (!value_.is(rax)) __ movq(rax, value_); |
624 // Call the IC stub. | 624 // Call the IC stub. |
625 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 625 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
626 __ Call(ic, RelocInfo::CODE_TARGET); | 626 __ Call(ic, RelocInfo::CODE_TARGET); |
627 // The delta from the start of the map-compare instructions (initial movq) | 627 // The delta from the start of the map-compare instructions (initial movq) |
628 // to the test instruction. We use masm_-> directly here instead of the | 628 // to the test instruction. We use masm_-> directly here instead of the |
(...skipping 4637 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5266 // The call must be followed by a test rax instruction to indicate | 5266 // The call must be followed by a test rax instruction to indicate |
5267 // that the inobject property case was inlined. | 5267 // that the inobject property case was inlined. |
5268 // | 5268 // |
5269 // Store the delta to the map check instruction here in the test | 5269 // Store the delta to the map check instruction here in the test |
5270 // instruction. Use masm_-> instead of the __ macro since the | 5270 // instruction. Use masm_-> instead of the __ macro since the |
5271 // latter can't return a value. | 5271 // latter can't return a value. |
5272 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(patch_site()); | 5272 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(patch_site()); |
5273 // Here we use masm_-> instead of the __ macro because this is the | 5273 // Here we use masm_-> instead of the __ macro because this is the |
5274 // instruction that gets patched and coverage code gets in the way. | 5274 // instruction that gets patched and coverage code gets in the way. |
5275 masm_->testl(rax, Immediate(-delta_to_patch_site)); | 5275 masm_->testl(rax, Immediate(-delta_to_patch_site)); |
5276 __ IncrementCounter(&Counters::named_load_inline_miss, 1); | 5276 __ IncrementCounter(&COUNTER(named_load_inline_miss), 1); |
5277 | 5277 |
5278 if (!dst_.is(rax)) __ movq(dst_, rax); | 5278 if (!dst_.is(rax)) __ movq(dst_, rax); |
5279 __ pop(receiver_); | 5279 __ pop(receiver_); |
5280 } | 5280 } |
5281 | 5281 |
5282 | 5282 |
5283 void DeferredInlineSmiAdd::Generate() { | 5283 void DeferredInlineSmiAdd::Generate() { |
5284 GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, NO_SMI_CODE_IN_STUB); | 5284 GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, NO_SMI_CODE_IN_STUB); |
5285 igostub.GenerateCall(masm_, dst_, value_); | 5285 igostub.GenerateCall(masm_, dst_, value_); |
5286 if (!dst_.is(rax)) __ movq(dst_, rax); | 5286 if (!dst_.is(rax)) __ movq(dst_, rax); |
(...skipping 610 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5897 // The delta from the patch label to the load offset must be | 5897 // The delta from the patch label to the load offset must be |
5898 // statically known. | 5898 // statically known. |
5899 ASSERT(masm->SizeOfCodeGeneratedSince(deferred->patch_site()) == | 5899 ASSERT(masm->SizeOfCodeGeneratedSince(deferred->patch_site()) == |
5900 LoadIC::kOffsetToLoadInstruction); | 5900 LoadIC::kOffsetToLoadInstruction); |
5901 // The initial (invalid) offset has to be large enough to force | 5901 // The initial (invalid) offset has to be large enough to force |
5902 // a 32-bit instruction encoding to allow patching with an | 5902 // a 32-bit instruction encoding to allow patching with an |
5903 // arbitrary offset. Use kMaxInt (minus kHeapObjectTag). | 5903 // arbitrary offset. Use kMaxInt (minus kHeapObjectTag). |
5904 int offset = kMaxInt; | 5904 int offset = kMaxInt; |
5905 masm->movq(value.reg(), FieldOperand(receiver.reg(), offset)); | 5905 masm->movq(value.reg(), FieldOperand(receiver.reg(), offset)); |
5906 | 5906 |
5907 __ IncrementCounter(&Counters::named_load_inline, 1); | 5907 __ IncrementCounter(&COUNTER(named_load_inline), 1); |
5908 deferred->BindExit(); | 5908 deferred->BindExit(); |
5909 cgen_->frame()->Push(&receiver); | 5909 cgen_->frame()->Push(&receiver); |
5910 cgen_->frame()->Push(&value); | 5910 cgen_->frame()->Push(&value); |
5911 } | 5911 } |
5912 break; | 5912 break; |
5913 } | 5913 } |
5914 | 5914 |
5915 case KEYED: { | 5915 case KEYED: { |
5916 Comment cmnt(masm, "[ Load from keyed Property"); | 5916 Comment cmnt(masm, "[ Load from keyed Property"); |
5917 Variable* var = expression_->AsVariableProxy()->AsVariable(); | 5917 Variable* var = expression_->AsVariableProxy()->AsVariable(); |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5995 Result value = index; | 5995 Result value = index; |
5996 __ movq(value.reg(), | 5996 __ movq(value.reg(), |
5997 Operand(elements.reg(), | 5997 Operand(elements.reg(), |
5998 index.reg(), | 5998 index.reg(), |
5999 times_pointer_size, | 5999 times_pointer_size, |
6000 FixedArray::kHeaderSize - kHeapObjectTag)); | 6000 FixedArray::kHeaderSize - kHeapObjectTag)); |
6001 elements.Unuse(); | 6001 elements.Unuse(); |
6002 index.Unuse(); | 6002 index.Unuse(); |
6003 __ CompareRoot(value.reg(), Heap::kTheHoleValueRootIndex); | 6003 __ CompareRoot(value.reg(), Heap::kTheHoleValueRootIndex); |
6004 deferred->Branch(equal); | 6004 deferred->Branch(equal); |
6005 __ IncrementCounter(&Counters::keyed_load_inline, 1); | 6005 __ IncrementCounter(&COUNTER(keyed_load_inline), 1); |
6006 | 6006 |
6007 deferred->BindExit(); | 6007 deferred->BindExit(); |
6008 // Restore the receiver and key to the frame and push the | 6008 // Restore the receiver and key to the frame and push the |
6009 // result on top of it. | 6009 // result on top of it. |
6010 cgen_->frame()->Push(&receiver); | 6010 cgen_->frame()->Push(&receiver); |
6011 cgen_->frame()->Push(&key); | 6011 cgen_->frame()->Push(&key); |
6012 cgen_->frame()->Push(&value); | 6012 cgen_->frame()->Push(&value); |
6013 | 6013 |
6014 } else { | 6014 } else { |
6015 Comment cmnt(masm, "[ Load from keyed Property"); | 6015 Comment cmnt(masm, "[ Load from keyed Property"); |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6166 deferred->Branch(not_equal); | 6166 deferred->Branch(not_equal); |
6167 | 6167 |
6168 // Store the value. | 6168 // Store the value. |
6169 SmiIndex index = | 6169 SmiIndex index = |
6170 masm->SmiToIndex(kScratchRegister, key.reg(), kPointerSizeLog2); | 6170 masm->SmiToIndex(kScratchRegister, key.reg(), kPointerSizeLog2); |
6171 __ movq(Operand(tmp.reg(), | 6171 __ movq(Operand(tmp.reg(), |
6172 index.reg, | 6172 index.reg, |
6173 index.scale, | 6173 index.scale, |
6174 FixedArray::kHeaderSize - kHeapObjectTag), | 6174 FixedArray::kHeaderSize - kHeapObjectTag), |
6175 value.reg()); | 6175 value.reg()); |
6176 __ IncrementCounter(&Counters::keyed_store_inline, 1); | 6176 __ IncrementCounter(&COUNTER(keyed_store_inline), 1); |
6177 | 6177 |
6178 deferred->BindExit(); | 6178 deferred->BindExit(); |
6179 | 6179 |
6180 cgen_->frame()->Push(&receiver); | 6180 cgen_->frame()->Push(&receiver); |
6181 cgen_->frame()->Push(&key); | 6181 cgen_->frame()->Push(&key); |
6182 cgen_->frame()->Push(&value); | 6182 cgen_->frame()->Push(&value); |
6183 } else { | 6183 } else { |
6184 Result answer = cgen_->frame()->CallKeyedStoreIC(); | 6184 Result answer = cgen_->frame()->CallKeyedStoreIC(); |
6185 // Make sure that we do not have a test instruction after the | 6185 // Make sure that we do not have a test instruction after the |
6186 // call. A test instruction after the call is used to | 6186 // call. A test instruction after the call is used to |
(...skipping 1243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7430 __ movq(left_arg, left); | 7430 __ movq(left_arg, left); |
7431 } else { | 7431 } else { |
7432 // Order of moves is not important. | 7432 // Order of moves is not important. |
7433 __ movq(left_arg, left); | 7433 __ movq(left_arg, left); |
7434 __ movq(right_arg, right); | 7434 __ movq(right_arg, right); |
7435 } | 7435 } |
7436 } | 7436 } |
7437 | 7437 |
7438 // Update flags to indicate that arguments are in registers. | 7438 // Update flags to indicate that arguments are in registers. |
7439 SetArgsInRegisters(); | 7439 SetArgsInRegisters(); |
7440 __ IncrementCounter(&Counters::generic_binary_stub_calls_regs, 1); | 7440 __ IncrementCounter(&COUNTER(generic_binary_stub_calls_regs), 1); |
7441 } | 7441 } |
7442 | 7442 |
7443 // Call the stub. | 7443 // Call the stub. |
7444 __ CallStub(this); | 7444 __ CallStub(this); |
7445 } | 7445 } |
7446 | 7446 |
7447 | 7447 |
7448 void GenericBinaryOpStub::GenerateCall( | 7448 void GenericBinaryOpStub::GenerateCall( |
7449 MacroAssembler* masm, | 7449 MacroAssembler* masm, |
7450 Register left, | 7450 Register left, |
(...skipping 11 matching lines...) Expand all Loading... |
7462 } else if (left.is(right_arg) && IsOperationCommutative()) { | 7462 } else if (left.is(right_arg) && IsOperationCommutative()) { |
7463 __ Move(left_arg, right); | 7463 __ Move(left_arg, right); |
7464 SetArgsReversed(); | 7464 SetArgsReversed(); |
7465 } else { | 7465 } else { |
7466 __ movq(left_arg, left); | 7466 __ movq(left_arg, left); |
7467 __ Move(right_arg, right); | 7467 __ Move(right_arg, right); |
7468 } | 7468 } |
7469 | 7469 |
7470 // Update flags to indicate that arguments are in registers. | 7470 // Update flags to indicate that arguments are in registers. |
7471 SetArgsInRegisters(); | 7471 SetArgsInRegisters(); |
7472 __ IncrementCounter(&Counters::generic_binary_stub_calls_regs, 1); | 7472 __ IncrementCounter(&COUNTER(generic_binary_stub_calls_regs), 1); |
7473 } | 7473 } |
7474 | 7474 |
7475 // Call the stub. | 7475 // Call the stub. |
7476 __ CallStub(this); | 7476 __ CallStub(this); |
7477 } | 7477 } |
7478 | 7478 |
7479 | 7479 |
7480 void GenericBinaryOpStub::GenerateCall( | 7480 void GenericBinaryOpStub::GenerateCall( |
7481 MacroAssembler* masm, | 7481 MacroAssembler* masm, |
7482 Smi* left, | 7482 Smi* left, |
(...skipping 10 matching lines...) Expand all Loading... |
7493 __ Move(left_arg, left); | 7493 __ Move(left_arg, left); |
7494 } else if (right.is(left_arg) && IsOperationCommutative()) { | 7494 } else if (right.is(left_arg) && IsOperationCommutative()) { |
7495 __ Move(right_arg, left); | 7495 __ Move(right_arg, left); |
7496 SetArgsReversed(); | 7496 SetArgsReversed(); |
7497 } else { | 7497 } else { |
7498 __ Move(left_arg, left); | 7498 __ Move(left_arg, left); |
7499 __ movq(right_arg, right); | 7499 __ movq(right_arg, right); |
7500 } | 7500 } |
7501 // Update flags to indicate that arguments are in registers. | 7501 // Update flags to indicate that arguments are in registers. |
7502 SetArgsInRegisters(); | 7502 SetArgsInRegisters(); |
7503 __ IncrementCounter(&Counters::generic_binary_stub_calls_regs, 1); | 7503 __ IncrementCounter(&COUNTER(generic_binary_stub_calls_regs), 1); |
7504 } | 7504 } |
7505 | 7505 |
7506 // Call the stub. | 7506 // Call the stub. |
7507 __ CallStub(this); | 7507 __ CallStub(this); |
7508 } | 7508 } |
7509 | 7509 |
7510 | 7510 |
7511 void GenericBinaryOpStub::GenerateSmiCode(MacroAssembler* masm, Label* slow) { | 7511 void GenericBinaryOpStub::GenerateSmiCode(MacroAssembler* masm, Label* slow) { |
7512 // Perform fast-case smi code for the operation (rax <op> rbx) and | 7512 // Perform fast-case smi code for the operation (rax <op> rbx) and |
7513 // leave result in register rax. | 7513 // leave result in register rax. |
(...skipping 455 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7969 masm.GetCode(&desc); | 7969 masm.GetCode(&desc); |
7970 // Call the function from C++. | 7970 // Call the function from C++. |
7971 return FUNCTION_CAST<ModuloFunction>(buffer); | 7971 return FUNCTION_CAST<ModuloFunction>(buffer); |
7972 } | 7972 } |
7973 | 7973 |
7974 #endif | 7974 #endif |
7975 | 7975 |
7976 #undef __ | 7976 #undef __ |
7977 | 7977 |
7978 } } // namespace v8::internal | 7978 } } // namespace v8::internal |
OLD | NEW |