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

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

Issue 7348008: Merge up to 8597 to experimental/gc from the bleeding edge. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: '' Created 9 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/x64/disasm-x64.cc ('k') | src/x64/ic-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 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 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
71 } 71 }
72 72
73 void EmitJumpIfSmi(Register reg, 73 void EmitJumpIfSmi(Register reg,
74 Label* target, 74 Label* target,
75 Label::Distance near_jump = Label::kFar) { 75 Label::Distance near_jump = Label::kFar) {
76 __ testb(reg, Immediate(kSmiTagMask)); 76 __ testb(reg, Immediate(kSmiTagMask));
77 EmitJump(carry, target, near_jump); // Never taken before patched. 77 EmitJump(carry, target, near_jump); // Never taken before patched.
78 } 78 }
79 79
80 void EmitPatchInfo() { 80 void EmitPatchInfo() {
81 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(&patch_site_); 81 if (patch_site_.is_bound()) {
82 ASSERT(is_int8(delta_to_patch_site)); 82 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(&patch_site_);
83 __ testl(rax, Immediate(delta_to_patch_site)); 83 ASSERT(is_int8(delta_to_patch_site));
84 __ testl(rax, Immediate(delta_to_patch_site));
84 #ifdef DEBUG 85 #ifdef DEBUG
85 info_emitted_ = true; 86 info_emitted_ = true;
86 #endif 87 #endif
88 } else {
89 __ nop(); // Signals no inlined code.
90 }
87 } 91 }
88 92
89 bool is_bound() const { return patch_site_.is_bound(); }
90
91 private: 93 private:
92 // jc will be patched with jz, jnc will become jnz. 94 // jc will be patched with jz, jnc will become jnz.
93 void EmitJump(Condition cc, Label* target, Label::Distance near_jump) { 95 void EmitJump(Condition cc, Label* target, Label::Distance near_jump) {
94 ASSERT(!patch_site_.is_bound() && !info_emitted_); 96 ASSERT(!patch_site_.is_bound() && !info_emitted_);
95 ASSERT(cc == carry || cc == not_carry); 97 ASSERT(cc == carry || cc == not_carry);
96 __ bind(&patch_site_); 98 __ bind(&patch_site_);
97 __ j(cc, target, near_jump); 99 __ j(cc, target, near_jump);
98 } 100 }
99 101
100 MacroAssembler* masm_; 102 MacroAssembler* masm_;
(...skipping 13 matching lines...) Expand all
114 // o rdi: the JS function object being called (ie, ourselves) 116 // o rdi: the JS function object being called (ie, ourselves)
115 // o rsi: our context 117 // o rsi: our context
116 // o rbp: our caller's frame pointer 118 // o rbp: our caller's frame pointer
117 // o rsp: stack pointer (pointing to return address) 119 // o rsp: stack pointer (pointing to return address)
118 // 120 //
119 // The function builds a JS frame. Please see JavaScriptFrameConstants in 121 // The function builds a JS frame. Please see JavaScriptFrameConstants in
120 // frames-x64.h for its layout. 122 // frames-x64.h for its layout.
121 void FullCodeGenerator::Generate(CompilationInfo* info) { 123 void FullCodeGenerator::Generate(CompilationInfo* info) {
122 ASSERT(info_ == NULL); 124 ASSERT(info_ == NULL);
123 info_ = info; 125 info_ = info;
126 scope_ = info->scope();
124 SetFunctionPosition(function()); 127 SetFunctionPosition(function());
125 Comment cmnt(masm_, "[ function compiled by full code generator"); 128 Comment cmnt(masm_, "[ function compiled by full code generator");
126 129
127 #ifdef DEBUG 130 #ifdef DEBUG
128 if (strlen(FLAG_stop_at) > 0 && 131 if (strlen(FLAG_stop_at) > 0 &&
129 info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { 132 info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
130 __ int3(); 133 __ int3();
131 } 134 }
132 #endif 135 #endif
133 136
134 // Strict mode functions need to replace the receiver with undefined 137 // Strict mode functions and builtins need to replace the receiver
135 // when called as functions (without an explicit receiver 138 // with undefined when called as functions (without an explicit
136 // object). rcx is zero for method calls and non-zero for function 139 // receiver object). rcx is zero for method calls and non-zero for
137 // calls. 140 // function calls.
138 if (info->is_strict_mode()) { 141 if (info->is_strict_mode() || info->is_native()) {
139 Label ok; 142 Label ok;
140 __ testq(rcx, rcx); 143 __ testq(rcx, rcx);
141 __ j(zero, &ok, Label::kNear); 144 __ j(zero, &ok, Label::kNear);
142 // +1 for return address. 145 // +1 for return address.
143 int receiver_offset = (scope()->num_parameters() + 1) * kPointerSize; 146 int receiver_offset = (info->scope()->num_parameters() + 1) * kPointerSize;
144 __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex); 147 __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex);
145 __ movq(Operand(rsp, receiver_offset), kScratchRegister); 148 __ movq(Operand(rsp, receiver_offset), kScratchRegister);
146 __ bind(&ok); 149 __ bind(&ok);
147 } 150 }
148 151
149 __ push(rbp); // Caller's frame pointer. 152 __ push(rbp); // Caller's frame pointer.
150 __ movq(rbp, rsp); 153 __ movq(rbp, rsp);
151 __ push(rsi); // Callee's context. 154 __ push(rsi); // Callee's context.
152 __ push(rdi); // Callee's JS Function. 155 __ push(rdi); // Callee's JS Function.
153 156
154 { Comment cmnt(masm_, "[ Allocate locals"); 157 { Comment cmnt(masm_, "[ Allocate locals");
155 int locals_count = scope()->num_stack_slots(); 158 int locals_count = info->scope()->num_stack_slots();
156 if (locals_count == 1) { 159 if (locals_count == 1) {
157 __ PushRoot(Heap::kUndefinedValueRootIndex); 160 __ PushRoot(Heap::kUndefinedValueRootIndex);
158 } else if (locals_count > 1) { 161 } else if (locals_count > 1) {
159 __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex); 162 __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex);
160 for (int i = 0; i < locals_count; i++) { 163 for (int i = 0; i < locals_count; i++) {
161 __ push(rdx); 164 __ push(rdx);
162 } 165 }
163 } 166 }
164 } 167 }
165 168
166 bool function_in_register = true; 169 bool function_in_register = true;
167 170
168 // Possibly allocate a local context. 171 // Possibly allocate a local context.
169 int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; 172 int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
170 if (heap_slots > 0) { 173 if (heap_slots > 0) {
171 Comment cmnt(masm_, "[ Allocate local context"); 174 Comment cmnt(masm_, "[ Allocate local context");
172 // Argument to NewContext is the function, which is still in rdi. 175 // Argument to NewContext is the function, which is still in rdi.
173 __ push(rdi); 176 __ push(rdi);
174 if (heap_slots <= FastNewContextStub::kMaximumSlots) { 177 if (heap_slots <= FastNewContextStub::kMaximumSlots) {
175 FastNewContextStub stub(heap_slots); 178 FastNewContextStub stub(heap_slots);
176 __ CallStub(&stub); 179 __ CallStub(&stub);
177 } else { 180 } else {
178 __ CallRuntime(Runtime::kNewContext, 1); 181 __ CallRuntime(Runtime::kNewFunctionContext, 1);
179 } 182 }
180 function_in_register = false; 183 function_in_register = false;
181 // Context is returned in both rax and rsi. It replaces the context 184 // Context is returned in both rax and rsi. It replaces the context
182 // passed to us. It's saved in the stack and kept live in rsi. 185 // passed to us. It's saved in the stack and kept live in rsi.
183 __ movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi); 186 __ movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi);
184 187
185 // Copy any necessary parameters into the context. 188 // Copy any necessary parameters into the context.
186 int num_parameters = scope()->num_parameters(); 189 int num_parameters = info->scope()->num_parameters();
187 for (int i = 0; i < num_parameters; i++) { 190 for (int i = 0; i < num_parameters; i++) {
188 Slot* slot = scope()->parameter(i)->AsSlot(); 191 Slot* slot = scope()->parameter(i)->AsSlot();
189 if (slot != NULL && slot->type() == Slot::CONTEXT) { 192 if (slot != NULL && slot->type() == Slot::CONTEXT) {
190 int parameter_offset = StandardFrameConstants::kCallerSPOffset + 193 int parameter_offset = StandardFrameConstants::kCallerSPOffset +
191 (num_parameters - 1 - i) * kPointerSize; 194 (num_parameters - 1 - i) * kPointerSize;
192 // Load parameter from stack. 195 // Load parameter from stack.
193 __ movq(rax, Operand(rbp, parameter_offset)); 196 __ movq(rax, Operand(rbp, parameter_offset));
194 // Store it in the context. 197 // Store it in the context.
195 int context_offset = Context::SlotOffset(slot->index()); 198 int context_offset = Context::SlotOffset(slot->index());
196 __ movq(Operand(rsi, context_offset), rax); 199 __ movq(Operand(rsi, context_offset), rax);
197 // Update the write barrier. This clobbers rax and rbx. 200 // Update the write barrier. This clobbers rax and rbx.
198 __ RecordWriteContextSlot( 201 __ RecordWriteContextSlot(
199 rsi, context_offset, rax, rbx, kDontSaveFPRegs); 202 rsi, context_offset, rax, rbx, kDontSaveFPRegs);
200 } 203 }
201 } 204 }
202 } 205 }
203 206
204 // Possibly allocate an arguments object. 207 // Possibly allocate an arguments object.
205 Variable* arguments = scope()->arguments(); 208 Variable* arguments = scope()->arguments();
206 if (arguments != NULL) { 209 if (arguments != NULL) {
207 // Arguments object must be allocated after the context object, in 210 // Arguments object must be allocated after the context object, in
208 // case the "arguments" or ".arguments" variables are in the context. 211 // case the "arguments" or ".arguments" variables are in the context.
209 Comment cmnt(masm_, "[ Allocate arguments object"); 212 Comment cmnt(masm_, "[ Allocate arguments object");
210 if (function_in_register) { 213 if (function_in_register) {
211 __ push(rdi); 214 __ push(rdi);
212 } else { 215 } else {
213 __ push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 216 __ push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
214 } 217 }
215 // The receiver is just before the parameters on the caller's stack. 218 // The receiver is just before the parameters on the caller's stack.
216 int offset = scope()->num_parameters() * kPointerSize; 219 int num_parameters = info->scope()->num_parameters();
220 int offset = num_parameters * kPointerSize;
217 __ lea(rdx, 221 __ lea(rdx,
218 Operand(rbp, StandardFrameConstants::kCallerSPOffset + offset)); 222 Operand(rbp, StandardFrameConstants::kCallerSPOffset + offset));
219 __ push(rdx); 223 __ push(rdx);
220 __ Push(Smi::FromInt(scope()->num_parameters())); 224 __ Push(Smi::FromInt(num_parameters));
221 // Arguments to ArgumentsAccessStub: 225 // Arguments to ArgumentsAccessStub:
222 // function, receiver address, parameter count. 226 // function, receiver address, parameter count.
223 // The stub will rewrite receiver and parameter count if the previous 227 // The stub will rewrite receiver and parameter count if the previous
224 // stack frame was an arguments adapter frame. 228 // stack frame was an arguments adapter frame.
225 ArgumentsAccessStub stub( 229 ArgumentsAccessStub stub(
226 is_strict_mode() ? ArgumentsAccessStub::NEW_STRICT 230 is_strict_mode() ? ArgumentsAccessStub::NEW_STRICT
227 : ArgumentsAccessStub::NEW_NON_STRICT); 231 : ArgumentsAccessStub::NEW_NON_STRICT_SLOW);
228 __ CallStub(&stub); 232 __ CallStub(&stub);
229 233
230 Variable* arguments_shadow = scope()->arguments_shadow();
231 if (arguments_shadow != NULL) {
232 // Store new arguments object in both "arguments" and ".arguments" slots.
233 __ movq(rcx, rax);
234 Move(arguments_shadow->AsSlot(), rcx, rbx, rdx);
235 }
236 Move(arguments->AsSlot(), rax, rbx, rdx); 234 Move(arguments->AsSlot(), rax, rbx, rdx);
237 } 235 }
238 236
239 if (FLAG_trace) { 237 if (FLAG_trace) {
240 __ CallRuntime(Runtime::kTraceEnter, 0); 238 __ CallRuntime(Runtime::kTraceEnter, 0);
241 } 239 }
242 240
243 // Visit the declarations and body unless there is an illegal 241 // Visit the declarations and body unless there is an illegal
244 // redeclaration. 242 // redeclaration.
245 if (scope()->HasIllegalRedeclaration()) { 243 if (scope()->HasIllegalRedeclaration()) {
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
329 Label check_exit_codesize; 327 Label check_exit_codesize;
330 masm_->bind(&check_exit_codesize); 328 masm_->bind(&check_exit_codesize);
331 #endif 329 #endif
332 CodeGenerator::RecordPositions(masm_, function()->end_position() - 1); 330 CodeGenerator::RecordPositions(masm_, function()->end_position() - 1);
333 __ RecordJSReturn(); 331 __ RecordJSReturn();
334 // Do not use the leave instruction here because it is too short to 332 // Do not use the leave instruction here because it is too short to
335 // patch with the code required by the debugger. 333 // patch with the code required by the debugger.
336 __ movq(rsp, rbp); 334 __ movq(rsp, rbp);
337 __ pop(rbp); 335 __ pop(rbp);
338 336
339 int arguments_bytes = (scope()->num_parameters() + 1) * kPointerSize; 337 int arguments_bytes = (info_->scope()->num_parameters() + 1) * kPointerSize;
340 __ Ret(arguments_bytes, rcx); 338 __ Ret(arguments_bytes, rcx);
341 339
342 #ifdef ENABLE_DEBUGGER_SUPPORT 340 #ifdef ENABLE_DEBUGGER_SUPPORT
343 // Add padding that will be overwritten by a debugger breakpoint. We 341 // Add padding that will be overwritten by a debugger breakpoint. We
344 // have just generated at least 7 bytes: "movq rsp, rbp; pop rbp; ret k" 342 // have just generated at least 7 bytes: "movq rsp, rbp; pop rbp; ret k"
345 // (3 + 1 + 3). 343 // (3 + 1 + 3).
346 const int kPadding = Assembler::kJSReturnSequenceLength - 7; 344 const int kPadding = Assembler::kJSReturnSequenceLength - 7;
347 for (int i = 0; i < kPadding; ++i) { 345 for (int i = 0; i < kPadding; ++i) {
348 masm_->int3(); 346 masm_->int3();
349 } 347 }
(...skipping 18 matching lines...) Expand all
368 366
369 void FullCodeGenerator::StackValueContext::Plug(Slot* slot) const { 367 void FullCodeGenerator::StackValueContext::Plug(Slot* slot) const {
370 MemOperand slot_operand = codegen()->EmitSlotSearch(slot, result_register()); 368 MemOperand slot_operand = codegen()->EmitSlotSearch(slot, result_register());
371 __ push(slot_operand); 369 __ push(slot_operand);
372 } 370 }
373 371
374 372
375 void FullCodeGenerator::TestContext::Plug(Slot* slot) const { 373 void FullCodeGenerator::TestContext::Plug(Slot* slot) const {
376 codegen()->Move(result_register(), slot); 374 codegen()->Move(result_register(), slot);
377 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); 375 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
378 codegen()->DoTest(true_label_, false_label_, fall_through_); 376 codegen()->DoTest(this);
379 } 377 }
380 378
381 379
382 void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const { 380 void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const {
383 } 381 }
384 382
385 383
386 void FullCodeGenerator::AccumulatorValueContext::Plug( 384 void FullCodeGenerator::AccumulatorValueContext::Plug(
387 Heap::RootListIndex index) const { 385 Heap::RootListIndex index) const {
388 __ LoadRoot(result_register(), index); 386 __ LoadRoot(result_register(), index);
(...skipping 12 matching lines...) Expand all
401 true_label_, 399 true_label_,
402 false_label_); 400 false_label_);
403 if (index == Heap::kUndefinedValueRootIndex || 401 if (index == Heap::kUndefinedValueRootIndex ||
404 index == Heap::kNullValueRootIndex || 402 index == Heap::kNullValueRootIndex ||
405 index == Heap::kFalseValueRootIndex) { 403 index == Heap::kFalseValueRootIndex) {
406 if (false_label_ != fall_through_) __ jmp(false_label_); 404 if (false_label_ != fall_through_) __ jmp(false_label_);
407 } else if (index == Heap::kTrueValueRootIndex) { 405 } else if (index == Heap::kTrueValueRootIndex) {
408 if (true_label_ != fall_through_) __ jmp(true_label_); 406 if (true_label_ != fall_through_) __ jmp(true_label_);
409 } else { 407 } else {
410 __ LoadRoot(result_register(), index); 408 __ LoadRoot(result_register(), index);
411 codegen()->DoTest(true_label_, false_label_, fall_through_); 409 codegen()->DoTest(this);
412 } 410 }
413 } 411 }
414 412
415 413
416 void FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const { 414 void FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const {
417 } 415 }
418 416
419 417
420 void FullCodeGenerator::AccumulatorValueContext::Plug( 418 void FullCodeGenerator::AccumulatorValueContext::Plug(
421 Handle<Object> lit) const { 419 Handle<Object> lit) const {
(...skipping 24 matching lines...) Expand all
446 } 444 }
447 } else if (lit->IsSmi()) { 445 } else if (lit->IsSmi()) {
448 if (Smi::cast(*lit)->value() == 0) { 446 if (Smi::cast(*lit)->value() == 0) {
449 if (false_label_ != fall_through_) __ jmp(false_label_); 447 if (false_label_ != fall_through_) __ jmp(false_label_);
450 } else { 448 } else {
451 if (true_label_ != fall_through_) __ jmp(true_label_); 449 if (true_label_ != fall_through_) __ jmp(true_label_);
452 } 450 }
453 } else { 451 } else {
454 // For simplicity we always test the accumulator register. 452 // For simplicity we always test the accumulator register.
455 __ Move(result_register(), lit); 453 __ Move(result_register(), lit);
456 codegen()->DoTest(true_label_, false_label_, fall_through_); 454 codegen()->DoTest(this);
457 } 455 }
458 } 456 }
459 457
460 458
461 void FullCodeGenerator::EffectContext::DropAndPlug(int count, 459 void FullCodeGenerator::EffectContext::DropAndPlug(int count,
462 Register reg) const { 460 Register reg) const {
463 ASSERT(count > 0); 461 ASSERT(count > 0);
464 __ Drop(count); 462 __ Drop(count);
465 } 463 }
466 464
(...skipping 15 matching lines...) Expand all
482 } 480 }
483 481
484 482
485 void FullCodeGenerator::TestContext::DropAndPlug(int count, 483 void FullCodeGenerator::TestContext::DropAndPlug(int count,
486 Register reg) const { 484 Register reg) const {
487 ASSERT(count > 0); 485 ASSERT(count > 0);
488 // For simplicity we always test the accumulator register. 486 // For simplicity we always test the accumulator register.
489 __ Drop(count); 487 __ Drop(count);
490 __ Move(result_register(), reg); 488 __ Move(result_register(), reg);
491 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); 489 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
492 codegen()->DoTest(true_label_, false_label_, fall_through_); 490 codegen()->DoTest(this);
493 } 491 }
494 492
495 493
496 void FullCodeGenerator::EffectContext::Plug(Label* materialize_true, 494 void FullCodeGenerator::EffectContext::Plug(Label* materialize_true,
497 Label* materialize_false) const { 495 Label* materialize_false) const {
498 ASSERT(materialize_true == materialize_false); 496 ASSERT(materialize_true == materialize_false);
499 __ bind(materialize_true); 497 __ bind(materialize_true);
500 } 498 }
501 499
502 500
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
557 true_label_, 555 true_label_,
558 false_label_); 556 false_label_);
559 if (flag) { 557 if (flag) {
560 if (true_label_ != fall_through_) __ jmp(true_label_); 558 if (true_label_ != fall_through_) __ jmp(true_label_);
561 } else { 559 } else {
562 if (false_label_ != fall_through_) __ jmp(false_label_); 560 if (false_label_ != fall_through_) __ jmp(false_label_);
563 } 561 }
564 } 562 }
565 563
566 564
567 void FullCodeGenerator::DoTest(Label* if_true, 565 void FullCodeGenerator::DoTest(Expression* condition,
566 Label* if_true,
568 Label* if_false, 567 Label* if_false,
569 Label* fall_through) { 568 Label* fall_through) {
570 ToBooleanStub stub; 569 ToBooleanStub stub(result_register());
571 __ push(result_register()); 570 __ push(result_register());
572 __ CallStub(&stub); 571 __ CallStub(&stub);
573 __ testq(rax, rax); 572 __ testq(result_register(), result_register());
574 // The stub returns nonzero for true. 573 // The stub returns nonzero for true.
575 Split(not_zero, if_true, if_false, fall_through); 574 Split(not_zero, if_true, if_false, fall_through);
576 } 575 }
577 576
578 577
579 void FullCodeGenerator::Split(Condition cc, 578 void FullCodeGenerator::Split(Condition cc,
580 Label* if_true, 579 Label* if_true,
581 Label* if_false, 580 Label* if_false,
582 Label* fall_through) { 581 Label* fall_through) {
583 if (if_false == fall_through) { 582 if (if_false == fall_through) {
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
677 } else if (function != NULL) { 676 } else if (function != NULL) {
678 VisitForAccumulatorValue(function); 677 VisitForAccumulatorValue(function);
679 __ movq(Operand(rbp, SlotOffset(slot)), result_register()); 678 __ movq(Operand(rbp, SlotOffset(slot)), result_register());
680 } 679 }
681 break; 680 break;
682 681
683 case Slot::CONTEXT: 682 case Slot::CONTEXT:
684 // We bypass the general EmitSlotSearch because we know more about 683 // We bypass the general EmitSlotSearch because we know more about
685 // this specific context. 684 // this specific context.
686 685
687 // The variable in the decl always resides in the current context. 686 // The variable in the decl always resides in the current function
687 // context.
688 ASSERT_EQ(0, scope()->ContextChainLength(variable->scope())); 688 ASSERT_EQ(0, scope()->ContextChainLength(variable->scope()));
689 if (FLAG_debug_code) { 689 if (FLAG_debug_code) {
690 // Check if we have the correct context pointer. 690 // Check that we're not inside a with or catch context.
691 __ movq(rbx, ContextOperand(rsi, Context::FCONTEXT_INDEX)); 691 __ movq(rbx, FieldOperand(rsi, HeapObject::kMapOffset));
692 __ cmpq(rbx, rsi); 692 __ CompareRoot(rbx, Heap::kWithContextMapRootIndex);
693 __ Check(equal, "Unexpected declaration in current context."); 693 __ Check(not_equal, "Declaration in with context.");
694 __ CompareRoot(rbx, Heap::kCatchContextMapRootIndex);
695 __ Check(not_equal, "Declaration in catch context.");
694 } 696 }
695 if (mode == Variable::CONST) { 697 if (mode == Variable::CONST) {
696 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); 698 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
697 __ movq(ContextOperand(rsi, slot->index()), kScratchRegister); 699 __ movq(ContextOperand(rsi, slot->index()), kScratchRegister);
698 // No write barrier since the hole value is in old space. 700 // No write barrier since the hole value is in old space.
699 } else if (function != NULL) { 701 } else if (function != NULL) {
700 VisitForAccumulatorValue(function); 702 VisitForAccumulatorValue(function);
701 __ movq(ContextOperand(rsi, slot->index()), result_register()); 703 __ movq(ContextOperand(rsi, slot->index()), result_register());
702 int offset = Context::SlotOffset(slot->index()); 704 int offset = Context::SlotOffset(slot->index());
703 // We know that we have written a function, which is not a smi. 705 // We know that we have written a function, which is not a smi.
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
749 __ push(rax); 751 __ push(rax);
750 VisitForAccumulatorValue(function); 752 VisitForAccumulatorValue(function);
751 __ pop(rdx); 753 __ pop(rdx);
752 ASSERT(prop->key()->AsLiteral() != NULL && 754 ASSERT(prop->key()->AsLiteral() != NULL &&
753 prop->key()->AsLiteral()->handle()->IsSmi()); 755 prop->key()->AsLiteral()->handle()->IsSmi());
754 __ Move(rcx, prop->key()->AsLiteral()->handle()); 756 __ Move(rcx, prop->key()->AsLiteral()->handle());
755 757
756 Handle<Code> ic = is_strict_mode() 758 Handle<Code> ic = is_strict_mode()
757 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() 759 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
758 : isolate()->builtins()->KeyedStoreIC_Initialize(); 760 : isolate()->builtins()->KeyedStoreIC_Initialize();
759 EmitCallIC(ic, RelocInfo::CODE_TARGET, AstNode::kNoNumber); 761 __ call(ic);
760 } 762 }
761 } 763 }
762 } 764 }
763 765
764 766
765 void FullCodeGenerator::VisitDeclaration(Declaration* decl) { 767 void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
766 EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun()); 768 EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun());
767 } 769 }
768 770
769 771
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
822 __ cmpq(rdx, rax); 824 __ cmpq(rdx, rax);
823 __ j(not_equal, &next_test); 825 __ j(not_equal, &next_test);
824 __ Drop(1); // Switch value is no longer needed. 826 __ Drop(1); // Switch value is no longer needed.
825 __ jmp(clause->body_target()); 827 __ jmp(clause->body_target());
826 __ bind(&slow_case); 828 __ bind(&slow_case);
827 } 829 }
828 830
829 // Record position before stub call for type feedback. 831 // Record position before stub call for type feedback.
830 SetSourcePosition(clause->position()); 832 SetSourcePosition(clause->position());
831 Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT); 833 Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT);
832 EmitCallIC(ic, &patch_site, clause->CompareId()); 834 __ call(ic, RelocInfo::CODE_TARGET, clause->CompareId());
835 patch_site.EmitPatchInfo();
833 836
834 __ testq(rax, rax); 837 __ testq(rax, rax);
835 __ j(not_equal, &next_test); 838 __ j(not_equal, &next_test);
836 __ Drop(1); // Switch value is no longer needed. 839 __ Drop(1); // Switch value is no longer needed.
837 __ jmp(clause->body_target()); 840 __ jmp(clause->body_target());
838 } 841 }
839 842
840 // Discard the test value and jump to the default if present, otherwise to 843 // Discard the test value and jump to the default if present, otherwise to
841 // the end of the statement. 844 // the end of the statement.
842 __ bind(&next_test); 845 __ bind(&next_test);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
876 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); 879 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
877 __ j(equal, &exit); 880 __ j(equal, &exit);
878 Register null_value = rdi; 881 Register null_value = rdi;
879 __ LoadRoot(null_value, Heap::kNullValueRootIndex); 882 __ LoadRoot(null_value, Heap::kNullValueRootIndex);
880 __ cmpq(rax, null_value); 883 __ cmpq(rax, null_value);
881 __ j(equal, &exit); 884 __ j(equal, &exit);
882 885
883 // Convert the object to a JS object. 886 // Convert the object to a JS object.
884 Label convert, done_convert; 887 Label convert, done_convert;
885 __ JumpIfSmi(rax, &convert); 888 __ JumpIfSmi(rax, &convert);
886 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rcx); 889 __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rcx);
887 __ j(above_equal, &done_convert); 890 __ j(above_equal, &done_convert);
888 __ bind(&convert); 891 __ bind(&convert);
889 __ push(rax); 892 __ push(rax);
890 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); 893 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
891 __ bind(&done_convert); 894 __ bind(&done_convert);
892 __ push(rax); 895 __ push(rax);
893 896
894 // Check cache validity in generated code. This is a fast case for 897 // Check cache validity in generated code. This is a fast case for
895 // the JSObject::IsSimpleEnum cache validity checks. If we cannot 898 // the JSObject::IsSimpleEnum cache validity checks. If we cannot
896 // guarantee cache validity, call the runtime system to check cache 899 // guarantee cache validity, call the runtime system to check cache
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
1087 Scope* s = scope(); 1090 Scope* s = scope();
1088 while (s != NULL) { 1091 while (s != NULL) {
1089 if (s->num_heap_slots() > 0) { 1092 if (s->num_heap_slots() > 0) {
1090 if (s->calls_eval()) { 1093 if (s->calls_eval()) {
1091 // Check that extension is NULL. 1094 // Check that extension is NULL.
1092 __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX), 1095 __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX),
1093 Immediate(0)); 1096 Immediate(0));
1094 __ j(not_equal, slow); 1097 __ j(not_equal, slow);
1095 } 1098 }
1096 // Load next context in chain. 1099 // Load next context in chain.
1097 __ movq(temp, ContextOperand(context, Context::CLOSURE_INDEX)); 1100 __ movq(temp, ContextOperand(context, Context::PREVIOUS_INDEX));
1098 __ movq(temp, FieldOperand(temp, JSFunction::kContextOffset));
1099 // Walk the rest of the chain without clobbering rsi. 1101 // Walk the rest of the chain without clobbering rsi.
1100 context = temp; 1102 context = temp;
1101 } 1103 }
1102 // If no outer scope calls eval, we do not need to check more 1104 // If no outer scope calls eval, we do not need to check more
1103 // context extensions. If we have reached an eval scope, we check 1105 // context extensions. If we have reached an eval scope, we check
1104 // all extensions from this point. 1106 // all extensions from this point.
1105 if (!s->outer_scope_calls_eval() || s->is_eval_scope()) break; 1107 if (!s->outer_scope_calls_eval() || s->is_eval_scope()) break;
1106 s = s->outer_scope(); 1108 s = s->outer_scope();
1107 } 1109 }
1108 1110
1109 if (s != NULL && s->is_eval_scope()) { 1111 if (s != NULL && s->is_eval_scope()) {
1110 // Loop up the context chain. There is no frame effect so it is 1112 // Loop up the context chain. There is no frame effect so it is
1111 // safe to use raw labels here. 1113 // safe to use raw labels here.
1112 Label next, fast; 1114 Label next, fast;
1113 if (!context.is(temp)) { 1115 if (!context.is(temp)) {
1114 __ movq(temp, context); 1116 __ movq(temp, context);
1115 } 1117 }
1116 // Load map for comparison into register, outside loop. 1118 // Load map for comparison into register, outside loop.
1117 __ LoadRoot(kScratchRegister, Heap::kGlobalContextMapRootIndex); 1119 __ LoadRoot(kScratchRegister, Heap::kGlobalContextMapRootIndex);
1118 __ bind(&next); 1120 __ bind(&next);
1119 // Terminate at global context. 1121 // Terminate at global context.
1120 __ cmpq(kScratchRegister, FieldOperand(temp, HeapObject::kMapOffset)); 1122 __ cmpq(kScratchRegister, FieldOperand(temp, HeapObject::kMapOffset));
1121 __ j(equal, &fast, Label::kNear); 1123 __ j(equal, &fast, Label::kNear);
1122 // Check that extension is NULL. 1124 // Check that extension is NULL.
1123 __ cmpq(ContextOperand(temp, Context::EXTENSION_INDEX), Immediate(0)); 1125 __ cmpq(ContextOperand(temp, Context::EXTENSION_INDEX), Immediate(0));
1124 __ j(not_equal, slow); 1126 __ j(not_equal, slow);
1125 // Load next context in chain. 1127 // Load next context in chain.
1126 __ movq(temp, ContextOperand(temp, Context::CLOSURE_INDEX)); 1128 __ movq(temp, ContextOperand(temp, Context::PREVIOUS_INDEX));
1127 __ movq(temp, FieldOperand(temp, JSFunction::kContextOffset));
1128 __ jmp(&next); 1129 __ jmp(&next);
1129 __ bind(&fast); 1130 __ bind(&fast);
1130 } 1131 }
1131 1132
1132 // All extension objects were empty and it is safe to use a global 1133 // All extension objects were empty and it is safe to use a global
1133 // load IC call. 1134 // load IC call.
1134 __ movq(rax, GlobalObjectOperand()); 1135 __ movq(rax, GlobalObjectOperand());
1135 __ Move(rcx, slot->var()->name()); 1136 __ Move(rcx, slot->var()->name());
1136 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 1137 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
1137 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) 1138 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
1138 ? RelocInfo::CODE_TARGET 1139 ? RelocInfo::CODE_TARGET
1139 : RelocInfo::CODE_TARGET_CONTEXT; 1140 : RelocInfo::CODE_TARGET_CONTEXT;
1140 EmitCallIC(ic, mode, AstNode::kNoNumber); 1141 __ call(ic, mode);
1141 } 1142 }
1142 1143
1143 1144
1144 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions( 1145 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(
1145 Slot* slot, 1146 Slot* slot,
1146 Label* slow) { 1147 Label* slow) {
1147 ASSERT(slot->type() == Slot::CONTEXT); 1148 ASSERT(slot->type() == Slot::CONTEXT);
1148 Register context = rsi; 1149 Register context = rsi;
1149 Register temp = rbx; 1150 Register temp = rbx;
1150 1151
1151 for (Scope* s = scope(); s != slot->var()->scope(); s = s->outer_scope()) { 1152 for (Scope* s = scope(); s != slot->var()->scope(); s = s->outer_scope()) {
1152 if (s->num_heap_slots() > 0) { 1153 if (s->num_heap_slots() > 0) {
1153 if (s->calls_eval()) { 1154 if (s->calls_eval()) {
1154 // Check that extension is NULL. 1155 // Check that extension is NULL.
1155 __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX), 1156 __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX),
1156 Immediate(0)); 1157 Immediate(0));
1157 __ j(not_equal, slow); 1158 __ j(not_equal, slow);
1158 } 1159 }
1159 __ movq(temp, ContextOperand(context, Context::CLOSURE_INDEX)); 1160 __ movq(temp, ContextOperand(context, Context::PREVIOUS_INDEX));
1160 __ movq(temp, FieldOperand(temp, JSFunction::kContextOffset));
1161 // Walk the rest of the chain without clobbering rsi. 1161 // Walk the rest of the chain without clobbering rsi.
1162 context = temp; 1162 context = temp;
1163 } 1163 }
1164 } 1164 }
1165 // Check that last extension is NULL. 1165 // Check that last extension is NULL.
1166 __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX), Immediate(0)); 1166 __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX), Immediate(0));
1167 __ j(not_equal, slow); 1167 __ j(not_equal, slow);
1168 1168
1169 // This function is used only for loads, not stores, so it's safe to 1169 // This function is used only for loads, not stores, so it's safe to
1170 // return an rsi-based operand (the write barrier cannot be allowed to 1170 // return an rsi-based operand (the write barrier cannot be allowed to
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1211 key_literal->handle()->IsSmi()) { 1211 key_literal->handle()->IsSmi()) {
1212 // Load arguments object if there are no eval-introduced 1212 // Load arguments object if there are no eval-introduced
1213 // variables. Then load the argument from the arguments 1213 // variables. Then load the argument from the arguments
1214 // object using keyed load. 1214 // object using keyed load.
1215 __ movq(rdx, 1215 __ movq(rdx,
1216 ContextSlotOperandCheckExtensions(obj_proxy->var()->AsSlot(), 1216 ContextSlotOperandCheckExtensions(obj_proxy->var()->AsSlot(),
1217 slow)); 1217 slow));
1218 __ Move(rax, key_literal->handle()); 1218 __ Move(rax, key_literal->handle());
1219 Handle<Code> ic = 1219 Handle<Code> ic =
1220 isolate()->builtins()->KeyedLoadIC_Initialize(); 1220 isolate()->builtins()->KeyedLoadIC_Initialize();
1221 EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(property)); 1221 __ call(ic, RelocInfo::CODE_TARGET, GetPropertyId(property));
1222 __ jmp(done); 1222 __ jmp(done);
1223 } 1223 }
1224 } 1224 }
1225 } 1225 }
1226 } 1226 }
1227 } 1227 }
1228 1228
1229 1229
1230 void FullCodeGenerator::EmitVariableLoad(Variable* var) { 1230 void FullCodeGenerator::EmitVariableLoad(Variable* var) {
1231 // Four cases: non-this global variables, lookup slots, all other 1231 // Three cases: non-this global variables, lookup slots, and all other
1232 // types of slots, and parameters that rewrite to explicit property 1232 // types of slots.
1233 // accesses on the arguments object.
1234 Slot* slot = var->AsSlot(); 1233 Slot* slot = var->AsSlot();
1235 Property* property = var->AsProperty(); 1234 ASSERT((var->is_global() && !var->is_this()) == (slot == NULL));
1236 1235
1237 if (var->is_global() && !var->is_this()) { 1236 if (slot == NULL) {
1238 Comment cmnt(masm_, "Global variable"); 1237 Comment cmnt(masm_, "Global variable");
1239 // Use inline caching. Variable name is passed in rcx and the global 1238 // Use inline caching. Variable name is passed in rcx and the global
1240 // object on the stack. 1239 // object on the stack.
1241 __ Move(rcx, var->name()); 1240 __ Move(rcx, var->name());
1242 __ movq(rax, GlobalObjectOperand()); 1241 __ movq(rax, GlobalObjectOperand());
1243 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 1242 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
1244 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT, AstNode::kNoNumber); 1243 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT);
1245 context()->Plug(rax); 1244 context()->Plug(rax);
1246 1245
1247 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { 1246 } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
1248 Label done, slow; 1247 Label done, slow;
1249 1248
1250 // Generate code for loading from variables potentially shadowed 1249 // Generate code for loading from variables potentially shadowed
1251 // by eval-introduced variables. 1250 // by eval-introduced variables.
1252 EmitDynamicLoadFromSlotFastCase(slot, NOT_INSIDE_TYPEOF, &slow, &done); 1251 EmitDynamicLoadFromSlotFastCase(slot, NOT_INSIDE_TYPEOF, &slow, &done);
1253 1252
1254 __ bind(&slow); 1253 __ bind(&slow);
1255 Comment cmnt(masm_, "Lookup slot"); 1254 Comment cmnt(masm_, "Lookup slot");
1256 __ push(rsi); // Context. 1255 __ push(rsi); // Context.
1257 __ Push(var->name()); 1256 __ Push(var->name());
1258 __ CallRuntime(Runtime::kLoadContextSlot, 2); 1257 __ CallRuntime(Runtime::kLoadContextSlot, 2);
1259 __ bind(&done); 1258 __ bind(&done);
1260 1259
1261 context()->Plug(rax); 1260 context()->Plug(rax);
1262 1261
1263 } else if (slot != NULL) { 1262 } else {
1264 Comment cmnt(masm_, (slot->type() == Slot::CONTEXT) 1263 Comment cmnt(masm_, (slot->type() == Slot::CONTEXT)
1265 ? "Context slot" 1264 ? "Context slot"
1266 : "Stack slot"); 1265 : "Stack slot");
1267 if (var->mode() == Variable::CONST) { 1266 if (var->mode() == Variable::CONST) {
1268 // Constants may be the hole value if they have not been initialized. 1267 // Constants may be the hole value if they have not been initialized.
1269 // Unhole them. 1268 // Unhole them.
1270 Label done; 1269 Label done;
1271 MemOperand slot_operand = EmitSlotSearch(slot, rax); 1270 MemOperand slot_operand = EmitSlotSearch(slot, rax);
1272 __ movq(rax, slot_operand); 1271 __ movq(rax, slot_operand);
1273 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); 1272 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
1274 __ j(not_equal, &done, Label::kNear); 1273 __ j(not_equal, &done, Label::kNear);
1275 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 1274 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
1276 __ bind(&done); 1275 __ bind(&done);
1277 context()->Plug(rax); 1276 context()->Plug(rax);
1278 } else { 1277 } else {
1279 context()->Plug(slot); 1278 context()->Plug(slot);
1280 } 1279 }
1281
1282 } else {
1283 Comment cmnt(masm_, "Rewritten parameter");
1284 ASSERT_NOT_NULL(property);
1285 // Rewritten parameter accesses are of the form "slot[literal]".
1286
1287 // Assert that the object is in a slot.
1288 Variable* object_var = property->obj()->AsVariableProxy()->AsVariable();
1289 ASSERT_NOT_NULL(object_var);
1290 Slot* object_slot = object_var->AsSlot();
1291 ASSERT_NOT_NULL(object_slot);
1292
1293 // Load the object.
1294 MemOperand object_loc = EmitSlotSearch(object_slot, rax);
1295 __ movq(rdx, object_loc);
1296
1297 // Assert that the key is a smi.
1298 Literal* key_literal = property->key()->AsLiteral();
1299 ASSERT_NOT_NULL(key_literal);
1300 ASSERT(key_literal->handle()->IsSmi());
1301
1302 // Load the key.
1303 __ Move(rax, key_literal->handle());
1304
1305 // Do a keyed property load.
1306 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
1307 EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(property));
1308 context()->Plug(rax);
1309 } 1280 }
1310 } 1281 }
1311 1282
1312 1283
1313 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { 1284 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
1314 Comment cmnt(masm_, "[ RegExpLiteral"); 1285 Comment cmnt(masm_, "[ RegExpLiteral");
1315 Label materialized; 1286 Label materialized;
1316 // Registers will be used as follows: 1287 // Registers will be used as follows:
1317 // rdi = JS function. 1288 // rdi = JS function.
1318 // rcx = literals array. 1289 // rcx = literals array.
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
1410 // Fall through. 1381 // Fall through.
1411 case ObjectLiteral::Property::COMPUTED: 1382 case ObjectLiteral::Property::COMPUTED:
1412 if (key->handle()->IsSymbol()) { 1383 if (key->handle()->IsSymbol()) {
1413 if (property->emit_store()) { 1384 if (property->emit_store()) {
1414 VisitForAccumulatorValue(value); 1385 VisitForAccumulatorValue(value);
1415 __ Move(rcx, key->handle()); 1386 __ Move(rcx, key->handle());
1416 __ movq(rdx, Operand(rsp, 0)); 1387 __ movq(rdx, Operand(rsp, 0));
1417 Handle<Code> ic = is_strict_mode() 1388 Handle<Code> ic = is_strict_mode()
1418 ? isolate()->builtins()->StoreIC_Initialize_Strict() 1389 ? isolate()->builtins()->StoreIC_Initialize_Strict()
1419 : isolate()->builtins()->StoreIC_Initialize(); 1390 : isolate()->builtins()->StoreIC_Initialize();
1420 EmitCallIC(ic, RelocInfo::CODE_TARGET, key->id()); 1391 __ call(ic, RelocInfo::CODE_TARGET, key->id());
1421 PrepareForBailoutForId(key->id(), NO_REGISTERS); 1392 PrepareForBailoutForId(key->id(), NO_REGISTERS);
1422 } else { 1393 } else {
1423 VisitForEffect(value); 1394 VisitForEffect(value);
1424 } 1395 }
1425 break; 1396 break;
1426 } 1397 }
1427 // Fall through. 1398 // Fall through.
1428 case ObjectLiteral::Property::PROTOTYPE: 1399 case ObjectLiteral::Property::PROTOTYPE:
1429 __ push(Operand(rsp, 0)); // Duplicate receiver. 1400 __ push(Operand(rsp, 0)); // Duplicate receiver.
1430 VisitForStackValue(key); 1401 VisitForStackValue(key);
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
1531 void FullCodeGenerator::VisitAssignment(Assignment* expr) { 1502 void FullCodeGenerator::VisitAssignment(Assignment* expr) {
1532 Comment cmnt(masm_, "[ Assignment"); 1503 Comment cmnt(masm_, "[ Assignment");
1533 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' 1504 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
1534 // on the left-hand side. 1505 // on the left-hand side.
1535 if (!expr->target()->IsValidLeftHandSide()) { 1506 if (!expr->target()->IsValidLeftHandSide()) {
1536 VisitForEffect(expr->target()); 1507 VisitForEffect(expr->target());
1537 return; 1508 return;
1538 } 1509 }
1539 1510
1540 // Left-hand side can only be a property, a global or a (parameter or local) 1511 // Left-hand side can only be a property, a global or a (parameter or local)
1541 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. 1512 // slot.
1542 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 1513 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
1543 LhsKind assign_type = VARIABLE; 1514 LhsKind assign_type = VARIABLE;
1544 Property* property = expr->target()->AsProperty(); 1515 Property* property = expr->target()->AsProperty();
1545 if (property != NULL) { 1516 if (property != NULL) {
1546 assign_type = (property->key()->IsPropertyName()) 1517 assign_type = (property->key()->IsPropertyName())
1547 ? NAMED_PROPERTY 1518 ? NAMED_PROPERTY
1548 : KEYED_PROPERTY; 1519 : KEYED_PROPERTY;
1549 } 1520 }
1550 1521
1551 // Evaluate LHS expression. 1522 // Evaluate LHS expression.
1552 switch (assign_type) { 1523 switch (assign_type) {
1553 case VARIABLE: 1524 case VARIABLE:
1554 // Nothing to do here. 1525 // Nothing to do here.
1555 break; 1526 break;
1556 case NAMED_PROPERTY: 1527 case NAMED_PROPERTY:
1557 if (expr->is_compound()) { 1528 if (expr->is_compound()) {
1558 // We need the receiver both on the stack and in the accumulator. 1529 // We need the receiver both on the stack and in the accumulator.
1559 VisitForAccumulatorValue(property->obj()); 1530 VisitForAccumulatorValue(property->obj());
1560 __ push(result_register()); 1531 __ push(result_register());
1561 } else { 1532 } else {
1562 VisitForStackValue(property->obj()); 1533 VisitForStackValue(property->obj());
1563 } 1534 }
1564 break; 1535 break;
1565 case KEYED_PROPERTY: { 1536 case KEYED_PROPERTY: {
1566 if (expr->is_compound()) { 1537 if (expr->is_compound()) {
1567 if (property->is_arguments_access()) { 1538 VisitForStackValue(property->obj());
1568 VariableProxy* obj_proxy = property->obj()->AsVariableProxy(); 1539 VisitForAccumulatorValue(property->key());
1569 MemOperand slot_operand =
1570 EmitSlotSearch(obj_proxy->var()->AsSlot(), rcx);
1571 __ push(slot_operand);
1572 __ Move(rax, property->key()->AsLiteral()->handle());
1573 } else {
1574 VisitForStackValue(property->obj());
1575 VisitForAccumulatorValue(property->key());
1576 }
1577 __ movq(rdx, Operand(rsp, 0)); 1540 __ movq(rdx, Operand(rsp, 0));
1578 __ push(rax); 1541 __ push(rax);
1579 } else { 1542 } else {
1580 if (property->is_arguments_access()) { 1543 VisitForStackValue(property->obj());
1581 VariableProxy* obj_proxy = property->obj()->AsVariableProxy(); 1544 VisitForStackValue(property->key());
1582 MemOperand slot_operand =
1583 EmitSlotSearch(obj_proxy->var()->AsSlot(), rcx);
1584 __ push(slot_operand);
1585 __ Push(property->key()->AsLiteral()->handle());
1586 } else {
1587 VisitForStackValue(property->obj());
1588 VisitForStackValue(property->key());
1589 }
1590 } 1545 }
1591 break; 1546 break;
1592 } 1547 }
1593 } 1548 }
1594 1549
1595 // For compound assignments we need another deoptimization point after the 1550 // For compound assignments we need another deoptimization point after the
1596 // variable/property load. 1551 // variable/property load.
1597 if (expr->is_compound()) { 1552 if (expr->is_compound()) {
1598 { AccumulatorValueContext context(this); 1553 { AccumulatorValueContext context(this);
1599 switch (assign_type) { 1554 switch (assign_type) {
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
1655 break; 1610 break;
1656 } 1611 }
1657 } 1612 }
1658 1613
1659 1614
1660 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { 1615 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
1661 SetSourcePosition(prop->position()); 1616 SetSourcePosition(prop->position());
1662 Literal* key = prop->key()->AsLiteral(); 1617 Literal* key = prop->key()->AsLiteral();
1663 __ Move(rcx, key->handle()); 1618 __ Move(rcx, key->handle());
1664 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 1619 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
1665 EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(prop)); 1620 __ call(ic, RelocInfo::CODE_TARGET, GetPropertyId(prop));
1666 } 1621 }
1667 1622
1668 1623
1669 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { 1624 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
1670 SetSourcePosition(prop->position()); 1625 SetSourcePosition(prop->position());
1671 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); 1626 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
1672 EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(prop)); 1627 __ call(ic, RelocInfo::CODE_TARGET, GetPropertyId(prop));
1673 } 1628 }
1674 1629
1675 1630
1676 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, 1631 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
1677 Token::Value op, 1632 Token::Value op,
1678 OverwriteMode mode, 1633 OverwriteMode mode,
1679 Expression* left, 1634 Expression* left,
1680 Expression* right) { 1635 Expression* right) {
1681 // Do combined smi check of the operands. Left operand is on the 1636 // Do combined smi check of the operands. Left operand is on the
1682 // stack (popped into rdx). Right operand is in rax but moved into 1637 // stack (popped into rdx). Right operand is in rax but moved into
1683 // rcx to make the shifts easier. 1638 // rcx to make the shifts easier.
1684 Label done, stub_call, smi_case; 1639 Label done, stub_call, smi_case;
1685 __ pop(rdx); 1640 __ pop(rdx);
1686 __ movq(rcx, rax); 1641 __ movq(rcx, rax);
1687 __ or_(rax, rdx); 1642 __ or_(rax, rdx);
1688 JumpPatchSite patch_site(masm_); 1643 JumpPatchSite patch_site(masm_);
1689 patch_site.EmitJumpIfSmi(rax, &smi_case, Label::kNear); 1644 patch_site.EmitJumpIfSmi(rax, &smi_case, Label::kNear);
1690 1645
1691 __ bind(&stub_call); 1646 __ bind(&stub_call);
1692 __ movq(rax, rcx); 1647 __ movq(rax, rcx);
1693 BinaryOpStub stub(op, mode); 1648 BinaryOpStub stub(op, mode);
1694 EmitCallIC(stub.GetCode(), &patch_site, expr->id()); 1649 __ call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id());
1650 patch_site.EmitPatchInfo();
1695 __ jmp(&done, Label::kNear); 1651 __ jmp(&done, Label::kNear);
1696 1652
1697 __ bind(&smi_case); 1653 __ bind(&smi_case);
1698 switch (op) { 1654 switch (op) {
1699 case Token::SAR: 1655 case Token::SAR:
1700 __ SmiShiftArithmeticRight(rax, rdx, rcx); 1656 __ SmiShiftArithmeticRight(rax, rdx, rcx);
1701 break; 1657 break;
1702 case Token::SHL: 1658 case Token::SHL:
1703 __ SmiShiftLeft(rax, rdx, rcx); 1659 __ SmiShiftLeft(rax, rdx, rcx);
1704 break; 1660 break;
(...skipping 26 matching lines...) Expand all
1731 __ bind(&done); 1687 __ bind(&done);
1732 context()->Plug(rax); 1688 context()->Plug(rax);
1733 } 1689 }
1734 1690
1735 1691
1736 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, 1692 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr,
1737 Token::Value op, 1693 Token::Value op,
1738 OverwriteMode mode) { 1694 OverwriteMode mode) {
1739 __ pop(rdx); 1695 __ pop(rdx);
1740 BinaryOpStub stub(op, mode); 1696 BinaryOpStub stub(op, mode);
1741 // NULL signals no inlined smi code. 1697 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code.
1742 EmitCallIC(stub.GetCode(), NULL, expr->id()); 1698 __ call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id());
1699 patch_site.EmitPatchInfo();
1743 context()->Plug(rax); 1700 context()->Plug(rax);
1744 } 1701 }
1745 1702
1746 1703
1747 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) { 1704 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) {
1748 // Invalid left-hand sides are rewritten to have a 'throw 1705 // Invalid left-hand sides are rewritten to have a 'throw
1749 // ReferenceError' on the left-hand side. 1706 // ReferenceError' on the left-hand side.
1750 if (!expr->IsValidLeftHandSide()) { 1707 if (!expr->IsValidLeftHandSide()) {
1751 VisitForEffect(expr); 1708 VisitForEffect(expr);
1752 return; 1709 return;
1753 } 1710 }
1754 1711
1755 // Left-hand side can only be a property, a global or a (parameter or local) 1712 // Left-hand side can only be a property, a global or a (parameter or local)
1756 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. 1713 // slot.
1757 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 1714 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
1758 LhsKind assign_type = VARIABLE; 1715 LhsKind assign_type = VARIABLE;
1759 Property* prop = expr->AsProperty(); 1716 Property* prop = expr->AsProperty();
1760 if (prop != NULL) { 1717 if (prop != NULL) {
1761 assign_type = (prop->key()->IsPropertyName()) 1718 assign_type = (prop->key()->IsPropertyName())
1762 ? NAMED_PROPERTY 1719 ? NAMED_PROPERTY
1763 : KEYED_PROPERTY; 1720 : KEYED_PROPERTY;
1764 } 1721 }
1765 1722
1766 switch (assign_type) { 1723 switch (assign_type) {
1767 case VARIABLE: { 1724 case VARIABLE: {
1768 Variable* var = expr->AsVariableProxy()->var(); 1725 Variable* var = expr->AsVariableProxy()->var();
1769 EffectContext context(this); 1726 EffectContext context(this);
1770 EmitVariableAssignment(var, Token::ASSIGN); 1727 EmitVariableAssignment(var, Token::ASSIGN);
1771 break; 1728 break;
1772 } 1729 }
1773 case NAMED_PROPERTY: { 1730 case NAMED_PROPERTY: {
1774 __ push(rax); // Preserve value. 1731 __ push(rax); // Preserve value.
1775 VisitForAccumulatorValue(prop->obj()); 1732 VisitForAccumulatorValue(prop->obj());
1776 __ movq(rdx, rax); 1733 __ movq(rdx, rax);
1777 __ pop(rax); // Restore value. 1734 __ pop(rax); // Restore value.
1778 __ Move(rcx, prop->key()->AsLiteral()->handle()); 1735 __ Move(rcx, prop->key()->AsLiteral()->handle());
1779 Handle<Code> ic = is_strict_mode() 1736 Handle<Code> ic = is_strict_mode()
1780 ? isolate()->builtins()->StoreIC_Initialize_Strict() 1737 ? isolate()->builtins()->StoreIC_Initialize_Strict()
1781 : isolate()->builtins()->StoreIC_Initialize(); 1738 : isolate()->builtins()->StoreIC_Initialize();
1782 EmitCallIC(ic, RelocInfo::CODE_TARGET, AstNode::kNoNumber); 1739 __ call(ic);
1783 break; 1740 break;
1784 } 1741 }
1785 case KEYED_PROPERTY: { 1742 case KEYED_PROPERTY: {
1786 __ push(rax); // Preserve value. 1743 __ push(rax); // Preserve value.
1787 if (prop->is_synthetic()) { 1744 VisitForStackValue(prop->obj());
1788 ASSERT(prop->obj()->AsVariableProxy() != NULL); 1745 VisitForAccumulatorValue(prop->key());
1789 ASSERT(prop->key()->AsLiteral() != NULL); 1746 __ movq(rcx, rax);
1790 { AccumulatorValueContext for_object(this); 1747 __ pop(rdx);
1791 EmitVariableLoad(prop->obj()->AsVariableProxy()->var());
1792 }
1793 __ movq(rdx, rax);
1794 __ Move(rcx, prop->key()->AsLiteral()->handle());
1795 } else {
1796 VisitForStackValue(prop->obj());
1797 VisitForAccumulatorValue(prop->key());
1798 __ movq(rcx, rax);
1799 __ pop(rdx);
1800 }
1801 __ pop(rax); // Restore value. 1748 __ pop(rax); // Restore value.
1802 Handle<Code> ic = is_strict_mode() 1749 Handle<Code> ic = is_strict_mode()
1803 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() 1750 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
1804 : isolate()->builtins()->KeyedStoreIC_Initialize(); 1751 : isolate()->builtins()->KeyedStoreIC_Initialize();
1805 EmitCallIC(ic, RelocInfo::CODE_TARGET, AstNode::kNoNumber); 1752 __ call(ic);
1806 break; 1753 break;
1807 } 1754 }
1808 } 1755 }
1809 PrepareForBailoutForId(bailout_ast_id, TOS_REG); 1756 PrepareForBailoutForId(bailout_ast_id, TOS_REG);
1810 context()->Plug(rax); 1757 context()->Plug(rax);
1811 } 1758 }
1812 1759
1813 1760
1814 void FullCodeGenerator::EmitVariableAssignment(Variable* var, 1761 void FullCodeGenerator::EmitVariableAssignment(Variable* var,
1815 Token::Value op) { 1762 Token::Value op) {
1816 // Left-hand sides that rewrite to explicit property accesses do not reach
1817 // here.
1818 ASSERT(var != NULL); 1763 ASSERT(var != NULL);
1819 ASSERT(var->is_global() || var->AsSlot() != NULL); 1764 ASSERT(var->is_global() || var->AsSlot() != NULL);
1820 1765
1821 if (var->is_global()) { 1766 if (var->is_global()) {
1822 ASSERT(!var->is_this()); 1767 ASSERT(!var->is_this());
1823 // Assignment to a global variable. Use inline caching for the 1768 // Assignment to a global variable. Use inline caching for the
1824 // assignment. Right-hand-side value is passed in rax, variable name in 1769 // assignment. Right-hand-side value is passed in rax, variable name in
1825 // rcx, and the global object on the stack. 1770 // rcx, and the global object on the stack.
1826 __ Move(rcx, var->name()); 1771 __ Move(rcx, var->name());
1827 __ movq(rdx, GlobalObjectOperand()); 1772 __ movq(rdx, GlobalObjectOperand());
1828 Handle<Code> ic = is_strict_mode() 1773 Handle<Code> ic = is_strict_mode()
1829 ? isolate()->builtins()->StoreIC_Initialize_Strict() 1774 ? isolate()->builtins()->StoreIC_Initialize_Strict()
1830 : isolate()->builtins()->StoreIC_Initialize(); 1775 : isolate()->builtins()->StoreIC_Initialize();
1831 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT, AstNode::kNoNumber); 1776 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT);
1832 1777
1833 } else if (op == Token::INIT_CONST) { 1778 } else if (op == Token::INIT_CONST) {
1834 // Like var declarations, const declarations are hoisted to function 1779 // Like var declarations, const declarations are hoisted to function
1835 // scope. However, unlike var initializers, const initializers are able 1780 // scope. However, unlike var initializers, const initializers are able
1836 // to drill a hole to that function context, even from inside a 'with' 1781 // to drill a hole to that function context, even from inside a 'with'
1837 // context. We thus bypass the normal static scope lookup. 1782 // context. We thus bypass the normal static scope lookup.
1838 Slot* slot = var->AsSlot(); 1783 Slot* slot = var->AsSlot();
1839 Label skip; 1784 Label skip;
1840 switch (slot->type()) { 1785 switch (slot->type()) {
1841 case Slot::PARAMETER: 1786 case Slot::PARAMETER:
1842 // No const parameters. 1787 // No const parameters.
1843 UNREACHABLE(); 1788 UNREACHABLE();
1844 break; 1789 break;
1845 case Slot::LOCAL: 1790 case Slot::LOCAL:
1846 __ movq(rdx, Operand(rbp, SlotOffset(slot))); 1791 __ movq(rdx, Operand(rbp, SlotOffset(slot)));
1847 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); 1792 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
1848 __ j(not_equal, &skip); 1793 __ j(not_equal, &skip);
1849 __ movq(Operand(rbp, SlotOffset(slot)), rax); 1794 __ movq(Operand(rbp, SlotOffset(slot)), rax);
1850 break; 1795 break;
1851 case Slot::CONTEXT: { 1796 case Slot::CONTEXT:
1852 __ movq(rcx, ContextOperand(rsi, Context::FCONTEXT_INDEX));
1853 __ movq(rdx, ContextOperand(rcx, slot->index()));
1854 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
1855 __ j(not_equal, &skip);
1856 __ movq(ContextOperand(rcx, slot->index()), rax);
1857 int offset = Context::SlotOffset(slot->index());
1858 __ movq(rdx, rax); // Preserve the stored value in eax.
1859 __ RecordWriteContextSlot(rcx, offset, rdx, rbx, kDontSaveFPRegs);
1860 break;
1861 }
1862 case Slot::LOOKUP: 1797 case Slot::LOOKUP:
1863 __ push(rax); 1798 __ push(rax);
1864 __ push(rsi); 1799 __ push(rsi);
1865 __ Push(var->name()); 1800 __ Push(var->name());
1866 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); 1801 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
1867 break; 1802 break;
1868 } 1803 }
1869 __ bind(&skip); 1804 __ bind(&skip);
1870 1805
1871 } else if (var->mode() != Variable::CONST) { 1806 } else if (var->mode() != Variable::CONST) {
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
1925 SetSourcePosition(expr->position()); 1860 SetSourcePosition(expr->position());
1926 __ Move(rcx, prop->key()->AsLiteral()->handle()); 1861 __ Move(rcx, prop->key()->AsLiteral()->handle());
1927 if (expr->ends_initialization_block()) { 1862 if (expr->ends_initialization_block()) {
1928 __ movq(rdx, Operand(rsp, 0)); 1863 __ movq(rdx, Operand(rsp, 0));
1929 } else { 1864 } else {
1930 __ pop(rdx); 1865 __ pop(rdx);
1931 } 1866 }
1932 Handle<Code> ic = is_strict_mode() 1867 Handle<Code> ic = is_strict_mode()
1933 ? isolate()->builtins()->StoreIC_Initialize_Strict() 1868 ? isolate()->builtins()->StoreIC_Initialize_Strict()
1934 : isolate()->builtins()->StoreIC_Initialize(); 1869 : isolate()->builtins()->StoreIC_Initialize();
1935 EmitCallIC(ic, RelocInfo::CODE_TARGET, expr->id()); 1870 __ call(ic, RelocInfo::CODE_TARGET, expr->id());
1936 1871
1937 // If the assignment ends an initialization block, revert to fast case. 1872 // If the assignment ends an initialization block, revert to fast case.
1938 if (expr->ends_initialization_block()) { 1873 if (expr->ends_initialization_block()) {
1939 __ push(rax); // Result of assignment, saved even if not needed. 1874 __ push(rax); // Result of assignment, saved even if not needed.
1940 __ push(Operand(rsp, kPointerSize)); // Receiver is under value. 1875 __ push(Operand(rsp, kPointerSize)); // Receiver is under value.
1941 __ CallRuntime(Runtime::kToFastProperties, 1); 1876 __ CallRuntime(Runtime::kToFastProperties, 1);
1942 __ pop(rax); 1877 __ pop(rax);
1943 __ Drop(1); 1878 __ Drop(1);
1944 } 1879 }
1945 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 1880 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
(...skipping 19 matching lines...) Expand all
1965 if (expr->ends_initialization_block()) { 1900 if (expr->ends_initialization_block()) {
1966 __ movq(rdx, Operand(rsp, 0)); // Leave receiver on the stack for later. 1901 __ movq(rdx, Operand(rsp, 0)); // Leave receiver on the stack for later.
1967 } else { 1902 } else {
1968 __ pop(rdx); 1903 __ pop(rdx);
1969 } 1904 }
1970 // Record source code position before IC call. 1905 // Record source code position before IC call.
1971 SetSourcePosition(expr->position()); 1906 SetSourcePosition(expr->position());
1972 Handle<Code> ic = is_strict_mode() 1907 Handle<Code> ic = is_strict_mode()
1973 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() 1908 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
1974 : isolate()->builtins()->KeyedStoreIC_Initialize(); 1909 : isolate()->builtins()->KeyedStoreIC_Initialize();
1975 EmitCallIC(ic, RelocInfo::CODE_TARGET, expr->id()); 1910 __ call(ic, RelocInfo::CODE_TARGET, expr->id());
1976 1911
1977 // If the assignment ends an initialization block, revert to fast case. 1912 // If the assignment ends an initialization block, revert to fast case.
1978 if (expr->ends_initialization_block()) { 1913 if (expr->ends_initialization_block()) {
1979 __ pop(rdx); 1914 __ pop(rdx);
1980 __ push(rax); // Result of assignment, saved even if not needed. 1915 __ push(rax); // Result of assignment, saved even if not needed.
1981 __ push(rdx); 1916 __ push(rdx);
1982 __ CallRuntime(Runtime::kToFastProperties, 1); 1917 __ CallRuntime(Runtime::kToFastProperties, 1);
1983 __ pop(rax); 1918 __ pop(rax);
1984 } 1919 }
1985 1920
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
2017 VisitForStackValue(args->at(i)); 1952 VisitForStackValue(args->at(i));
2018 } 1953 }
2019 __ Move(rcx, name); 1954 __ Move(rcx, name);
2020 } 1955 }
2021 // Record source position for debugger. 1956 // Record source position for debugger.
2022 SetSourcePosition(expr->position()); 1957 SetSourcePosition(expr->position());
2023 // Call the IC initialization code. 1958 // Call the IC initialization code.
2024 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 1959 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
2025 Handle<Code> ic = 1960 Handle<Code> ic =
2026 ISOLATE->stub_cache()->ComputeCallInitialize(arg_count, in_loop, mode); 1961 ISOLATE->stub_cache()->ComputeCallInitialize(arg_count, in_loop, mode);
2027 EmitCallIC(ic, mode, expr->id()); 1962 __ call(ic, mode, expr->id());
2028 RecordJSReturnSite(expr); 1963 RecordJSReturnSite(expr);
2029 // Restore context register. 1964 // Restore context register.
2030 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 1965 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2031 context()->Plug(rax); 1966 context()->Plug(rax);
2032 } 1967 }
2033 1968
2034 1969
2035 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, 1970 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr,
2036 Expression* key) { 1971 Expression* key) {
2037 // Load the key. 1972 // Load the key.
(...skipping 13 matching lines...) Expand all
2051 VisitForStackValue(args->at(i)); 1986 VisitForStackValue(args->at(i));
2052 } 1987 }
2053 } 1988 }
2054 // Record source position for debugger. 1989 // Record source position for debugger.
2055 SetSourcePosition(expr->position()); 1990 SetSourcePosition(expr->position());
2056 // Call the IC initialization code. 1991 // Call the IC initialization code.
2057 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 1992 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
2058 Handle<Code> ic = 1993 Handle<Code> ic =
2059 ISOLATE->stub_cache()->ComputeKeyedCallInitialize(arg_count, in_loop); 1994 ISOLATE->stub_cache()->ComputeKeyedCallInitialize(arg_count, in_loop);
2060 __ movq(rcx, Operand(rsp, (arg_count + 1) * kPointerSize)); // Key. 1995 __ movq(rcx, Operand(rsp, (arg_count + 1) * kPointerSize)); // Key.
2061 EmitCallIC(ic, RelocInfo::CODE_TARGET, expr->id()); 1996 __ call(ic, RelocInfo::CODE_TARGET, expr->id());
2062 RecordJSReturnSite(expr); 1997 RecordJSReturnSite(expr);
2063 // Restore context register. 1998 // Restore context register.
2064 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 1999 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2065 context()->DropAndPlug(1, rax); // Drop the key still on the stack. 2000 context()->DropAndPlug(1, rax); // Drop the key still on the stack.
2066 } 2001 }
2067 2002
2068 2003
2069 void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) { 2004 void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) {
2070 // Code common for calls using the call stub. 2005 // Code common for calls using the call stub.
2071 ZoneList<Expression*>* args = expr->arguments(); 2006 ZoneList<Expression*>* args = expr->arguments();
(...skipping 19 matching lines...) Expand all
2091 void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag, 2026 void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag,
2092 int arg_count) { 2027 int arg_count) {
2093 // Push copy of the first argument or undefined if it doesn't exist. 2028 // Push copy of the first argument or undefined if it doesn't exist.
2094 if (arg_count > 0) { 2029 if (arg_count > 0) {
2095 __ push(Operand(rsp, arg_count * kPointerSize)); 2030 __ push(Operand(rsp, arg_count * kPointerSize));
2096 } else { 2031 } else {
2097 __ PushRoot(Heap::kUndefinedValueRootIndex); 2032 __ PushRoot(Heap::kUndefinedValueRootIndex);
2098 } 2033 }
2099 2034
2100 // Push the receiver of the enclosing function and do runtime call. 2035 // Push the receiver of the enclosing function and do runtime call.
2101 __ push(Operand(rbp, (2 + scope()->num_parameters()) * kPointerSize)); 2036 __ push(Operand(rbp, (2 + info_->scope()->num_parameters()) * kPointerSize));
2102 2037
2103 // Push the strict mode flag. 2038 // Push the strict mode flag.
2104 __ Push(Smi::FromInt(strict_mode_flag())); 2039 __ Push(Smi::FromInt(strict_mode_flag()));
2105 2040
2106 __ CallRuntime(flag == SKIP_CONTEXT_LOOKUP 2041 __ CallRuntime(flag == SKIP_CONTEXT_LOOKUP
2107 ? Runtime::kResolvePossiblyDirectEvalNoLookup 2042 ? Runtime::kResolvePossiblyDirectEvalNoLookup
2108 : Runtime::kResolvePossiblyDirectEval, 4); 2043 : Runtime::kResolvePossiblyDirectEval, 4);
2109 } 2044 }
2110 2045
2111 2046
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
2205 2140
2206 // If fast case code has been generated, emit code to push the 2141 // If fast case code has been generated, emit code to push the
2207 // function and receiver and have the slow path jump around this 2142 // function and receiver and have the slow path jump around this
2208 // code. 2143 // code.
2209 if (done.is_linked()) { 2144 if (done.is_linked()) {
2210 Label call; 2145 Label call;
2211 __ jmp(&call, Label::kNear); 2146 __ jmp(&call, Label::kNear);
2212 __ bind(&done); 2147 __ bind(&done);
2213 // Push function. 2148 // Push function.
2214 __ push(rax); 2149 __ push(rax);
2215 // Push global receiver. 2150 // The receiver is implicitly the global receiver. Indicate this
2216 __ movq(rbx, GlobalObjectOperand()); 2151 // by passing the hole to the call function stub.
2217 __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset)); 2152 __ PushRoot(Heap::kTheHoleValueRootIndex);
2218 __ bind(&call); 2153 __ bind(&call);
2219 } 2154 }
2220 2155
2221 // The receiver is either the global receiver or an object found 2156 // The receiver is either the global receiver or an object found
2222 // by LoadContextSlot. That object could be the hole if the 2157 // by LoadContextSlot. That object could be the hole if the
2223 // receiver is implicitly the global object. 2158 // receiver is implicitly the global object.
2224 EmitCallWithStub(expr, RECEIVER_MIGHT_BE_IMPLICIT); 2159 EmitCallWithStub(expr, RECEIVER_MIGHT_BE_IMPLICIT);
2225 } else if (fun->AsProperty() != NULL) { 2160 } else if (fun->AsProperty() != NULL) {
2226 // Call to an object property. 2161 // Call to an object property.
2227 Property* prop = fun->AsProperty(); 2162 Property* prop = fun->AsProperty();
2228 Literal* key = prop->key()->AsLiteral(); 2163 Literal* key = prop->key()->AsLiteral();
2229 if (key != NULL && key->handle()->IsSymbol()) { 2164 if (key != NULL && key->handle()->IsSymbol()) {
2230 // Call to a named property, use call IC. 2165 // Call to a named property, use call IC.
2231 { PreservePositionScope scope(masm()->positions_recorder()); 2166 { PreservePositionScope scope(masm()->positions_recorder());
2232 VisitForStackValue(prop->obj()); 2167 VisitForStackValue(prop->obj());
2233 } 2168 }
2234 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); 2169 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET);
2235 } else { 2170 } else {
2236 // Call to a keyed property. 2171 // Call to a keyed property.
2237 // For a synthetic property use keyed load IC followed by function call, 2172 // For a synthetic property use keyed load IC followed by function call,
2238 // for a regular property use keyed EmitCallIC. 2173 // for a regular property use EmitKeyedCallWithIC.
2239 if (prop->is_synthetic()) { 2174 if (prop->is_synthetic()) {
2240 // Do not visit the object and key subexpressions (they are shared 2175 // Do not visit the object and key subexpressions (they are shared
2241 // by all occurrences of the same rewritten parameter). 2176 // by all occurrences of the same rewritten parameter).
2242 ASSERT(prop->obj()->AsVariableProxy() != NULL); 2177 ASSERT(prop->obj()->AsVariableProxy() != NULL);
2243 ASSERT(prop->obj()->AsVariableProxy()->var()->AsSlot() != NULL); 2178 ASSERT(prop->obj()->AsVariableProxy()->var()->AsSlot() != NULL);
2244 Slot* slot = prop->obj()->AsVariableProxy()->var()->AsSlot(); 2179 Slot* slot = prop->obj()->AsVariableProxy()->var()->AsSlot();
2245 MemOperand operand = EmitSlotSearch(slot, rdx); 2180 MemOperand operand = EmitSlotSearch(slot, rdx);
2246 __ movq(rdx, operand); 2181 __ movq(rdx, operand);
2247 2182
2248 ASSERT(prop->key()->AsLiteral() != NULL); 2183 ASSERT(prop->key()->AsLiteral() != NULL);
2249 ASSERT(prop->key()->AsLiteral()->handle()->IsSmi()); 2184 ASSERT(prop->key()->AsLiteral()->handle()->IsSmi());
2250 __ Move(rax, prop->key()->AsLiteral()->handle()); 2185 __ Move(rax, prop->key()->AsLiteral()->handle());
2251 2186
2252 // Record source code position for IC call. 2187 // Record source code position for IC call.
2253 SetSourcePosition(prop->position()); 2188 SetSourcePosition(prop->position());
2254 2189
2255 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); 2190 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
2256 EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(prop)); 2191 __ call(ic, RelocInfo::CODE_TARGET, GetPropertyId(prop));
2257 // Push result (function). 2192 // Push result (function).
2258 __ push(rax); 2193 __ push(rax);
2259 // Push Global receiver. 2194 // Push Global receiver.
2260 __ movq(rcx, GlobalObjectOperand()); 2195 __ movq(rcx, GlobalObjectOperand());
2261 __ push(FieldOperand(rcx, GlobalObject::kGlobalReceiverOffset)); 2196 __ push(FieldOperand(rcx, GlobalObject::kGlobalReceiverOffset));
2262 EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS); 2197 EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS);
2263 } else { 2198 } else {
2264 { PreservePositionScope scope(masm()->positions_recorder()); 2199 { PreservePositionScope scope(masm()->positions_recorder());
2265 VisitForStackValue(prop->obj()); 2200 VisitForStackValue(prop->obj());
2266 } 2201 }
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
2372 2307
2373 __ JumpIfSmi(rax, if_false); 2308 __ JumpIfSmi(rax, if_false);
2374 __ CompareRoot(rax, Heap::kNullValueRootIndex); 2309 __ CompareRoot(rax, Heap::kNullValueRootIndex);
2375 __ j(equal, if_true); 2310 __ j(equal, if_true);
2376 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); 2311 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
2377 // Undetectable objects behave like undefined when tested with typeof. 2312 // Undetectable objects behave like undefined when tested with typeof.
2378 __ testb(FieldOperand(rbx, Map::kBitFieldOffset), 2313 __ testb(FieldOperand(rbx, Map::kBitFieldOffset),
2379 Immediate(1 << Map::kIsUndetectable)); 2314 Immediate(1 << Map::kIsUndetectable));
2380 __ j(not_zero, if_false); 2315 __ j(not_zero, if_false);
2381 __ movzxbq(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); 2316 __ movzxbq(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
2382 __ cmpq(rbx, Immediate(FIRST_JS_OBJECT_TYPE)); 2317 __ cmpq(rbx, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
2383 __ j(below, if_false); 2318 __ j(below, if_false);
2384 __ cmpq(rbx, Immediate(LAST_JS_OBJECT_TYPE)); 2319 __ cmpq(rbx, Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE));
2385 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 2320 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2386 Split(below_equal, if_true, if_false, fall_through); 2321 Split(below_equal, if_true, if_false, fall_through);
2387 2322
2388 context()->Plug(if_true, if_false); 2323 context()->Plug(if_true, if_false);
2389 } 2324 }
2390 2325
2391 2326
2392 void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) { 2327 void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) {
2393 ASSERT(args->length() == 1); 2328 ASSERT(args->length() == 1);
2394 2329
2395 VisitForAccumulatorValue(args->at(0)); 2330 VisitForAccumulatorValue(args->at(0));
2396 2331
2397 Label materialize_true, materialize_false; 2332 Label materialize_true, materialize_false;
2398 Label* if_true = NULL; 2333 Label* if_true = NULL;
2399 Label* if_false = NULL; 2334 Label* if_false = NULL;
2400 Label* fall_through = NULL; 2335 Label* fall_through = NULL;
2401 context()->PrepareTest(&materialize_true, &materialize_false, 2336 context()->PrepareTest(&materialize_true, &materialize_false,
2402 &if_true, &if_false, &fall_through); 2337 &if_true, &if_false, &fall_through);
2403 2338
2404 __ JumpIfSmi(rax, if_false); 2339 __ JumpIfSmi(rax, if_false);
2405 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rbx); 2340 __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rbx);
2406 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 2341 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2407 Split(above_equal, if_true, if_false, fall_through); 2342 Split(above_equal, if_true, if_false, fall_through);
2408 2343
2409 context()->Plug(if_true, if_false); 2344 context()->Plug(if_true, if_false);
2410 } 2345 }
2411 2346
2412 2347
2413 void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) { 2348 void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) {
2414 ASSERT(args->length() == 1); 2349 ASSERT(args->length() == 1);
2415 2350
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
2633 } 2568 }
2634 2569
2635 2570
2636 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) { 2571 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) {
2637 ASSERT(args->length() == 1); 2572 ASSERT(args->length() == 1);
2638 2573
2639 // ArgumentsAccessStub expects the key in rdx and the formal 2574 // ArgumentsAccessStub expects the key in rdx and the formal
2640 // parameter count in rax. 2575 // parameter count in rax.
2641 VisitForAccumulatorValue(args->at(0)); 2576 VisitForAccumulatorValue(args->at(0));
2642 __ movq(rdx, rax); 2577 __ movq(rdx, rax);
2643 __ Move(rax, Smi::FromInt(scope()->num_parameters())); 2578 __ Move(rax, Smi::FromInt(info_->scope()->num_parameters()));
2644 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); 2579 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
2645 __ CallStub(&stub); 2580 __ CallStub(&stub);
2646 context()->Plug(rax); 2581 context()->Plug(rax);
2647 } 2582 }
2648 2583
2649 2584
2650 void FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) { 2585 void FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) {
2651 ASSERT(args->length() == 0); 2586 ASSERT(args->length() == 0);
2652 2587
2653 Label exit; 2588 Label exit;
2654 // Get the number of formal parameters. 2589 // Get the number of formal parameters.
2655 __ Move(rax, Smi::FromInt(scope()->num_parameters())); 2590 __ Move(rax, Smi::FromInt(info_->scope()->num_parameters()));
2656 2591
2657 // Check if the calling frame is an arguments adaptor frame. 2592 // Check if the calling frame is an arguments adaptor frame.
2658 __ movq(rbx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 2593 __ movq(rbx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
2659 __ Cmp(Operand(rbx, StandardFrameConstants::kContextOffset), 2594 __ Cmp(Operand(rbx, StandardFrameConstants::kContextOffset),
2660 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); 2595 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
2661 __ j(not_equal, &exit, Label::kNear); 2596 __ j(not_equal, &exit, Label::kNear);
2662 2597
2663 // Arguments adaptor case: Read the arguments length from the 2598 // Arguments adaptor case: Read the arguments length from the
2664 // adaptor frame. 2599 // adaptor frame.
2665 __ movq(rax, Operand(rbx, ArgumentsAdaptorFrameConstants::kLengthOffset)); 2600 __ movq(rax, Operand(rbx, ArgumentsAdaptorFrameConstants::kLengthOffset));
2666 2601
2667 __ bind(&exit); 2602 __ bind(&exit);
2668 if (FLAG_debug_code) __ AbortIfNotSmi(rax); 2603 if (FLAG_debug_code) __ AbortIfNotSmi(rax);
2669 context()->Plug(rax); 2604 context()->Plug(rax);
2670 } 2605 }
2671 2606
2672 2607
2673 void FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) { 2608 void FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) {
2674 ASSERT(args->length() == 1); 2609 ASSERT(args->length() == 1);
2675 Label done, null, function, non_function_constructor; 2610 Label done, null, function, non_function_constructor;
2676 2611
2677 VisitForAccumulatorValue(args->at(0)); 2612 VisitForAccumulatorValue(args->at(0));
2678 2613
2679 // If the object is a smi, we return null. 2614 // If the object is a smi, we return null.
2680 __ JumpIfSmi(rax, &null); 2615 __ JumpIfSmi(rax, &null);
2681 2616
2682 // Check that the object is a JS object but take special care of JS 2617 // Check that the object is a JS object but take special care of JS
2683 // functions to make sure they have 'Function' as their class. 2618 // functions to make sure they have 'Function' as their class.
2684 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rax); // Map is now in rax. 2619 __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rax);
2620 // Map is now in rax.
2685 __ j(below, &null); 2621 __ j(below, &null);
2686 2622
2687 // As long as JS_FUNCTION_TYPE is the last instance type and it is 2623 // As long as LAST_CALLABLE_SPEC_OBJECT_TYPE is the last instance type, and
2688 // right after LAST_JS_OBJECT_TYPE, we can avoid checking for 2624 // FIRST_CALLABLE_SPEC_OBJECT_TYPE comes right after
2689 // LAST_JS_OBJECT_TYPE. 2625 // LAST_NONCALLABLE_SPEC_OBJECT_TYPE, we can avoid checking for the latter.
2690 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); 2626 STATIC_ASSERT(LAST_TYPE == LAST_CALLABLE_SPEC_OBJECT_TYPE);
2691 ASSERT(JS_FUNCTION_TYPE == LAST_JS_OBJECT_TYPE + 1); 2627 STATIC_ASSERT(FIRST_CALLABLE_SPEC_OBJECT_TYPE ==
2692 __ CmpInstanceType(rax, JS_FUNCTION_TYPE); 2628 LAST_NONCALLABLE_SPEC_OBJECT_TYPE + 1);
2693 __ j(equal, &function); 2629 __ CmpInstanceType(rax, FIRST_CALLABLE_SPEC_OBJECT_TYPE);
2630 __ j(above_equal, &function);
2694 2631
2695 // Check if the constructor in the map is a function. 2632 // Check if the constructor in the map is a function.
2696 __ movq(rax, FieldOperand(rax, Map::kConstructorOffset)); 2633 __ movq(rax, FieldOperand(rax, Map::kConstructorOffset));
2697 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); 2634 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx);
2698 __ j(not_equal, &non_function_constructor); 2635 __ j(not_equal, &non_function_constructor);
2699 2636
2700 // rax now contains the constructor function. Grab the 2637 // rax now contains the constructor function. Grab the
2701 // instance class name from there. 2638 // instance class name from there.
2702 __ movq(rax, FieldOperand(rax, JSFunction::kSharedFunctionInfoOffset)); 2639 __ movq(rax, FieldOperand(rax, JSFunction::kSharedFunctionInfoOffset));
2703 __ movq(rax, FieldOperand(rax, SharedFunctionInfo::kInstanceClassNameOffset)); 2640 __ movq(rax, FieldOperand(rax, SharedFunctionInfo::kInstanceClassNameOffset));
(...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after
3066 3003
3067 int arg_count = args->length() - 2; // 2 ~ receiver and function. 3004 int arg_count = args->length() - 2; // 2 ~ receiver and function.
3068 for (int i = 0; i < arg_count + 1; i++) { 3005 for (int i = 0; i < arg_count + 1; i++) {
3069 VisitForStackValue(args->at(i)); 3006 VisitForStackValue(args->at(i));
3070 } 3007 }
3071 VisitForAccumulatorValue(args->last()); // Function. 3008 VisitForAccumulatorValue(args->last()); // Function.
3072 3009
3073 // InvokeFunction requires the function in rdi. Move it in there. 3010 // InvokeFunction requires the function in rdi. Move it in there.
3074 __ movq(rdi, result_register()); 3011 __ movq(rdi, result_register());
3075 ParameterCount count(arg_count); 3012 ParameterCount count(arg_count);
3076 __ InvokeFunction(rdi, count, CALL_FUNCTION); 3013 __ InvokeFunction(rdi, count, CALL_FUNCTION,
3014 NullCallWrapper(), CALL_AS_METHOD);
3077 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 3015 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
3078 context()->Plug(rax); 3016 context()->Plug(rax);
3079 } 3017 }
3080 3018
3081 3019
3082 void FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) { 3020 void FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) {
3083 RegExpConstructResultStub stub; 3021 RegExpConstructResultStub stub;
3084 ASSERT(args->length() == 3); 3022 ASSERT(args->length() == 3);
3085 VisitForStackValue(args->at(0)); 3023 VisitForStackValue(args->at(0));
3086 VisitForStackValue(args->at(1)); 3024 VisitForStackValue(args->at(1));
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after
3342 // other stack fields, and clear the direction flag in anticipation 3280 // other stack fields, and clear the direction flag in anticipation
3343 // of calling CopyBytes. 3281 // of calling CopyBytes.
3344 __ subq(rsp, Immediate(2 * kPointerSize)); 3282 __ subq(rsp, Immediate(2 * kPointerSize));
3345 __ cld(); 3283 __ cld();
3346 // Check that the array is a JSArray 3284 // Check that the array is a JSArray
3347 __ JumpIfSmi(array, &bailout); 3285 __ JumpIfSmi(array, &bailout);
3348 __ CmpObjectType(array, JS_ARRAY_TYPE, scratch); 3286 __ CmpObjectType(array, JS_ARRAY_TYPE, scratch);
3349 __ j(not_equal, &bailout); 3287 __ j(not_equal, &bailout);
3350 3288
3351 // Check that the array has fast elements. 3289 // Check that the array has fast elements.
3352 __ testb(FieldOperand(scratch, Map::kBitField2Offset), 3290 __ CheckFastElements(scratch, &bailout);
3353 Immediate(1 << Map::kHasFastElements));
3354 __ j(zero, &bailout);
3355 3291
3356 // Array has fast elements, so its length must be a smi. 3292 // Array has fast elements, so its length must be a smi.
3357 // If the array has length zero, return the empty string. 3293 // If the array has length zero, return the empty string.
3358 __ movq(array_length, FieldOperand(array, JSArray::kLengthOffset)); 3294 __ movq(array_length, FieldOperand(array, JSArray::kLengthOffset));
3359 __ SmiCompare(array_length, Smi::FromInt(0)); 3295 __ SmiCompare(array_length, Smi::FromInt(0));
3360 __ j(not_zero, &non_trivial_array); 3296 __ j(not_zero, &non_trivial_array);
3361 __ LoadRoot(rax, Heap::kEmptyStringRootIndex); 3297 __ LoadRoot(rax, Heap::kEmptyStringRootIndex);
3362 __ jmp(&return_result); 3298 __ jmp(&return_result);
3363 3299
3364 // Save the array length on the stack. 3300 // Save the array length on the stack.
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after
3590 __ movq(rax, result_operand); 3526 __ movq(rax, result_operand);
3591 3527
3592 __ bind(&return_result); 3528 __ bind(&return_result);
3593 // Drop temp values from the stack, and restore context register. 3529 // Drop temp values from the stack, and restore context register.
3594 __ addq(rsp, Immediate(3 * kPointerSize)); 3530 __ addq(rsp, Immediate(3 * kPointerSize));
3595 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 3531 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
3596 context()->Plug(rax); 3532 context()->Plug(rax);
3597 } 3533 }
3598 3534
3599 3535
3536 void FullCodeGenerator::EmitIsNativeOrStrictMode(ZoneList<Expression*>* args) {
3537 ASSERT(args->length() == 1);
3538
3539 // Load the function into rax.
3540 VisitForAccumulatorValue(args->at(0));
3541
3542 // Prepare for the test.
3543 Label materialize_true, materialize_false;
3544 Label* if_true = NULL;
3545 Label* if_false = NULL;
3546 Label* fall_through = NULL;
3547 context()->PrepareTest(&materialize_true, &materialize_false,
3548 &if_true, &if_false, &fall_through);
3549
3550 // Test for strict mode function.
3551 __ movq(rdx, FieldOperand(rax, JSFunction::kSharedFunctionInfoOffset));
3552 __ testb(FieldOperand(rdx, SharedFunctionInfo::kStrictModeByteOffset),
3553 Immediate(1 << SharedFunctionInfo::kStrictModeBitWithinByte));
3554 __ j(not_equal, if_true);
3555
3556 // Test for native function.
3557 __ testb(FieldOperand(rdx, SharedFunctionInfo::kNativeByteOffset),
3558 Immediate(1 << SharedFunctionInfo::kNativeBitWithinByte));
3559 __ j(not_equal, if_true);
3560
3561 // Not native or strict-mode function.
3562 __ jmp(if_false);
3563
3564 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
3565 context()->Plug(if_true, if_false);
3566 }
3567
3568
3600 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { 3569 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
3601 Handle<String> name = expr->name(); 3570 Handle<String> name = expr->name();
3602 if (name->length() > 0 && name->Get(0) == '_') { 3571 if (name->length() > 0 && name->Get(0) == '_') {
3603 Comment cmnt(masm_, "[ InlineRuntimeCall"); 3572 Comment cmnt(masm_, "[ InlineRuntimeCall");
3604 EmitInlineRuntimeCall(expr); 3573 EmitInlineRuntimeCall(expr);
3605 return; 3574 return;
3606 } 3575 }
3607 3576
3608 Comment cmnt(masm_, "[ CallRuntime"); 3577 Comment cmnt(masm_, "[ CallRuntime");
3609 ZoneList<Expression*>* args = expr->arguments(); 3578 ZoneList<Expression*>* args = expr->arguments();
(...skipping 10 matching lines...) Expand all
3620 VisitForStackValue(args->at(i)); 3589 VisitForStackValue(args->at(i));
3621 } 3590 }
3622 3591
3623 if (expr->is_jsruntime()) { 3592 if (expr->is_jsruntime()) {
3624 // Call the JS runtime function using a call IC. 3593 // Call the JS runtime function using a call IC.
3625 __ Move(rcx, expr->name()); 3594 __ Move(rcx, expr->name());
3626 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 3595 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
3627 RelocInfo::Mode mode = RelocInfo::CODE_TARGET; 3596 RelocInfo::Mode mode = RelocInfo::CODE_TARGET;
3628 Handle<Code> ic = 3597 Handle<Code> ic =
3629 ISOLATE->stub_cache()->ComputeCallInitialize(arg_count, in_loop, mode); 3598 ISOLATE->stub_cache()->ComputeCallInitialize(arg_count, in_loop, mode);
3630 EmitCallIC(ic, mode, expr->id()); 3599 __ call(ic, mode, expr->id());
3631 // Restore context register. 3600 // Restore context register.
3632 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 3601 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
3633 } else { 3602 } else {
3634 __ CallRuntime(expr->function(), arg_count); 3603 __ CallRuntime(expr->function(), arg_count);
3635 } 3604 }
3636 context()->Plug(rax); 3605 context()->Plug(rax);
3637 } 3606 }
3638 3607
3639 3608
3640 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { 3609 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
3723 } 3692 }
3724 __ CallRuntime(Runtime::kTypeof, 1); 3693 __ CallRuntime(Runtime::kTypeof, 1);
3725 context()->Plug(rax); 3694 context()->Plug(rax);
3726 break; 3695 break;
3727 } 3696 }
3728 3697
3729 case Token::ADD: { 3698 case Token::ADD: {
3730 Comment cmt(masm_, "[ UnaryOperation (ADD)"); 3699 Comment cmt(masm_, "[ UnaryOperation (ADD)");
3731 VisitForAccumulatorValue(expr->expression()); 3700 VisitForAccumulatorValue(expr->expression());
3732 Label no_conversion; 3701 Label no_conversion;
3733 Condition is_smi = masm_->CheckSmi(result_register()); 3702 __ JumpIfSmi(result_register(), &no_conversion);
3734 __ j(is_smi, &no_conversion);
3735 ToNumberStub convert_stub; 3703 ToNumberStub convert_stub;
3736 __ CallStub(&convert_stub); 3704 __ CallStub(&convert_stub);
3737 __ bind(&no_conversion); 3705 __ bind(&no_conversion);
3738 context()->Plug(result_register()); 3706 context()->Plug(result_register());
3739 break; 3707 break;
3740 } 3708 }
3741 3709
3742 case Token::SUB: 3710 case Token::SUB:
3743 EmitUnaryOperation(expr, "[ UnaryOperation (SUB)"); 3711 EmitUnaryOperation(expr, "[ UnaryOperation (SUB)");
3744 break; 3712 break;
(...skipping 13 matching lines...) Expand all
3758 // TODO(svenpanne): Allowing format strings in Comment would be nice here... 3726 // TODO(svenpanne): Allowing format strings in Comment would be nice here...
3759 Comment cmt(masm_, comment); 3727 Comment cmt(masm_, comment);
3760 bool can_overwrite = expr->expression()->ResultOverwriteAllowed(); 3728 bool can_overwrite = expr->expression()->ResultOverwriteAllowed();
3761 UnaryOverwriteMode overwrite = 3729 UnaryOverwriteMode overwrite =
3762 can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; 3730 can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
3763 UnaryOpStub stub(expr->op(), overwrite); 3731 UnaryOpStub stub(expr->op(), overwrite);
3764 // UnaryOpStub expects the argument to be in the 3732 // UnaryOpStub expects the argument to be in the
3765 // accumulator register rax. 3733 // accumulator register rax.
3766 VisitForAccumulatorValue(expr->expression()); 3734 VisitForAccumulatorValue(expr->expression());
3767 SetSourcePosition(expr->position()); 3735 SetSourcePosition(expr->position());
3768 EmitCallIC(stub.GetCode(), NULL, expr->id()); 3736 __ call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id());
3769 context()->Plug(rax); 3737 context()->Plug(rax);
3770 } 3738 }
3771 3739
3772 3740
3773 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { 3741 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
3774 Comment cmnt(masm_, "[ CountOperation"); 3742 Comment cmnt(masm_, "[ CountOperation");
3775 SetSourcePosition(expr->position()); 3743 SetSourcePosition(expr->position());
3776 3744
3777 // Invalid left-hand-sides are rewritten to have a 'throw 3745 // Invalid left-hand-sides are rewritten to have a 'throw
3778 // ReferenceError' as the left-hand side. 3746 // ReferenceError' as the left-hand side.
3779 if (!expr->expression()->IsValidLeftHandSide()) { 3747 if (!expr->expression()->IsValidLeftHandSide()) {
3780 VisitForEffect(expr->expression()); 3748 VisitForEffect(expr->expression());
3781 return; 3749 return;
3782 } 3750 }
3783 3751
3784 // Expression can only be a property, a global or a (parameter or local) 3752 // Expression can only be a property, a global or a (parameter or local)
3785 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. 3753 // slot.
3786 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 3754 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
3787 LhsKind assign_type = VARIABLE; 3755 LhsKind assign_type = VARIABLE;
3788 Property* prop = expr->expression()->AsProperty(); 3756 Property* prop = expr->expression()->AsProperty();
3789 // In case of a property we use the uninitialized expression context 3757 // In case of a property we use the uninitialized expression context
3790 // of the key to detect a named property. 3758 // of the key to detect a named property.
3791 if (prop != NULL) { 3759 if (prop != NULL) {
3792 assign_type = 3760 assign_type =
3793 (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; 3761 (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY;
3794 } 3762 }
3795 3763
3796 // Evaluate expression and get value. 3764 // Evaluate expression and get value.
3797 if (assign_type == VARIABLE) { 3765 if (assign_type == VARIABLE) {
3798 ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); 3766 ASSERT(expr->expression()->AsVariableProxy()->var() != NULL);
3799 AccumulatorValueContext context(this); 3767 AccumulatorValueContext context(this);
3800 EmitVariableLoad(expr->expression()->AsVariableProxy()->var()); 3768 EmitVariableLoad(expr->expression()->AsVariableProxy()->var());
3801 } else { 3769 } else {
3802 // Reserve space for result of postfix operation. 3770 // Reserve space for result of postfix operation.
3803 if (expr->is_postfix() && !context()->IsEffect()) { 3771 if (expr->is_postfix() && !context()->IsEffect()) {
3804 __ Push(Smi::FromInt(0)); 3772 __ Push(Smi::FromInt(0));
3805 } 3773 }
3806 if (assign_type == NAMED_PROPERTY) { 3774 if (assign_type == NAMED_PROPERTY) {
3807 VisitForAccumulatorValue(prop->obj()); 3775 VisitForAccumulatorValue(prop->obj());
3808 __ push(rax); // Copy of receiver, needed for later store. 3776 __ push(rax); // Copy of receiver, needed for later store.
3809 EmitNamedPropertyLoad(prop); 3777 EmitNamedPropertyLoad(prop);
3810 } else { 3778 } else {
3811 if (prop->is_arguments_access()) { 3779 VisitForStackValue(prop->obj());
3812 VariableProxy* obj_proxy = prop->obj()->AsVariableProxy(); 3780 VisitForAccumulatorValue(prop->key());
3813 MemOperand slot_operand =
3814 EmitSlotSearch(obj_proxy->var()->AsSlot(), rcx);
3815 __ push(slot_operand);
3816 __ Move(rax, prop->key()->AsLiteral()->handle());
3817 } else {
3818 VisitForStackValue(prop->obj());
3819 VisitForAccumulatorValue(prop->key());
3820 }
3821 __ movq(rdx, Operand(rsp, 0)); // Leave receiver on stack 3781 __ movq(rdx, Operand(rsp, 0)); // Leave receiver on stack
3822 __ push(rax); // Copy of key, needed for later store. 3782 __ push(rax); // Copy of key, needed for later store.
3823 EmitKeyedPropertyLoad(prop); 3783 EmitKeyedPropertyLoad(prop);
3824 } 3784 }
3825 } 3785 }
3826 3786
3827 // We need a second deoptimization point after loading the value 3787 // We need a second deoptimization point after loading the value
3828 // in case evaluating the property load my have a side effect. 3788 // in case evaluating the property load my have a side effect.
3829 if (assign_type == VARIABLE) { 3789 if (assign_type == VARIABLE) {
3830 PrepareForBailout(expr->expression(), TOS_REG); 3790 PrepareForBailout(expr->expression(), TOS_REG);
3831 } else { 3791 } else {
3832 PrepareForBailoutForId(expr->CountId(), TOS_REG); 3792 PrepareForBailoutForId(expr->CountId(), TOS_REG);
3833 } 3793 }
3834 3794
3835 // Call ToNumber only if operand is not a smi. 3795 // Call ToNumber only if operand is not a smi.
3836 Label no_conversion; 3796 Label no_conversion;
3837 Condition is_smi; 3797 __ JumpIfSmi(rax, &no_conversion, Label::kNear);
3838 is_smi = masm_->CheckSmi(rax);
3839 __ j(is_smi, &no_conversion, Label::kNear);
3840 ToNumberStub convert_stub; 3798 ToNumberStub convert_stub;
3841 __ CallStub(&convert_stub); 3799 __ CallStub(&convert_stub);
3842 __ bind(&no_conversion); 3800 __ bind(&no_conversion);
3843 3801
3844 // Save result for postfix expressions. 3802 // Save result for postfix expressions.
3845 if (expr->is_postfix()) { 3803 if (expr->is_postfix()) {
3846 if (!context()->IsEffect()) { 3804 if (!context()->IsEffect()) {
3847 // Save the result on the stack. If we have a named or keyed property 3805 // Save the result on the stack. If we have a named or keyed property
3848 // we store the result under the receiver that is currently on top 3806 // we store the result under the receiver that is currently on top
3849 // of the stack. 3807 // of the stack.
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
3889 SetSourcePosition(expr->position()); 3847 SetSourcePosition(expr->position());
3890 3848
3891 // Call stub for +1/-1. 3849 // Call stub for +1/-1.
3892 BinaryOpStub stub(expr->binary_op(), NO_OVERWRITE); 3850 BinaryOpStub stub(expr->binary_op(), NO_OVERWRITE);
3893 if (expr->op() == Token::INC) { 3851 if (expr->op() == Token::INC) {
3894 __ Move(rdx, Smi::FromInt(1)); 3852 __ Move(rdx, Smi::FromInt(1));
3895 } else { 3853 } else {
3896 __ movq(rdx, rax); 3854 __ movq(rdx, rax);
3897 __ Move(rax, Smi::FromInt(1)); 3855 __ Move(rax, Smi::FromInt(1));
3898 } 3856 }
3899 EmitCallIC(stub.GetCode(), &patch_site, expr->CountId()); 3857 __ call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->CountId());
3858 patch_site.EmitPatchInfo();
3900 __ bind(&done); 3859 __ bind(&done);
3901 3860
3902 // Store the value returned in rax. 3861 // Store the value returned in rax.
3903 switch (assign_type) { 3862 switch (assign_type) {
3904 case VARIABLE: 3863 case VARIABLE:
3905 if (expr->is_postfix()) { 3864 if (expr->is_postfix()) {
3906 // Perform the assignment as if via '='. 3865 // Perform the assignment as if via '='.
3907 { EffectContext context(this); 3866 { EffectContext context(this);
3908 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 3867 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
3909 Token::ASSIGN); 3868 Token::ASSIGN);
(...skipping 12 matching lines...) Expand all
3922 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 3881 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
3923 context()->Plug(rax); 3882 context()->Plug(rax);
3924 } 3883 }
3925 break; 3884 break;
3926 case NAMED_PROPERTY: { 3885 case NAMED_PROPERTY: {
3927 __ Move(rcx, prop->key()->AsLiteral()->handle()); 3886 __ Move(rcx, prop->key()->AsLiteral()->handle());
3928 __ pop(rdx); 3887 __ pop(rdx);
3929 Handle<Code> ic = is_strict_mode() 3888 Handle<Code> ic = is_strict_mode()
3930 ? isolate()->builtins()->StoreIC_Initialize_Strict() 3889 ? isolate()->builtins()->StoreIC_Initialize_Strict()
3931 : isolate()->builtins()->StoreIC_Initialize(); 3890 : isolate()->builtins()->StoreIC_Initialize();
3932 EmitCallIC(ic, RelocInfo::CODE_TARGET, expr->id()); 3891 __ call(ic, RelocInfo::CODE_TARGET, expr->id());
3933 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 3892 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
3934 if (expr->is_postfix()) { 3893 if (expr->is_postfix()) {
3935 if (!context()->IsEffect()) { 3894 if (!context()->IsEffect()) {
3936 context()->PlugTOS(); 3895 context()->PlugTOS();
3937 } 3896 }
3938 } else { 3897 } else {
3939 context()->Plug(rax); 3898 context()->Plug(rax);
3940 } 3899 }
3941 break; 3900 break;
3942 } 3901 }
3943 case KEYED_PROPERTY: { 3902 case KEYED_PROPERTY: {
3944 __ pop(rcx); 3903 __ pop(rcx);
3945 __ pop(rdx); 3904 __ pop(rdx);
3946 Handle<Code> ic = is_strict_mode() 3905 Handle<Code> ic = is_strict_mode()
3947 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() 3906 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
3948 : isolate()->builtins()->KeyedStoreIC_Initialize(); 3907 : isolate()->builtins()->KeyedStoreIC_Initialize();
3949 EmitCallIC(ic, RelocInfo::CODE_TARGET, expr->id()); 3908 __ call(ic, RelocInfo::CODE_TARGET, expr->id());
3950 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 3909 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
3951 if (expr->is_postfix()) { 3910 if (expr->is_postfix()) {
3952 if (!context()->IsEffect()) { 3911 if (!context()->IsEffect()) {
3953 context()->PlugTOS(); 3912 context()->PlugTOS();
3954 } 3913 }
3955 } else { 3914 } else {
3956 context()->Plug(rax); 3915 context()->Plug(rax);
3957 } 3916 }
3958 break; 3917 break;
3959 } 3918 }
3960 } 3919 }
3961 } 3920 }
3962 3921
3963 3922
3964 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { 3923 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
3965 VariableProxy* proxy = expr->AsVariableProxy(); 3924 VariableProxy* proxy = expr->AsVariableProxy();
3966 ASSERT(!context()->IsEffect()); 3925 ASSERT(!context()->IsEffect());
3967 ASSERT(!context()->IsTest()); 3926 ASSERT(!context()->IsTest());
3968 3927
3969 if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) { 3928 if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) {
3970 Comment cmnt(masm_, "Global variable"); 3929 Comment cmnt(masm_, "Global variable");
3971 __ Move(rcx, proxy->name()); 3930 __ Move(rcx, proxy->name());
3972 __ movq(rax, GlobalObjectOperand()); 3931 __ movq(rax, GlobalObjectOperand());
3973 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 3932 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
3974 // Use a regular load, not a contextual load, to avoid a reference 3933 // Use a regular load, not a contextual load, to avoid a reference
3975 // error. 3934 // error.
3976 EmitCallIC(ic, RelocInfo::CODE_TARGET, AstNode::kNoNumber); 3935 __ call(ic);
3977 PrepareForBailout(expr, TOS_REG); 3936 PrepareForBailout(expr, TOS_REG);
3978 context()->Plug(rax); 3937 context()->Plug(rax);
3979 } else if (proxy != NULL && 3938 } else if (proxy != NULL &&
3980 proxy->var()->AsSlot() != NULL && 3939 proxy->var()->AsSlot() != NULL &&
3981 proxy->var()->AsSlot()->type() == Slot::LOOKUP) { 3940 proxy->var()->AsSlot()->type() == Slot::LOOKUP) {
3982 Label done, slow; 3941 Label done, slow;
3983 3942
3984 // Generate code for loading from variables potentially shadowed 3943 // Generate code for loading from variables potentially shadowed
3985 // by eval-introduced variables. 3944 // by eval-introduced variables.
3986 Slot* slot = proxy->var()->AsSlot(); 3945 Slot* slot = proxy->var()->AsSlot();
3987 EmitDynamicLoadFromSlotFastCase(slot, INSIDE_TYPEOF, &slow, &done); 3946 EmitDynamicLoadFromSlotFastCase(slot, INSIDE_TYPEOF, &slow, &done);
3988 3947
3989 __ bind(&slow); 3948 __ bind(&slow);
3990 __ push(rsi); 3949 __ push(rsi);
3991 __ Push(proxy->name()); 3950 __ Push(proxy->name());
3992 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); 3951 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
3993 PrepareForBailout(expr, TOS_REG); 3952 PrepareForBailout(expr, TOS_REG);
3994 __ bind(&done); 3953 __ bind(&done);
3995 3954
3996 context()->Plug(rax); 3955 context()->Plug(rax);
3997 } else { 3956 } else {
3998 // This expression cannot throw a reference error at the top level. 3957 // This expression cannot throw a reference error at the top level.
3999 context()->HandleExpression(expr); 3958 VisitInCurrentContext(expr);
4000 } 3959 }
4001 } 3960 }
4002 3961
4003 3962
4004 bool FullCodeGenerator::TryLiteralCompare(Token::Value op, 3963 void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
4005 Expression* left, 3964 Handle<String> check,
4006 Expression* right, 3965 Label* if_true,
4007 Label* if_true, 3966 Label* if_false,
4008 Label* if_false, 3967 Label* fall_through) {
4009 Label* fall_through) {
4010 if (op != Token::EQ && op != Token::EQ_STRICT) return false;
4011
4012 // Check for the pattern: typeof <expression> == <string literal>.
4013 Literal* right_literal = right->AsLiteral();
4014 if (right_literal == NULL) return false;
4015 Handle<Object> right_literal_value = right_literal->handle();
4016 if (!right_literal_value->IsString()) return false;
4017 UnaryOperation* left_unary = left->AsUnaryOperation();
4018 if (left_unary == NULL || left_unary->op() != Token::TYPEOF) return false;
4019 Handle<String> check = Handle<String>::cast(right_literal_value);
4020
4021 { AccumulatorValueContext context(this); 3968 { AccumulatorValueContext context(this);
4022 VisitForTypeofValue(left_unary->expression()); 3969 VisitForTypeofValue(expr);
4023 } 3970 }
4024 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 3971 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
4025 3972
4026 if (check->Equals(isolate()->heap()->number_symbol())) { 3973 if (check->Equals(isolate()->heap()->number_symbol())) {
4027 __ JumpIfSmi(rax, if_true); 3974 __ JumpIfSmi(rax, if_true);
4028 __ movq(rax, FieldOperand(rax, HeapObject::kMapOffset)); 3975 __ movq(rax, FieldOperand(rax, HeapObject::kMapOffset));
4029 __ CompareRoot(rax, Heap::kHeapNumberMapRootIndex); 3976 __ CompareRoot(rax, Heap::kHeapNumberMapRootIndex);
4030 Split(equal, if_true, if_false, fall_through); 3977 Split(equal, if_true, if_false, fall_through);
4031 } else if (check->Equals(isolate()->heap()->string_symbol())) { 3978 } else if (check->Equals(isolate()->heap()->string_symbol())) {
4032 __ JumpIfSmi(rax, if_false); 3979 __ JumpIfSmi(rax, if_false);
(...skipping 12 matching lines...) Expand all
4045 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); 3992 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
4046 __ j(equal, if_true); 3993 __ j(equal, if_true);
4047 __ JumpIfSmi(rax, if_false); 3994 __ JumpIfSmi(rax, if_false);
4048 // Check for undetectable objects => true. 3995 // Check for undetectable objects => true.
4049 __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset)); 3996 __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset));
4050 __ testb(FieldOperand(rdx, Map::kBitFieldOffset), 3997 __ testb(FieldOperand(rdx, Map::kBitFieldOffset),
4051 Immediate(1 << Map::kIsUndetectable)); 3998 Immediate(1 << Map::kIsUndetectable));
4052 Split(not_zero, if_true, if_false, fall_through); 3999 Split(not_zero, if_true, if_false, fall_through);
4053 } else if (check->Equals(isolate()->heap()->function_symbol())) { 4000 } else if (check->Equals(isolate()->heap()->function_symbol())) {
4054 __ JumpIfSmi(rax, if_false); 4001 __ JumpIfSmi(rax, if_false);
4055 __ CmpObjectType(rax, FIRST_FUNCTION_CLASS_TYPE, rdx); 4002 STATIC_ASSERT(LAST_CALLABLE_SPEC_OBJECT_TYPE == LAST_TYPE);
4003 __ CmpObjectType(rax, FIRST_CALLABLE_SPEC_OBJECT_TYPE, rdx);
4056 Split(above_equal, if_true, if_false, fall_through); 4004 Split(above_equal, if_true, if_false, fall_through);
4057 } else if (check->Equals(isolate()->heap()->object_symbol())) { 4005 } else if (check->Equals(isolate()->heap()->object_symbol())) {
4058 __ JumpIfSmi(rax, if_false); 4006 __ JumpIfSmi(rax, if_false);
4059 __ CompareRoot(rax, Heap::kNullValueRootIndex); 4007 __ CompareRoot(rax, Heap::kNullValueRootIndex);
4060 __ j(equal, if_true); 4008 __ j(equal, if_true);
4061 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rdx); 4009 __ CmpObjectType(rax, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, rdx);
4062 __ j(below, if_false); 4010 __ j(below, if_false);
4063 __ CmpInstanceType(rdx, FIRST_FUNCTION_CLASS_TYPE); 4011 __ CmpInstanceType(rdx, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
4064 __ j(above_equal, if_false); 4012 __ j(above, if_false);
4065 // Check for undetectable objects => false. 4013 // Check for undetectable objects => false.
4066 __ testb(FieldOperand(rdx, Map::kBitFieldOffset), 4014 __ testb(FieldOperand(rdx, Map::kBitFieldOffset),
4067 Immediate(1 << Map::kIsUndetectable)); 4015 Immediate(1 << Map::kIsUndetectable));
4068 Split(zero, if_true, if_false, fall_through); 4016 Split(zero, if_true, if_false, fall_through);
4069 } else { 4017 } else {
4070 if (if_false != fall_through) __ jmp(if_false); 4018 if (if_false != fall_through) __ jmp(if_false);
4071 } 4019 }
4072
4073 return true;
4074 } 4020 }
4075 4021
4076 4022
4023 void FullCodeGenerator::EmitLiteralCompareUndefined(Expression* expr,
4024 Label* if_true,
4025 Label* if_false,
4026 Label* fall_through) {
4027 VisitForAccumulatorValue(expr);
4028 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
4029
4030 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
4031 Split(equal, if_true, if_false, fall_through);
4032 }
4033
4034
4077 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { 4035 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
4078 Comment cmnt(masm_, "[ CompareOperation"); 4036 Comment cmnt(masm_, "[ CompareOperation");
4079 SetSourcePosition(expr->position()); 4037 SetSourcePosition(expr->position());
4080 4038
4081 // Always perform the comparison for its control flow. Pack the result 4039 // Always perform the comparison for its control flow. Pack the result
4082 // into the expression's context after the comparison is performed. 4040 // into the expression's context after the comparison is performed.
4083 Label materialize_true, materialize_false; 4041 Label materialize_true, materialize_false;
4084 Label* if_true = NULL; 4042 Label* if_true = NULL;
4085 Label* if_false = NULL; 4043 Label* if_false = NULL;
4086 Label* fall_through = NULL; 4044 Label* fall_through = NULL;
4087 context()->PrepareTest(&materialize_true, &materialize_false, 4045 context()->PrepareTest(&materialize_true, &materialize_false,
4088 &if_true, &if_false, &fall_through); 4046 &if_true, &if_false, &fall_through);
4089 4047
4090 // First we try a fast inlined version of the compare when one of 4048 // First we try a fast inlined version of the compare when one of
4091 // the operands is a literal. 4049 // the operands is a literal.
4092 Token::Value op = expr->op(); 4050 if (TryLiteralCompare(expr, if_true, if_false, fall_through)) {
4093 Expression* left = expr->left();
4094 Expression* right = expr->right();
4095 if (TryLiteralCompare(op, left, right, if_true, if_false, fall_through)) {
4096 context()->Plug(if_true, if_false); 4051 context()->Plug(if_true, if_false);
4097 return; 4052 return;
4098 } 4053 }
4099 4054
4055 Token::Value op = expr->op();
4100 VisitForStackValue(expr->left()); 4056 VisitForStackValue(expr->left());
4101 switch (op) { 4057 switch (op) {
4102 case Token::IN: 4058 case Token::IN:
4103 VisitForStackValue(expr->right()); 4059 VisitForStackValue(expr->right());
4104 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); 4060 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
4105 PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); 4061 PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
4106 __ CompareRoot(rax, Heap::kTrueValueRootIndex); 4062 __ CompareRoot(rax, Heap::kTrueValueRootIndex);
4107 Split(equal, if_true, if_false, fall_through); 4063 Split(equal, if_true, if_false, fall_through);
4108 break; 4064 break;
4109 4065
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
4164 __ or_(rcx, rax); 4120 __ or_(rcx, rax);
4165 patch_site.EmitJumpIfNotSmi(rcx, &slow_case, Label::kNear); 4121 patch_site.EmitJumpIfNotSmi(rcx, &slow_case, Label::kNear);
4166 __ cmpq(rdx, rax); 4122 __ cmpq(rdx, rax);
4167 Split(cc, if_true, if_false, NULL); 4123 Split(cc, if_true, if_false, NULL);
4168 __ bind(&slow_case); 4124 __ bind(&slow_case);
4169 } 4125 }
4170 4126
4171 // Record position and call the compare IC. 4127 // Record position and call the compare IC.
4172 SetSourcePosition(expr->position()); 4128 SetSourcePosition(expr->position());
4173 Handle<Code> ic = CompareIC::GetUninitialized(op); 4129 Handle<Code> ic = CompareIC::GetUninitialized(op);
4174 EmitCallIC(ic, &patch_site, expr->id()); 4130 __ call(ic, RelocInfo::CODE_TARGET, expr->id());
4131 patch_site.EmitPatchInfo();
4175 4132
4176 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 4133 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
4177 __ testq(rax, rax); 4134 __ testq(rax, rax);
4178 Split(cc, if_true, if_false, fall_through); 4135 Split(cc, if_true, if_false, fall_through);
4179 } 4136 }
4180 } 4137 }
4181 4138
4182 // Convert the result of the comparison into one expected for this 4139 // Convert the result of the comparison into one expected for this
4183 // expression's context. 4140 // expression's context.
4184 context()->Plug(if_true, if_false); 4141 context()->Plug(if_true, if_false);
(...skipping 11 matching lines...) Expand all
4196 4153
4197 VisitForAccumulatorValue(expr->expression()); 4154 VisitForAccumulatorValue(expr->expression());
4198 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 4155 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
4199 __ CompareRoot(rax, Heap::kNullValueRootIndex); 4156 __ CompareRoot(rax, Heap::kNullValueRootIndex);
4200 if (expr->is_strict()) { 4157 if (expr->is_strict()) {
4201 Split(equal, if_true, if_false, fall_through); 4158 Split(equal, if_true, if_false, fall_through);
4202 } else { 4159 } else {
4203 __ j(equal, if_true); 4160 __ j(equal, if_true);
4204 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); 4161 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
4205 __ j(equal, if_true); 4162 __ j(equal, if_true);
4206 Condition is_smi = masm_->CheckSmi(rax); 4163 __ JumpIfSmi(rax, if_false);
4207 __ j(is_smi, if_false);
4208 // It can be an undetectable object. 4164 // It can be an undetectable object.
4209 __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset)); 4165 __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset));
4210 __ testb(FieldOperand(rdx, Map::kBitFieldOffset), 4166 __ testb(FieldOperand(rdx, Map::kBitFieldOffset),
4211 Immediate(1 << Map::kIsUndetectable)); 4167 Immediate(1 << Map::kIsUndetectable));
4212 Split(not_zero, if_true, if_false, fall_through); 4168 Split(not_zero, if_true, if_false, fall_through);
4213 } 4169 }
4214 context()->Plug(if_true, if_false); 4170 context()->Plug(if_true, if_false);
4215 } 4171 }
4216 4172
4217 4173
4218 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { 4174 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) {
4219 __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 4175 __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
4220 context()->Plug(rax); 4176 context()->Plug(rax);
4221 } 4177 }
4222 4178
4223 4179
4224 Register FullCodeGenerator::result_register() { 4180 Register FullCodeGenerator::result_register() {
4225 return rax; 4181 return rax;
4226 } 4182 }
4227 4183
4228 4184
4229 Register FullCodeGenerator::context_register() { 4185 Register FullCodeGenerator::context_register() {
4230 return rsi; 4186 return rsi;
4231 } 4187 }
4232 4188
4233 4189
4234 void FullCodeGenerator::EmitCallIC(Handle<Code> ic,
4235 RelocInfo::Mode mode,
4236 unsigned ast_id) {
4237 ASSERT(mode == RelocInfo::CODE_TARGET ||
4238 mode == RelocInfo::CODE_TARGET_CONTEXT);
4239 Counters* counters = isolate()->counters();
4240 switch (ic->kind()) {
4241 case Code::LOAD_IC:
4242 __ IncrementCounter(counters->named_load_full(), 1);
4243 break;
4244 case Code::KEYED_LOAD_IC:
4245 __ IncrementCounter(counters->keyed_load_full(), 1);
4246 break;
4247 case Code::STORE_IC:
4248 __ IncrementCounter(counters->named_store_full(), 1);
4249 break;
4250 case Code::KEYED_STORE_IC:
4251 __ IncrementCounter(counters->keyed_store_full(), 1);
4252 default:
4253 break;
4254 }
4255 __ call(ic, mode, ast_id);
4256 }
4257
4258
4259 void FullCodeGenerator::EmitCallIC(Handle<Code> ic,
4260 JumpPatchSite* patch_site,
4261 unsigned ast_id) {
4262 Counters* counters = isolate()->counters();
4263 switch (ic->kind()) {
4264 case Code::LOAD_IC:
4265 __ IncrementCounter(counters->named_load_full(), 1);
4266 break;
4267 case Code::KEYED_LOAD_IC:
4268 __ IncrementCounter(counters->keyed_load_full(), 1);
4269 break;
4270 case Code::STORE_IC:
4271 __ IncrementCounter(counters->named_store_full(), 1);
4272 break;
4273 case Code::KEYED_STORE_IC:
4274 __ IncrementCounter(counters->keyed_store_full(), 1);
4275 default:
4276 break;
4277 }
4278 __ call(ic, RelocInfo::CODE_TARGET, ast_id);
4279 if (patch_site != NULL && patch_site->is_bound()) {
4280 patch_site->EmitPatchInfo();
4281 } else {
4282 __ nop(); // Signals no inlined code.
4283 }
4284 }
4285
4286
4287 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { 4190 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
4288 ASSERT(IsAligned(frame_offset, kPointerSize)); 4191 ASSERT(IsAligned(frame_offset, kPointerSize));
4289 __ movq(Operand(rbp, frame_offset), value); 4192 __ movq(Operand(rbp, frame_offset), value);
4290 } 4193 }
4291 4194
4292 4195
4293 void FullCodeGenerator::LoadContextField(Register dst, int context_index) { 4196 void FullCodeGenerator::LoadContextField(Register dst, int context_index) {
4294 __ movq(dst, ContextOperand(rsi, context_index)); 4197 __ movq(dst, ContextOperand(rsi, context_index));
4295 } 4198 }
4296 4199
4297 4200
4201 void FullCodeGenerator::PushFunctionArgumentForContextAllocation() {
4202 Scope* declaration_scope = scope()->DeclarationScope();
4203 if (declaration_scope->is_global_scope()) {
4204 // Contexts nested in the global context have a canonical empty function
4205 // as their closure, not the anonymous closure containing the global
4206 // code. Pass a smi sentinel and let the runtime look up the empty
4207 // function.
4208 __ Push(Smi::FromInt(0));
4209 } else if (declaration_scope->is_eval_scope()) {
4210 // Contexts created by a call to eval have the same closure as the
4211 // context calling eval, not the anonymous closure containing the eval
4212 // code. Fetch it from the context.
4213 __ push(ContextOperand(rsi, Context::CLOSURE_INDEX));
4214 } else {
4215 ASSERT(declaration_scope->is_function_scope());
4216 __ push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
4217 }
4218 }
4219
4220
4298 // ---------------------------------------------------------------------------- 4221 // ----------------------------------------------------------------------------
4299 // Non-local control flow support. 4222 // Non-local control flow support.
4300 4223
4301 4224
4302 void FullCodeGenerator::EnterFinallyBlock() { 4225 void FullCodeGenerator::EnterFinallyBlock() {
4303 ASSERT(!result_register().is(rdx)); 4226 ASSERT(!result_register().is(rdx));
4304 ASSERT(!result_register().is(rcx)); 4227 ASSERT(!result_register().is(rcx));
4305 // Cook return address on top of stack (smi encoded Code* delta) 4228 // Cook return address on top of stack (smi encoded Code* delta)
4306 __ movq(rdx, Operand(rsp, 0)); 4229 __ pop(rdx);
4307 __ Move(rcx, masm_->CodeObject()); 4230 __ Move(rcx, masm_->CodeObject());
4308 __ subq(rdx, rcx); 4231 __ subq(rdx, rcx);
4309 __ Integer32ToSmi(rdx, rdx); 4232 __ Integer32ToSmi(rdx, rdx);
4310 __ movq(Operand(rsp, 0), rdx); 4233 __ push(rdx);
4311 // Store result register while executing finally block. 4234 // Store result register while executing finally block.
4312 __ push(result_register()); 4235 __ push(result_register());
4313 } 4236 }
4314 4237
4315 4238
4316 void FullCodeGenerator::ExitFinallyBlock() { 4239 void FullCodeGenerator::ExitFinallyBlock() {
4317 ASSERT(!result_register().is(rdx)); 4240 ASSERT(!result_register().is(rdx));
4318 ASSERT(!result_register().is(rcx)); 4241 ASSERT(!result_register().is(rcx));
4319 // Restore result register from stack.
4320 __ pop(result_register()); 4242 __ pop(result_register());
4321 // Uncook return address. 4243 // Uncook return address.
4322 __ movq(rdx, Operand(rsp, 0)); 4244 __ pop(rdx);
4323 __ SmiToInteger32(rdx, rdx); 4245 __ SmiToInteger32(rdx, rdx);
4324 __ Move(rcx, masm_->CodeObject()); 4246 __ Move(rcx, masm_->CodeObject());
4325 __ addq(rdx, rcx); 4247 __ addq(rdx, rcx);
4326 __ movq(Operand(rsp, 0), rdx); 4248 __ jmp(rdx);
4327 // And return.
4328 __ ret(0);
4329 } 4249 }
4330 4250
4331 4251
4332 #undef __ 4252 #undef __
4333 4253
4334 4254
4335 } } // namespace v8::internal 4255 } } // namespace v8::internal
4336 4256
4337 #endif // V8_TARGET_ARCH_X64 4257 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/disasm-x64.cc ('k') | src/x64/ic-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698