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

Side by Side Diff: src/x64/codegen-x64.cc

Issue 6529032: Merge 6168:6800 from bleeding_edge to experimental/gc branch. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: Created 9 years, 10 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 | Annotate | Revision Log
« no previous file with comments | « src/x64/codegen-x64.h ('k') | src/x64/cpu-x64.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 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
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
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
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
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
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
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
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, &not_minus_half); 6992 __ j(not_equal, &not_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(&not_minus_half); 7004 __ bind(&not_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
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
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
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
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
OLDNEW
« no previous file with comments | « src/x64/codegen-x64.h ('k') | src/x64/cpu-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698