| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 613 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 624 : LAZY_ARGUMENTS_ALLOCATION; | 624 : LAZY_ARGUMENTS_ALLOCATION; |
| 625 } | 625 } |
| 626 | 626 |
| 627 | 627 |
| 628 Result CodeGenerator::StoreArgumentsObject(bool initial) { | 628 Result CodeGenerator::StoreArgumentsObject(bool initial) { |
| 629 ArgumentsAllocationMode mode = ArgumentsMode(); | 629 ArgumentsAllocationMode mode = ArgumentsMode(); |
| 630 ASSERT(mode != NO_ARGUMENTS_ALLOCATION); | 630 ASSERT(mode != NO_ARGUMENTS_ALLOCATION); |
| 631 | 631 |
| 632 Comment cmnt(masm_, "[ store arguments object"); | 632 Comment cmnt(masm_, "[ store arguments object"); |
| 633 if (mode == LAZY_ARGUMENTS_ALLOCATION && initial) { | 633 if (mode == LAZY_ARGUMENTS_ALLOCATION && initial) { |
| 634 // When using lazy arguments allocation, we store the hole value | 634 // When using lazy arguments allocation, we store the arguments marker value |
| 635 // as a sentinel indicating that the arguments object hasn't been | 635 // as a sentinel indicating that the arguments object hasn't been |
| 636 // allocated yet. | 636 // allocated yet. |
| 637 frame_->Push(Factory::the_hole_value()); | 637 frame_->Push(Factory::arguments_marker()); |
| 638 } else { | 638 } else { |
| 639 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT); | 639 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT); |
| 640 frame_->PushFunction(); | 640 frame_->PushFunction(); |
| 641 frame_->PushReceiverSlotAddress(); | 641 frame_->PushReceiverSlotAddress(); |
| 642 frame_->Push(Smi::FromInt(scope()->num_parameters())); | 642 frame_->Push(Smi::FromInt(scope()->num_parameters())); |
| 643 Result result = frame_->CallStub(&stub, 3); | 643 Result result = frame_->CallStub(&stub, 3); |
| 644 frame_->Push(&result); | 644 frame_->Push(&result); |
| 645 } | 645 } |
| 646 | 646 |
| 647 Variable* arguments = scope()->arguments(); | 647 Variable* arguments = scope()->arguments(); |
| 648 Variable* shadow = scope()->arguments_shadow(); | 648 Variable* shadow = scope()->arguments_shadow(); |
| 649 ASSERT(arguments != NULL && arguments->AsSlot() != NULL); | 649 ASSERT(arguments != NULL && arguments->AsSlot() != NULL); |
| 650 ASSERT(shadow != NULL && shadow->AsSlot() != NULL); | 650 ASSERT(shadow != NULL && shadow->AsSlot() != NULL); |
| 651 JumpTarget done; | 651 JumpTarget done; |
| 652 bool skip_arguments = false; | 652 bool skip_arguments = false; |
| 653 if (mode == LAZY_ARGUMENTS_ALLOCATION && !initial) { | 653 if (mode == LAZY_ARGUMENTS_ALLOCATION && !initial) { |
| 654 // We have to skip storing into the arguments slot if it has | 654 // We have to skip storing into the arguments slot if it has |
| 655 // already been written to. This can happen if the a function | 655 // already been written to. This can happen if the a function |
| 656 // has a local variable named 'arguments'. | 656 // has a local variable named 'arguments'. |
| 657 LoadFromSlot(arguments->AsSlot(), NOT_INSIDE_TYPEOF); | 657 LoadFromSlot(arguments->AsSlot(), NOT_INSIDE_TYPEOF); |
| 658 Result probe = frame_->Pop(); | 658 Result probe = frame_->Pop(); |
| 659 if (probe.is_constant()) { | 659 if (probe.is_constant()) { |
| 660 // We have to skip updating the arguments object if it has | 660 // We have to skip updating the arguments object if it has |
| 661 // been assigned a proper value. | 661 // been assigned a proper value. |
| 662 skip_arguments = !probe.handle()->IsTheHole(); | 662 skip_arguments = !probe.handle()->IsArgumentsMarker(); |
| 663 } else { | 663 } else { |
| 664 __ CompareRoot(probe.reg(), Heap::kTheHoleValueRootIndex); | 664 __ CompareRoot(probe.reg(), Heap::kArgumentsMarkerRootIndex); |
| 665 probe.Unuse(); | 665 probe.Unuse(); |
| 666 done.Branch(not_equal); | 666 done.Branch(not_equal); |
| 667 } | 667 } |
| 668 } | 668 } |
| 669 if (!skip_arguments) { | 669 if (!skip_arguments) { |
| 670 StoreToSlot(arguments->AsSlot(), NOT_CONST_INIT); | 670 StoreToSlot(arguments->AsSlot(), NOT_CONST_INIT); |
| 671 if (mode == LAZY_ARGUMENTS_ALLOCATION) done.Bind(); | 671 if (mode == LAZY_ARGUMENTS_ALLOCATION) done.Bind(); |
| 672 } | 672 } |
| 673 StoreToSlot(shadow->AsSlot(), NOT_CONST_INIT); | 673 StoreToSlot(shadow->AsSlot(), NOT_CONST_INIT); |
| 674 return frame_->Pop(); | 674 return frame_->Pop(); |
| (...skipping 1838 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2513 // Check if the arguments object has been lazily allocated | 2513 // Check if the arguments object has been lazily allocated |
| 2514 // already. If so, just use that instead of copying the arguments | 2514 // already. If so, just use that instead of copying the arguments |
| 2515 // from the stack. This also deals with cases where a local variable | 2515 // from the stack. This also deals with cases where a local variable |
| 2516 // named 'arguments' has been introduced. | 2516 // named 'arguments' has been introduced. |
| 2517 frame_->Dup(); | 2517 frame_->Dup(); |
| 2518 Result probe = frame_->Pop(); | 2518 Result probe = frame_->Pop(); |
| 2519 { VirtualFrame::SpilledScope spilled_scope; | 2519 { VirtualFrame::SpilledScope spilled_scope; |
| 2520 Label slow, done; | 2520 Label slow, done; |
| 2521 bool try_lazy = true; | 2521 bool try_lazy = true; |
| 2522 if (probe.is_constant()) { | 2522 if (probe.is_constant()) { |
| 2523 try_lazy = probe.handle()->IsTheHole(); | 2523 try_lazy = probe.handle()->IsArgumentsMarker(); |
| 2524 } else { | 2524 } else { |
| 2525 __ CompareRoot(probe.reg(), Heap::kTheHoleValueRootIndex); | 2525 __ CompareRoot(probe.reg(), Heap::kArgumentsMarkerRootIndex); |
| 2526 probe.Unuse(); | 2526 probe.Unuse(); |
| 2527 __ j(not_equal, &slow); | 2527 __ j(not_equal, &slow); |
| 2528 } | 2528 } |
| 2529 | 2529 |
| 2530 if (try_lazy) { | 2530 if (try_lazy) { |
| 2531 Label build_args; | 2531 Label build_args; |
| 2532 // Get rid of the arguments object probe. | 2532 // Get rid of the arguments object probe. |
| 2533 frame_->Drop(); // Can be called on a spilled frame. | 2533 frame_->Drop(); // Can be called on a spilled frame. |
| 2534 // Stack now has 3 elements on it. | 2534 // Stack now has 3 elements on it. |
| 2535 // Contents of stack at this point: | 2535 // Contents of stack at this point: |
| (...skipping 454 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2990 | 2990 |
| 2991 // Add a label for checking the size of the code used for returning. | 2991 // Add a label for checking the size of the code used for returning. |
| 2992 #ifdef DEBUG | 2992 #ifdef DEBUG |
| 2993 Label check_exit_codesize; | 2993 Label check_exit_codesize; |
| 2994 masm_->bind(&check_exit_codesize); | 2994 masm_->bind(&check_exit_codesize); |
| 2995 #endif | 2995 #endif |
| 2996 | 2996 |
| 2997 // Leave the frame and return popping the arguments and the | 2997 // Leave the frame and return popping the arguments and the |
| 2998 // receiver. | 2998 // receiver. |
| 2999 frame_->Exit(); | 2999 frame_->Exit(); |
| 3000 masm_->ret((scope()->num_parameters() + 1) * kPointerSize); | 3000 int arguments_bytes = (scope()->num_parameters() + 1) * kPointerSize; |
| 3001 __ Ret(arguments_bytes, rcx); |
| 3001 DeleteFrame(); | 3002 DeleteFrame(); |
| 3002 | 3003 |
| 3003 #ifdef ENABLE_DEBUGGER_SUPPORT | 3004 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 3004 // Add padding that will be overwritten by a debugger breakpoint. | 3005 // Add padding that will be overwritten by a debugger breakpoint. |
| 3005 // frame_->Exit() generates "movq rsp, rbp; pop rbp; ret k" | 3006 // The shortest return sequence generated is "movq rsp, rbp; pop rbp; ret k" |
| 3006 // with length 7 (3 + 1 + 3). | 3007 // with length 7 (3 + 1 + 3). |
| 3007 const int kPadding = Assembler::kJSReturnSequenceLength - 7; | 3008 const int kPadding = Assembler::kJSReturnSequenceLength - 7; |
| 3008 for (int i = 0; i < kPadding; ++i) { | 3009 for (int i = 0; i < kPadding; ++i) { |
| 3009 masm_->int3(); | 3010 masm_->int3(); |
| 3010 } | 3011 } |
| 3011 // Check that the size of the code used for returning matches what is | 3012 // Check that the size of the code used for returning is large enough |
| 3012 // expected by the debugger. | 3013 // for the debugger's requirements. |
| 3013 ASSERT_EQ(Assembler::kJSReturnSequenceLength, | 3014 ASSERT(Assembler::kJSReturnSequenceLength <= |
| 3014 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); | 3015 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); |
| 3015 #endif | 3016 #endif |
| 3016 } | 3017 } |
| 3017 | 3018 |
| 3018 | 3019 |
| 3019 void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) { | 3020 void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) { |
| 3020 ASSERT(!in_spilled_code()); | 3021 ASSERT(!in_spilled_code()); |
| 3021 Comment cmnt(masm_, "[ WithEnterStatement"); | 3022 Comment cmnt(masm_, "[ WithEnterStatement"); |
| 3022 CodeForStatementPosition(node); | 3023 CodeForStatementPosition(node); |
| 3023 Load(node->expression()); | 3024 Load(node->expression()); |
| 3024 Result context; | 3025 Result context; |
| (...skipping 1389 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4414 | 4415 |
| 4415 // ... or if the slot isn't a non-parameter arguments slot. | 4416 // ... or if the slot isn't a non-parameter arguments slot. |
| 4416 if (slot->type() == Slot::PARAMETER || !slot->is_arguments()) return; | 4417 if (slot->type() == Slot::PARAMETER || !slot->is_arguments()) return; |
| 4417 | 4418 |
| 4418 // Pop the loaded value from the stack. | 4419 // Pop the loaded value from the stack. |
| 4419 Result value = frame_->Pop(); | 4420 Result value = frame_->Pop(); |
| 4420 | 4421 |
| 4421 // If the loaded value is a constant, we know if the arguments | 4422 // If the loaded value is a constant, we know if the arguments |
| 4422 // object has been lazily loaded yet. | 4423 // object has been lazily loaded yet. |
| 4423 if (value.is_constant()) { | 4424 if (value.is_constant()) { |
| 4424 if (value.handle()->IsTheHole()) { | 4425 if (value.handle()->IsArgumentsMarker()) { |
| 4425 Result arguments = StoreArgumentsObject(false); | 4426 Result arguments = StoreArgumentsObject(false); |
| 4426 frame_->Push(&arguments); | 4427 frame_->Push(&arguments); |
| 4427 } else { | 4428 } else { |
| 4428 frame_->Push(&value); | 4429 frame_->Push(&value); |
| 4429 } | 4430 } |
| 4430 return; | 4431 return; |
| 4431 } | 4432 } |
| 4432 | 4433 |
| 4433 // The loaded value is in a register. If it is the sentinel that | 4434 // The loaded value is in a register. If it is the sentinel that |
| 4434 // indicates that we haven't loaded the arguments object yet, we | 4435 // indicates that we haven't loaded the arguments object yet, we |
| 4435 // need to do it now. | 4436 // need to do it now. |
| 4436 JumpTarget exit; | 4437 JumpTarget exit; |
| 4437 __ CompareRoot(value.reg(), Heap::kTheHoleValueRootIndex); | 4438 __ CompareRoot(value.reg(), Heap::kArgumentsMarkerRootIndex); |
| 4438 frame_->Push(&value); | 4439 frame_->Push(&value); |
| 4439 exit.Branch(not_equal); | 4440 exit.Branch(not_equal); |
| 4440 Result arguments = StoreArgumentsObject(false); | 4441 Result arguments = StoreArgumentsObject(false); |
| 4441 frame_->SetElementAt(0, &arguments); | 4442 frame_->SetElementAt(0, &arguments); |
| 4442 exit.Bind(); | 4443 exit.Bind(); |
| 4443 } | 4444 } |
| 4444 | 4445 |
| 4445 | 4446 |
| 4446 Result CodeGenerator::LoadFromGlobalSlotCheckExtensions( | 4447 Result CodeGenerator::LoadFromGlobalSlotCheckExtensions( |
| 4447 Slot* slot, | 4448 Slot* slot, |
| (...skipping 446 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4894 if (CompileTimeValue::IsCompileTimeValue(property->value())) break; | 4895 if (CompileTimeValue::IsCompileTimeValue(property->value())) break; |
| 4895 // else fall through. | 4896 // else fall through. |
| 4896 case ObjectLiteral::Property::COMPUTED: { | 4897 case ObjectLiteral::Property::COMPUTED: { |
| 4897 Handle<Object> key(property->key()->handle()); | 4898 Handle<Object> key(property->key()->handle()); |
| 4898 if (key->IsSymbol()) { | 4899 if (key->IsSymbol()) { |
| 4899 // Duplicate the object as the IC receiver. | 4900 // Duplicate the object as the IC receiver. |
| 4900 frame_->Dup(); | 4901 frame_->Dup(); |
| 4901 Load(property->value()); | 4902 Load(property->value()); |
| 4902 if (property->emit_store()) { | 4903 if (property->emit_store()) { |
| 4903 Result ignored = | 4904 Result ignored = |
| 4904 frame_->CallStoreIC(Handle<String>::cast(key), false); | 4905 frame_->CallStoreIC(Handle<String>::cast(key), false, |
| 4906 strict_mode_flag()); |
| 4905 // A test rax instruction following the store IC call would | 4907 // A test rax instruction following the store IC call would |
| 4906 // indicate the presence of an inlined version of the | 4908 // indicate the presence of an inlined version of the |
| 4907 // store. Add a nop to indicate that there is no such | 4909 // store. Add a nop to indicate that there is no such |
| 4908 // inlined version. | 4910 // inlined version. |
| 4909 __ nop(); | 4911 __ nop(); |
| 4910 } else { | 4912 } else { |
| 4911 frame_->Drop(2); | 4913 frame_->Drop(2); |
| 4912 } | 4914 } |
| 4913 break; | 4915 break; |
| 4914 } | 4916 } |
| (...skipping 492 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5407 NOT_INSIDE_TYPEOF, | 5409 NOT_INSIDE_TYPEOF, |
| 5408 &slow); | 5410 &slow); |
| 5409 frame_->Push(&fun); | 5411 frame_->Push(&fun); |
| 5410 if (arg_count > 0) { | 5412 if (arg_count > 0) { |
| 5411 frame_->PushElementAt(arg_count); | 5413 frame_->PushElementAt(arg_count); |
| 5412 } else { | 5414 } else { |
| 5413 frame_->Push(Factory::undefined_value()); | 5415 frame_->Push(Factory::undefined_value()); |
| 5414 } | 5416 } |
| 5415 frame_->PushParameterAt(-1); | 5417 frame_->PushParameterAt(-1); |
| 5416 | 5418 |
| 5419 // Push the strict mode flag. |
| 5420 frame_->Push(Smi::FromInt(strict_mode_flag())); |
| 5421 |
| 5417 // Resolve the call. | 5422 // Resolve the call. |
| 5418 result = | 5423 result = |
| 5419 frame_->CallRuntime(Runtime::kResolvePossiblyDirectEvalNoLookup, 3); | 5424 frame_->CallRuntime(Runtime::kResolvePossiblyDirectEvalNoLookup, 4); |
| 5420 | 5425 |
| 5421 done.Jump(&result); | 5426 done.Jump(&result); |
| 5422 slow.Bind(); | 5427 slow.Bind(); |
| 5423 } | 5428 } |
| 5424 | 5429 |
| 5425 // Prepare the stack for the call to ResolvePossiblyDirectEval by | 5430 // Prepare the stack for the call to ResolvePossiblyDirectEval by |
| 5426 // pushing the loaded function, the first argument to the eval | 5431 // pushing the loaded function, the first argument to the eval |
| 5427 // call and the receiver. | 5432 // call and the receiver. |
| 5428 frame_->PushElementAt(arg_count + 1); | 5433 frame_->PushElementAt(arg_count + 1); |
| 5429 if (arg_count > 0) { | 5434 if (arg_count > 0) { |
| 5430 frame_->PushElementAt(arg_count); | 5435 frame_->PushElementAt(arg_count); |
| 5431 } else { | 5436 } else { |
| 5432 frame_->Push(Factory::undefined_value()); | 5437 frame_->Push(Factory::undefined_value()); |
| 5433 } | 5438 } |
| 5434 frame_->PushParameterAt(-1); | 5439 frame_->PushParameterAt(-1); |
| 5435 | 5440 |
| 5441 // Push the strict mode flag. |
| 5442 frame_->Push(Smi::FromInt(strict_mode_flag())); |
| 5443 |
| 5436 // Resolve the call. | 5444 // Resolve the call. |
| 5437 result = frame_->CallRuntime(Runtime::kResolvePossiblyDirectEval, 3); | 5445 result = frame_->CallRuntime(Runtime::kResolvePossiblyDirectEval, 4); |
| 5438 | 5446 |
| 5439 // If we generated fast-case code bind the jump-target where fast | 5447 // If we generated fast-case code bind the jump-target where fast |
| 5440 // and slow case merge. | 5448 // and slow case merge. |
| 5441 if (done.is_linked()) done.Bind(&result); | 5449 if (done.is_linked()) done.Bind(&result); |
| 5442 | 5450 |
| 5443 // The runtime call returns a pair of values in rax (function) and | 5451 // The runtime call returns a pair of values in rax (function) and |
| 5444 // rdx (receiver). Touch up the stack with the right values. | 5452 // rdx (receiver). Touch up the stack with the right values. |
| 5445 Result receiver = allocator_->Allocate(rdx); | 5453 Result receiver = allocator_->Allocate(rdx); |
| 5446 frame_->SetElementAt(arg_count + 1, &result); | 5454 frame_->SetElementAt(arg_count + 1, &result); |
| 5447 frame_->SetElementAt(arg_count, &receiver); | 5455 frame_->SetElementAt(arg_count, &receiver); |
| (...skipping 1529 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6977 // Test for -0.5. | 6985 // Test for -0.5. |
| 6978 // Load xmm2 with -0.5. | 6986 // Load xmm2 with -0.5. |
| 6979 __ movl(answer.reg(), Immediate(0xBF000000)); | 6987 __ movl(answer.reg(), Immediate(0xBF000000)); |
| 6980 __ movd(xmm2, answer.reg()); | 6988 __ movd(xmm2, answer.reg()); |
| 6981 __ cvtss2sd(xmm2, xmm2); | 6989 __ cvtss2sd(xmm2, xmm2); |
| 6982 // xmm2 now has -0.5. | 6990 // xmm2 now has -0.5. |
| 6983 __ ucomisd(xmm2, xmm1); | 6991 __ ucomisd(xmm2, xmm1); |
| 6984 __ j(not_equal, ¬_minus_half); | 6992 __ j(not_equal, ¬_minus_half); |
| 6985 | 6993 |
| 6986 // Calculates reciprocal of square root. | 6994 // Calculates reciprocal of square root. |
| 6987 // Note that 1/sqrt(x) = sqrt(1/x)) | 6995 // sqrtsd returns -0 when input is -0. ECMA spec requires +0. |
| 6988 __ divsd(xmm3, xmm0); | 6996 __ xorpd(xmm1, xmm1); |
| 6997 __ addsd(xmm1, xmm0); |
| 6998 __ sqrtsd(xmm1, xmm1); |
| 6999 __ divsd(xmm3, xmm1); |
| 6989 __ movsd(xmm1, xmm3); | 7000 __ movsd(xmm1, xmm3); |
| 6990 __ sqrtsd(xmm1, xmm1); | |
| 6991 __ jmp(&allocate_return); | 7001 __ jmp(&allocate_return); |
| 6992 | 7002 |
| 6993 // Test for 0.5. | 7003 // Test for 0.5. |
| 6994 __ bind(¬_minus_half); | 7004 __ bind(¬_minus_half); |
| 6995 // Load xmm2 with 0.5. | 7005 // Load xmm2 with 0.5. |
| 6996 // Since xmm3 is 1 and xmm2 is -0.5 this is simply xmm2 + xmm3. | 7006 // Since xmm3 is 1 and xmm2 is -0.5 this is simply xmm2 + xmm3. |
| 6997 __ addsd(xmm2, xmm3); | 7007 __ addsd(xmm2, xmm3); |
| 6998 // xmm2 now has 0.5. | 7008 // xmm2 now has 0.5. |
| 6999 __ ucomisd(xmm2, xmm1); | 7009 __ ucomisd(xmm2, xmm1); |
| 7000 call_runtime.Branch(not_equal); | 7010 call_runtime.Branch(not_equal); |
| 7001 | 7011 |
| 7002 // Calculates square root. | 7012 // Calculates square root. |
| 7003 __ movsd(xmm1, xmm0); | 7013 // sqrtsd returns -0 when input is -0. ECMA spec requires +0. |
| 7014 __ xorpd(xmm1, xmm1); |
| 7015 __ addsd(xmm1, xmm0); |
| 7004 __ sqrtsd(xmm1, xmm1); | 7016 __ sqrtsd(xmm1, xmm1); |
| 7005 | 7017 |
| 7006 JumpTarget done; | 7018 JumpTarget done; |
| 7007 Label failure, success; | 7019 Label failure, success; |
| 7008 __ bind(&allocate_return); | 7020 __ bind(&allocate_return); |
| 7009 // Make a copy of the frame to enable us to handle allocation | 7021 // Make a copy of the frame to enable us to handle allocation |
| 7010 // failure after the JumpTarget jump. | 7022 // failure after the JumpTarget jump. |
| 7011 VirtualFrame* clone = new VirtualFrame(frame()); | 7023 VirtualFrame* clone = new VirtualFrame(frame()); |
| 7012 __ AllocateHeapNumber(answer.reg(), exponent.reg(), &failure); | 7024 __ AllocateHeapNumber(answer.reg(), exponent.reg(), &failure); |
| 7013 __ movsd(FieldOperand(answer.reg(), HeapNumber::kValueOffset), xmm1); | 7025 __ movsd(FieldOperand(answer.reg(), HeapNumber::kValueOffset), xmm1); |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7226 destination()->Invert(); | 7238 destination()->Invert(); |
| 7227 LoadCondition(node->expression(), destination(), true); | 7239 LoadCondition(node->expression(), destination(), true); |
| 7228 // Swap the labels back. | 7240 // Swap the labels back. |
| 7229 destination()->Invert(); | 7241 destination()->Invert(); |
| 7230 | 7242 |
| 7231 } else if (op == Token::DELETE) { | 7243 } else if (op == Token::DELETE) { |
| 7232 Property* property = node->expression()->AsProperty(); | 7244 Property* property = node->expression()->AsProperty(); |
| 7233 if (property != NULL) { | 7245 if (property != NULL) { |
| 7234 Load(property->obj()); | 7246 Load(property->obj()); |
| 7235 Load(property->key()); | 7247 Load(property->key()); |
| 7236 Result answer = frame_->InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, 2); | 7248 frame_->Push(Smi::FromInt(strict_mode_flag())); |
| 7249 Result answer = frame_->InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, 3); |
| 7237 frame_->Push(&answer); | 7250 frame_->Push(&answer); |
| 7238 return; | 7251 return; |
| 7239 } | 7252 } |
| 7240 | 7253 |
| 7241 Variable* variable = node->expression()->AsVariableProxy()->AsVariable(); | 7254 Variable* variable = node->expression()->AsVariableProxy()->AsVariable(); |
| 7242 if (variable != NULL) { | 7255 if (variable != NULL) { |
| 7256 // Delete of an unqualified identifier is disallowed in strict mode |
| 7257 // so this code can only be reached in non-strict mode. |
| 7258 ASSERT(strict_mode_flag() == kNonStrictMode); |
| 7243 Slot* slot = variable->AsSlot(); | 7259 Slot* slot = variable->AsSlot(); |
| 7244 if (variable->is_global()) { | 7260 if (variable->is_global()) { |
| 7245 LoadGlobal(); | 7261 LoadGlobal(); |
| 7246 frame_->Push(variable->name()); | 7262 frame_->Push(variable->name()); |
| 7263 frame_->Push(Smi::FromInt(kNonStrictMode)); |
| 7247 Result answer = frame_->InvokeBuiltin(Builtins::DELETE, | 7264 Result answer = frame_->InvokeBuiltin(Builtins::DELETE, |
| 7248 CALL_FUNCTION, 2); | 7265 CALL_FUNCTION, 3); |
| 7249 frame_->Push(&answer); | 7266 frame_->Push(&answer); |
| 7250 return; | 7267 return; |
| 7251 | 7268 |
| 7252 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { | 7269 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { |
| 7253 // Call the runtime to look up the context holding the named | 7270 // Call the runtime to delete from the context holding the named |
| 7254 // variable. Sync the virtual frame eagerly so we can push the | 7271 // variable. Sync the virtual frame eagerly so we can push the |
| 7255 // arguments directly into place. | 7272 // arguments directly into place. |
| 7256 frame_->SyncRange(0, frame_->element_count() - 1); | 7273 frame_->SyncRange(0, frame_->element_count() - 1); |
| 7257 frame_->EmitPush(rsi); | 7274 frame_->EmitPush(rsi); |
| 7258 frame_->EmitPush(variable->name()); | 7275 frame_->EmitPush(variable->name()); |
| 7259 Result context = frame_->CallRuntime(Runtime::kLookupContext, 2); | 7276 Result answer = frame_->CallRuntime(Runtime::kDeleteContextSlot, 2); |
| 7260 ASSERT(context.is_register()); | |
| 7261 frame_->EmitPush(context.reg()); | |
| 7262 context.Unuse(); | |
| 7263 frame_->EmitPush(variable->name()); | |
| 7264 Result answer = frame_->InvokeBuiltin(Builtins::DELETE, | |
| 7265 CALL_FUNCTION, 2); | |
| 7266 frame_->Push(&answer); | 7277 frame_->Push(&answer); |
| 7267 return; | 7278 return; |
| 7268 } | 7279 } |
| 7269 | 7280 |
| 7270 // Default: Result of deleting non-global, not dynamically | 7281 // Default: Result of deleting non-global, not dynamically |
| 7271 // introduced variables is false. | 7282 // introduced variables is false. |
| 7272 frame_->Push(Factory::false_value()); | 7283 frame_->Push(Factory::false_value()); |
| 7273 | 7284 |
| 7274 } else { | 7285 } else { |
| 7275 // Default: Result of deleting expressions is true. | 7286 // Default: Result of deleting expressions is true. |
| (...skipping 961 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8237 } | 8248 } |
| 8238 | 8249 |
| 8239 | 8250 |
| 8240 Result CodeGenerator::EmitNamedStore(Handle<String> name, bool is_contextual) { | 8251 Result CodeGenerator::EmitNamedStore(Handle<String> name, bool is_contextual) { |
| 8241 #ifdef DEBUG | 8252 #ifdef DEBUG |
| 8242 int expected_height = frame()->height() - (is_contextual ? 1 : 2); | 8253 int expected_height = frame()->height() - (is_contextual ? 1 : 2); |
| 8243 #endif | 8254 #endif |
| 8244 | 8255 |
| 8245 Result result; | 8256 Result result; |
| 8246 if (is_contextual || scope()->is_global_scope() || loop_nesting() == 0) { | 8257 if (is_contextual || scope()->is_global_scope() || loop_nesting() == 0) { |
| 8247 result = frame()->CallStoreIC(name, is_contextual); | 8258 result = frame()->CallStoreIC(name, is_contextual, strict_mode_flag()); |
| 8248 // A test rax instruction following the call signals that the inobject | 8259 // A test rax instruction following the call signals that the inobject |
| 8249 // property case was inlined. Ensure that there is not a test rax | 8260 // property case was inlined. Ensure that there is not a test rax |
| 8250 // instruction here. | 8261 // instruction here. |
| 8251 __ nop(); | 8262 __ nop(); |
| 8252 } else { | 8263 } else { |
| 8253 // Inline the in-object property case. | 8264 // Inline the in-object property case. |
| 8254 JumpTarget slow, done; | 8265 JumpTarget slow, done; |
| 8255 Label patch_site; | 8266 Label patch_site; |
| 8256 | 8267 |
| 8257 // Get the value and receiver from the stack. | 8268 // Get the value and receiver from the stack. |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8340 } | 8351 } |
| 8341 __ bind(&skip_write_barrier); | 8352 __ bind(&skip_write_barrier); |
| 8342 value.Unuse(); | 8353 value.Unuse(); |
| 8343 scratch.Unuse(); | 8354 scratch.Unuse(); |
| 8344 receiver.Unuse(); | 8355 receiver.Unuse(); |
| 8345 done.Jump(&result); | 8356 done.Jump(&result); |
| 8346 | 8357 |
| 8347 slow.Bind(&value, &receiver); | 8358 slow.Bind(&value, &receiver); |
| 8348 frame()->Push(&receiver); | 8359 frame()->Push(&receiver); |
| 8349 frame()->Push(&value); | 8360 frame()->Push(&value); |
| 8350 result = frame()->CallStoreIC(name, is_contextual); | 8361 result = frame()->CallStoreIC(name, is_contextual, strict_mode_flag()); |
| 8351 // Encode the offset to the map check instruction and the offset | 8362 // Encode the offset to the map check instruction and the offset |
| 8352 // to the write barrier store address computation in a test rax | 8363 // to the write barrier store address computation in a test rax |
| 8353 // instruction. | 8364 // instruction. |
| 8354 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(&patch_site); | 8365 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(&patch_site); |
| 8355 __ testl(rax, | 8366 __ testl(rax, |
| 8356 Immediate((delta_to_record_write << 16) | delta_to_patch_site)); | 8367 Immediate((delta_to_record_write << 16) | delta_to_patch_site)); |
| 8357 done.Bind(&result); | 8368 done.Bind(&result); |
| 8358 } | 8369 } |
| 8359 | 8370 |
| 8360 ASSERT_EQ(expected_height, frame()->height()); | 8371 ASSERT_EQ(expected_height, frame()->height()); |
| (...skipping 462 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8823 } | 8834 } |
| 8824 | 8835 |
| 8825 #endif | 8836 #endif |
| 8826 | 8837 |
| 8827 | 8838 |
| 8828 #undef __ | 8839 #undef __ |
| 8829 | 8840 |
| 8830 } } // namespace v8::internal | 8841 } } // namespace v8::internal |
| 8831 | 8842 |
| 8832 #endif // V8_TARGET_ARCH_X64 | 8843 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |