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

Side by Side Diff: src/mips/full-codegen-mips.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/mips/deoptimizer-mips.cc ('k') | src/mips/ic-mips.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 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 void EmitJumpIfSmi(Register reg, Label* target) { 94 void EmitJumpIfSmi(Register reg, Label* target) {
95 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_); 95 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_);
96 ASSERT(!patch_site_.is_bound() && !info_emitted_); 96 ASSERT(!patch_site_.is_bound() && !info_emitted_);
97 __ bind(&patch_site_); 97 __ bind(&patch_site_);
98 __ andi(at, reg, 0); 98 __ andi(at, reg, 0);
99 // Never taken before patched. 99 // Never taken before patched.
100 __ Branch(target, ne, at, Operand(zero_reg)); 100 __ Branch(target, ne, at, Operand(zero_reg));
101 } 101 }
102 102
103 void EmitPatchInfo() { 103 void EmitPatchInfo() {
104 int delta_to_patch_site = masm_->InstructionsGeneratedSince(&patch_site_); 104 if (patch_site_.is_bound()) {
105 Register reg = Register::from_code(delta_to_patch_site / kImm16Mask); 105 int delta_to_patch_site = masm_->InstructionsGeneratedSince(&patch_site_);
106 __ andi(at, reg, delta_to_patch_site % kImm16Mask); 106 Register reg = Register::from_code(delta_to_patch_site / kImm16Mask);
107 __ andi(at, reg, delta_to_patch_site % kImm16Mask);
107 #ifdef DEBUG 108 #ifdef DEBUG
108 info_emitted_ = true; 109 info_emitted_ = true;
109 #endif 110 #endif
111 } else {
112 __ nop(); // Signals no inlined code.
113 }
110 } 114 }
111 115
112 bool is_bound() const { return patch_site_.is_bound(); }
113
114 private: 116 private:
115 MacroAssembler* masm_; 117 MacroAssembler* masm_;
116 Label patch_site_; 118 Label patch_site_;
117 #ifdef DEBUG 119 #ifdef DEBUG
118 bool info_emitted_; 120 bool info_emitted_;
119 #endif 121 #endif
120 }; 122 };
121 123
122 124
123 // Generate code for a JS function. On entry to the function the receiver 125 // Generate code for a JS function. On entry to the function the receiver
124 // and arguments have been pushed on the stack left to right. The actual 126 // and arguments have been pushed on the stack left to right. The actual
125 // argument count matches the formal parameter count expected by the 127 // argument count matches the formal parameter count expected by the
126 // function. 128 // function.
127 // 129 //
128 // The live registers are: 130 // The live registers are:
129 // o a1: the JS function object being called (ie, ourselves) 131 // o a1: the JS function object being called (ie, ourselves)
130 // o cp: our context 132 // o cp: our context
131 // o fp: our caller's frame pointer 133 // o fp: our caller's frame pointer
132 // o sp: stack pointer 134 // o sp: stack pointer
133 // o ra: return address 135 // o ra: return address
134 // 136 //
135 // The function builds a JS frame. Please see JavaScriptFrameConstants in 137 // The function builds a JS frame. Please see JavaScriptFrameConstants in
136 // frames-mips.h for its layout. 138 // frames-mips.h for its layout.
137 void FullCodeGenerator::Generate(CompilationInfo* info) { 139 void FullCodeGenerator::Generate(CompilationInfo* info) {
138 ASSERT(info_ == NULL); 140 ASSERT(info_ == NULL);
139 info_ = info; 141 info_ = info;
142 scope_ = info->scope();
140 SetFunctionPosition(function()); 143 SetFunctionPosition(function());
141 Comment cmnt(masm_, "[ function compiled by full code generator"); 144 Comment cmnt(masm_, "[ function compiled by full code generator");
142 145
143 #ifdef DEBUG 146 #ifdef DEBUG
144 if (strlen(FLAG_stop_at) > 0 && 147 if (strlen(FLAG_stop_at) > 0 &&
145 info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { 148 info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
146 __ stop("stop-at"); 149 __ stop("stop-at");
147 } 150 }
148 #endif 151 #endif
149 152
150 // Strict mode functions need to replace the receiver with undefined 153 // Strict mode functions and builtins need to replace the receiver
151 // when called as functions (without an explicit receiver 154 // with undefined when called as functions (without an explicit
152 // object). t1 is zero for method calls and non-zero for function 155 // receiver object). t1 is zero for method calls and non-zero for
153 // calls. 156 // function calls.
154 if (info->is_strict_mode()) { 157 if (info->is_strict_mode() || info->is_native()) {
155 Label ok; 158 Label ok;
156 __ Branch(&ok, eq, t1, Operand(zero_reg)); 159 __ Branch(&ok, eq, t1, Operand(zero_reg));
157 int receiver_offset = scope()->num_parameters() * kPointerSize; 160 int receiver_offset = info->scope()->num_parameters() * kPointerSize;
158 __ LoadRoot(a2, Heap::kUndefinedValueRootIndex); 161 __ LoadRoot(a2, Heap::kUndefinedValueRootIndex);
159 __ sw(a2, MemOperand(sp, receiver_offset)); 162 __ sw(a2, MemOperand(sp, receiver_offset));
160 __ bind(&ok); 163 __ bind(&ok);
161 } 164 }
162 165
163 int locals_count = scope()->num_stack_slots(); 166 int locals_count = info->scope()->num_stack_slots();
164 167
165 __ Push(ra, fp, cp, a1); 168 __ Push(ra, fp, cp, a1);
166 if (locals_count > 0) { 169 if (locals_count > 0) {
167 // Load undefined value here, so the value is ready for the loop 170 // Load undefined value here, so the value is ready for the loop
168 // below. 171 // below.
169 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); 172 __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
170 } 173 }
171 // Adjust fp to point to caller's fp. 174 // Adjust fp to point to caller's fp.
172 __ Addu(fp, sp, Operand(2 * kPointerSize)); 175 __ Addu(fp, sp, Operand(2 * kPointerSize));
173 176
174 { Comment cmnt(masm_, "[ Allocate locals"); 177 { Comment cmnt(masm_, "[ Allocate locals");
175 for (int i = 0; i < locals_count; i++) { 178 for (int i = 0; i < locals_count; i++) {
176 __ push(at); 179 __ push(at);
177 } 180 }
178 } 181 }
179 182
180 bool function_in_register = true; 183 bool function_in_register = true;
181 184
182 // Possibly allocate a local context. 185 // Possibly allocate a local context.
183 int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; 186 int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
184 if (heap_slots > 0) { 187 if (heap_slots > 0) {
185 Comment cmnt(masm_, "[ Allocate local context"); 188 Comment cmnt(masm_, "[ Allocate local context");
186 // Argument to NewContext is the function, which is in a1. 189 // Argument to NewContext is the function, which is in a1.
187 __ push(a1); 190 __ push(a1);
188 if (heap_slots <= FastNewContextStub::kMaximumSlots) { 191 if (heap_slots <= FastNewContextStub::kMaximumSlots) {
189 FastNewContextStub stub(heap_slots); 192 FastNewContextStub stub(heap_slots);
190 __ CallStub(&stub); 193 __ CallStub(&stub);
191 } else { 194 } else {
192 __ CallRuntime(Runtime::kNewContext, 1); 195 __ CallRuntime(Runtime::kNewFunctionContext, 1);
193 } 196 }
194 function_in_register = false; 197 function_in_register = false;
195 // Context is returned in both v0 and cp. It replaces the context 198 // Context is returned in both v0 and cp. It replaces the context
196 // passed to us. It's saved in the stack and kept live in cp. 199 // passed to us. It's saved in the stack and kept live in cp.
197 __ sw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 200 __ sw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
198 // Copy any necessary parameters into the context. 201 // Copy any necessary parameters into the context.
199 int num_parameters = scope()->num_parameters(); 202 int num_parameters = info->scope()->num_parameters();
200 for (int i = 0; i < num_parameters; i++) { 203 for (int i = 0; i < num_parameters; i++) {
201 Slot* slot = scope()->parameter(i)->AsSlot(); 204 Slot* slot = scope()->parameter(i)->AsSlot();
202 if (slot != NULL && slot->type() == Slot::CONTEXT) { 205 if (slot != NULL && slot->type() == Slot::CONTEXT) {
203 int parameter_offset = StandardFrameConstants::kCallerSPOffset + 206 int parameter_offset = StandardFrameConstants::kCallerSPOffset +
204 (num_parameters - 1 - i) * kPointerSize; 207 (num_parameters - 1 - i) * kPointerSize;
205 // Load parameter from stack. 208 // Load parameter from stack.
206 __ lw(a0, MemOperand(fp, parameter_offset)); 209 __ lw(a0, MemOperand(fp, parameter_offset));
207 // Store it in the context. 210 // Store it in the context.
208 __ li(a1, Operand(Context::SlotOffset(slot->index()))); 211 __ li(a1, Operand(Context::SlotOffset(slot->index())));
209 __ addu(a2, cp, a1); 212 __ addu(a2, cp, a1);
(...skipping 11 matching lines...) Expand all
221 if (arguments != NULL) { 224 if (arguments != NULL) {
222 // Function uses arguments object. 225 // Function uses arguments object.
223 Comment cmnt(masm_, "[ Allocate arguments object"); 226 Comment cmnt(masm_, "[ Allocate arguments object");
224 if (!function_in_register) { 227 if (!function_in_register) {
225 // Load this again, if it's used by the local context below. 228 // Load this again, if it's used by the local context below.
226 __ lw(a3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 229 __ lw(a3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
227 } else { 230 } else {
228 __ mov(a3, a1); 231 __ mov(a3, a1);
229 } 232 }
230 // Receiver is just before the parameters on the caller's stack. 233 // Receiver is just before the parameters on the caller's stack.
231 int offset = scope()->num_parameters() * kPointerSize; 234 int num_parameters = info->scope()->num_parameters();
235 int offset = num_parameters * kPointerSize;
232 __ Addu(a2, fp, 236 __ Addu(a2, fp,
233 Operand(StandardFrameConstants::kCallerSPOffset + offset)); 237 Operand(StandardFrameConstants::kCallerSPOffset + offset));
234 __ li(a1, Operand(Smi::FromInt(scope()->num_parameters()))); 238 __ li(a1, Operand(Smi::FromInt(num_parameters)));
235 __ Push(a3, a2, a1); 239 __ Push(a3, a2, a1);
236 240
237 // Arguments to ArgumentsAccessStub: 241 // Arguments to ArgumentsAccessStub:
238 // function, receiver address, parameter count. 242 // function, receiver address, parameter count.
239 // The stub will rewrite receiever and parameter count if the previous 243 // The stub will rewrite receiever and parameter count if the previous
240 // stack frame was an arguments adapter frame. 244 // stack frame was an arguments adapter frame.
241 ArgumentsAccessStub stub( 245 ArgumentsAccessStub::Type type;
242 is_strict_mode() ? ArgumentsAccessStub::NEW_STRICT 246 if (is_strict_mode()) {
243 : ArgumentsAccessStub::NEW_NON_STRICT); 247 type = ArgumentsAccessStub::NEW_STRICT;
248 } else if (function()->has_duplicate_parameters()) {
249 type = ArgumentsAccessStub::NEW_NON_STRICT_SLOW;
250 } else {
251 type = ArgumentsAccessStub::NEW_NON_STRICT_FAST;
252 }
253 ArgumentsAccessStub stub(type);
244 __ CallStub(&stub); 254 __ CallStub(&stub);
245 255
246 Variable* arguments_shadow = scope()->arguments_shadow();
247 if (arguments_shadow != NULL) {
248 // Duplicate the value; move-to-slot operation might clobber registers.
249 __ mov(a3, v0);
250 Move(arguments_shadow->AsSlot(), a3, a1, a2);
251 }
252 Move(arguments->AsSlot(), v0, a1, a2); 256 Move(arguments->AsSlot(), v0, a1, a2);
253 } 257 }
254 258
255 if (FLAG_trace) { 259 if (FLAG_trace) {
256 __ CallRuntime(Runtime::kTraceEnter, 0); 260 __ CallRuntime(Runtime::kTraceEnter, 0);
257 } 261 }
258 262
259 // Visit the declarations and body unless there is an illegal 263 // Visit the declarations and body unless there is an illegal
260 // redeclaration. 264 // redeclaration.
261 if (scope()->HasIllegalRedeclaration()) { 265 if (scope()->HasIllegalRedeclaration()) {
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
341 #ifdef DEBUG 345 #ifdef DEBUG
342 // Add a label for checking the size of the code used for returning. 346 // Add a label for checking the size of the code used for returning.
343 Label check_exit_codesize; 347 Label check_exit_codesize;
344 masm_->bind(&check_exit_codesize); 348 masm_->bind(&check_exit_codesize);
345 #endif 349 #endif
346 // Make sure that the constant pool is not emitted inside of the return 350 // Make sure that the constant pool is not emitted inside of the return
347 // sequence. 351 // sequence.
348 { Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_); 352 { Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_);
349 // Here we use masm_-> instead of the __ macro to avoid the code coverage 353 // Here we use masm_-> instead of the __ macro to avoid the code coverage
350 // tool from instrumenting as we rely on the code size here. 354 // tool from instrumenting as we rely on the code size here.
351 int32_t sp_delta = (scope()->num_parameters() + 1) * kPointerSize; 355 int32_t sp_delta = (info_->scope()->num_parameters() + 1) * kPointerSize;
352 CodeGenerator::RecordPositions(masm_, function()->end_position() - 1); 356 CodeGenerator::RecordPositions(masm_, function()->end_position() - 1);
353 __ RecordJSReturn(); 357 __ RecordJSReturn();
354 masm_->mov(sp, fp); 358 masm_->mov(sp, fp);
355 masm_->MultiPop(static_cast<RegList>(fp.bit() | ra.bit())); 359 masm_->MultiPop(static_cast<RegList>(fp.bit() | ra.bit()));
356 masm_->Addu(sp, sp, Operand(sp_delta)); 360 masm_->Addu(sp, sp, Operand(sp_delta));
357 masm_->Jump(ra); 361 masm_->Jump(ra);
358 } 362 }
359 363
360 #ifdef DEBUG 364 #ifdef DEBUG
361 // Check that the size of the code used for returning is large enough 365 // Check that the size of the code used for returning is large enough
(...skipping 17 matching lines...) Expand all
379 void FullCodeGenerator::StackValueContext::Plug(Slot* slot) const { 383 void FullCodeGenerator::StackValueContext::Plug(Slot* slot) const {
380 codegen()->Move(result_register(), slot); 384 codegen()->Move(result_register(), slot);
381 __ push(result_register()); 385 __ push(result_register());
382 } 386 }
383 387
384 388
385 void FullCodeGenerator::TestContext::Plug(Slot* slot) const { 389 void FullCodeGenerator::TestContext::Plug(Slot* slot) const {
386 // For simplicity we always test the accumulator register. 390 // For simplicity we always test the accumulator register.
387 codegen()->Move(result_register(), slot); 391 codegen()->Move(result_register(), slot);
388 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); 392 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
389 codegen()->DoTest(true_label_, false_label_, fall_through_); 393 codegen()->DoTest(this);
390 } 394 }
391 395
392 396
393 void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const { 397 void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const {
394 } 398 }
395 399
396 400
397 void FullCodeGenerator::AccumulatorValueContext::Plug( 401 void FullCodeGenerator::AccumulatorValueContext::Plug(
398 Heap::RootListIndex index) const { 402 Heap::RootListIndex index) const {
399 __ LoadRoot(result_register(), index); 403 __ LoadRoot(result_register(), index);
(...skipping 13 matching lines...) Expand all
413 true_label_, 417 true_label_,
414 false_label_); 418 false_label_);
415 if (index == Heap::kUndefinedValueRootIndex || 419 if (index == Heap::kUndefinedValueRootIndex ||
416 index == Heap::kNullValueRootIndex || 420 index == Heap::kNullValueRootIndex ||
417 index == Heap::kFalseValueRootIndex) { 421 index == Heap::kFalseValueRootIndex) {
418 if (false_label_ != fall_through_) __ Branch(false_label_); 422 if (false_label_ != fall_through_) __ Branch(false_label_);
419 } else if (index == Heap::kTrueValueRootIndex) { 423 } else if (index == Heap::kTrueValueRootIndex) {
420 if (true_label_ != fall_through_) __ Branch(true_label_); 424 if (true_label_ != fall_through_) __ Branch(true_label_);
421 } else { 425 } else {
422 __ LoadRoot(result_register(), index); 426 __ LoadRoot(result_register(), index);
423 codegen()->DoTest(true_label_, false_label_, fall_through_); 427 codegen()->DoTest(this);
424 } 428 }
425 } 429 }
426 430
427 431
428 void FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const { 432 void FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const {
429 } 433 }
430 434
431 435
432 void FullCodeGenerator::AccumulatorValueContext::Plug( 436 void FullCodeGenerator::AccumulatorValueContext::Plug(
433 Handle<Object> lit) const { 437 Handle<Object> lit) const {
(...skipping 26 matching lines...) Expand all
460 } 464 }
461 } else if (lit->IsSmi()) { 465 } else if (lit->IsSmi()) {
462 if (Smi::cast(*lit)->value() == 0) { 466 if (Smi::cast(*lit)->value() == 0) {
463 if (false_label_ != fall_through_) __ Branch(false_label_); 467 if (false_label_ != fall_through_) __ Branch(false_label_);
464 } else { 468 } else {
465 if (true_label_ != fall_through_) __ Branch(true_label_); 469 if (true_label_ != fall_through_) __ Branch(true_label_);
466 } 470 }
467 } else { 471 } else {
468 // For simplicity we always test the accumulator register. 472 // For simplicity we always test the accumulator register.
469 __ li(result_register(), Operand(lit)); 473 __ li(result_register(), Operand(lit));
470 codegen()->DoTest(true_label_, false_label_, fall_through_); 474 codegen()->DoTest(this);
471 } 475 }
472 } 476 }
473 477
474 478
475 void FullCodeGenerator::EffectContext::DropAndPlug(int count, 479 void FullCodeGenerator::EffectContext::DropAndPlug(int count,
476 Register reg) const { 480 Register reg) const {
477 ASSERT(count > 0); 481 ASSERT(count > 0);
478 __ Drop(count); 482 __ Drop(count);
479 } 483 }
480 484
(...skipping 15 matching lines...) Expand all
496 } 500 }
497 501
498 502
499 void FullCodeGenerator::TestContext::DropAndPlug(int count, 503 void FullCodeGenerator::TestContext::DropAndPlug(int count,
500 Register reg) const { 504 Register reg) const {
501 ASSERT(count > 0); 505 ASSERT(count > 0);
502 // For simplicity we always test the accumulator register. 506 // For simplicity we always test the accumulator register.
503 __ Drop(count); 507 __ Drop(count);
504 __ Move(result_register(), reg); 508 __ Move(result_register(), reg);
505 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); 509 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
506 codegen()->DoTest(true_label_, false_label_, fall_through_); 510 codegen()->DoTest(this);
507 } 511 }
508 512
509 513
510 void FullCodeGenerator::EffectContext::Plug(Label* materialize_true, 514 void FullCodeGenerator::EffectContext::Plug(Label* materialize_true,
511 Label* materialize_false) const { 515 Label* materialize_false) const {
512 ASSERT(materialize_true == materialize_false); 516 ASSERT(materialize_true == materialize_false);
513 __ bind(materialize_true); 517 __ bind(materialize_true);
514 } 518 }
515 519
516 520
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
574 true_label_, 578 true_label_,
575 false_label_); 579 false_label_);
576 if (flag) { 580 if (flag) {
577 if (true_label_ != fall_through_) __ Branch(true_label_); 581 if (true_label_ != fall_through_) __ Branch(true_label_);
578 } else { 582 } else {
579 if (false_label_ != fall_through_) __ Branch(false_label_); 583 if (false_label_ != fall_through_) __ Branch(false_label_);
580 } 584 }
581 } 585 }
582 586
583 587
584 void FullCodeGenerator::DoTest(Label* if_true, 588 void FullCodeGenerator::DoTest(Expression* condition,
589 Label* if_true,
585 Label* if_false, 590 Label* if_false,
586 Label* fall_through) { 591 Label* fall_through) {
587 if (CpuFeatures::IsSupported(FPU)) { 592 if (CpuFeatures::IsSupported(FPU)) {
588 ToBooleanStub stub(result_register()); 593 ToBooleanStub stub(result_register());
589 __ CallStub(&stub); 594 __ CallStub(&stub);
590 __ mov(at, zero_reg); 595 __ mov(at, zero_reg);
591 } else { 596 } else {
592 // Call the runtime to find the boolean value of the source and then 597 // Call the runtime to find the boolean value of the source and then
593 // translate it into control flow to the pair of labels. 598 // translate it into control flow to the pair of labels.
594 __ push(result_register()); 599 __ push(result_register());
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
708 break; 713 break;
709 714
710 case Slot::CONTEXT: 715 case Slot::CONTEXT:
711 // We bypass the general EmitSlotSearch because we know more about 716 // We bypass the general EmitSlotSearch because we know more about
712 // this specific context. 717 // this specific context.
713 718
714 // The variable in the decl always resides in the current function 719 // The variable in the decl always resides in the current function
715 // context. 720 // context.
716 ASSERT_EQ(0, scope()->ContextChainLength(variable->scope())); 721 ASSERT_EQ(0, scope()->ContextChainLength(variable->scope()));
717 if (FLAG_debug_code) { 722 if (FLAG_debug_code) {
718 // Check that we're not inside a 'with'. 723 // Check that we're not inside a with or catch context.
719 __ lw(a1, ContextOperand(cp, Context::FCONTEXT_INDEX)); 724 __ lw(a1, FieldMemOperand(cp, HeapObject::kMapOffset));
720 __ Check(eq, "Unexpected declaration in current context.", 725 __ LoadRoot(t0, Heap::kWithContextMapRootIndex);
721 a1, Operand(cp)); 726 __ Check(ne, "Declaration in with context.",
727 a1, Operand(t0));
728 __ LoadRoot(t0, Heap::kCatchContextMapRootIndex);
729 __ Check(ne, "Declaration in catch context.",
730 a1, Operand(t0));
722 } 731 }
723 if (mode == Variable::CONST) { 732 if (mode == Variable::CONST) {
724 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); 733 __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
725 __ sw(at, ContextOperand(cp, slot->index())); 734 __ sw(at, ContextOperand(cp, slot->index()));
726 // No write barrier since the_hole_value is in old space. 735 // No write barrier since the_hole_value is in old space.
727 } else if (function != NULL) { 736 } else if (function != NULL) {
728 VisitForAccumulatorValue(function); 737 VisitForAccumulatorValue(function);
729 __ sw(result_register(), ContextOperand(cp, slot->index())); 738 __ sw(result_register(), ContextOperand(cp, slot->index()));
730 int offset = Context::SlotOffset(slot->index()); 739 int offset = Context::SlotOffset(slot->index());
731 // We know that we have written a function, which is not a smi. 740 // We know that we have written a function, which is not a smi.
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
782 __ mov(a0, result_register()); 791 __ mov(a0, result_register());
783 __ pop(a2); 792 __ pop(a2);
784 793
785 ASSERT(prop->key()->AsLiteral() != NULL && 794 ASSERT(prop->key()->AsLiteral() != NULL &&
786 prop->key()->AsLiteral()->handle()->IsSmi()); 795 prop->key()->AsLiteral()->handle()->IsSmi());
787 __ li(a1, Operand(prop->key()->AsLiteral()->handle())); 796 __ li(a1, Operand(prop->key()->AsLiteral()->handle()));
788 797
789 Handle<Code> ic = is_strict_mode() 798 Handle<Code> ic = is_strict_mode()
790 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() 799 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
791 : isolate()->builtins()->KeyedStoreIC_Initialize(); 800 : isolate()->builtins()->KeyedStoreIC_Initialize();
792 EmitCallIC(ic, RelocInfo::CODE_TARGET, AstNode::kNoNumber); 801 __ Call(ic);
793 // Value in v0 is ignored (declarations are statements). 802 // Value in v0 is ignored (declarations are statements).
794 } 803 }
795 } 804 }
796 } 805 }
797 806
798 807
799 void FullCodeGenerator::VisitDeclaration(Declaration* decl) { 808 void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
800 EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun()); 809 EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun());
801 } 810 }
802 811
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
857 __ Branch(&next_test, ne, a1, Operand(a0)); 866 __ Branch(&next_test, ne, a1, Operand(a0));
858 __ Drop(1); // Switch value is no longer needed. 867 __ Drop(1); // Switch value is no longer needed.
859 __ Branch(clause->body_target()); 868 __ Branch(clause->body_target());
860 869
861 __ bind(&slow_case); 870 __ bind(&slow_case);
862 } 871 }
863 872
864 // Record position before stub call for type feedback. 873 // Record position before stub call for type feedback.
865 SetSourcePosition(clause->position()); 874 SetSourcePosition(clause->position());
866 Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT); 875 Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT);
867 EmitCallIC(ic, &patch_site, clause->CompareId()); 876 __ Call(ic, RelocInfo::CODE_TARGET, clause->CompareId());
877 patch_site.EmitPatchInfo();
868 878
869 __ Branch(&next_test, ne, v0, Operand(zero_reg)); 879 __ Branch(&next_test, ne, v0, Operand(zero_reg));
870 __ Drop(1); // Switch value is no longer needed. 880 __ Drop(1); // Switch value is no longer needed.
871 __ Branch(clause->body_target()); 881 __ Branch(clause->body_target());
872 } 882 }
873 883
874 // Discard the test value and jump to the default if present, otherwise to 884 // Discard the test value and jump to the default if present, otherwise to
875 // the end of the statement. 885 // the end of the statement.
876 __ bind(&next_test); 886 __ bind(&next_test);
877 __ Drop(1); // Switch value is no longer needed. 887 __ Drop(1); // Switch value is no longer needed.
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
911 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); 921 __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
912 __ Branch(&exit, eq, a0, Operand(at)); 922 __ Branch(&exit, eq, a0, Operand(at));
913 Register null_value = t1; 923 Register null_value = t1;
914 __ LoadRoot(null_value, Heap::kNullValueRootIndex); 924 __ LoadRoot(null_value, Heap::kNullValueRootIndex);
915 __ Branch(&exit, eq, a0, Operand(null_value)); 925 __ Branch(&exit, eq, a0, Operand(null_value));
916 926
917 // Convert the object to a JS object. 927 // Convert the object to a JS object.
918 Label convert, done_convert; 928 Label convert, done_convert;
919 __ JumpIfSmi(a0, &convert); 929 __ JumpIfSmi(a0, &convert);
920 __ GetObjectType(a0, a1, a1); 930 __ GetObjectType(a0, a1, a1);
921 __ Branch(&done_convert, hs, a1, Operand(FIRST_JS_OBJECT_TYPE)); 931 __ Branch(&done_convert, ge, a1, Operand(FIRST_SPEC_OBJECT_TYPE));
922 __ bind(&convert); 932 __ bind(&convert);
923 __ push(a0); 933 __ push(a0);
924 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); 934 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
925 __ mov(a0, v0); 935 __ mov(a0, v0);
926 __ bind(&done_convert); 936 __ bind(&done_convert);
927 __ push(a0); 937 __ push(a0);
928 938
929 // Check cache validity in generated code. This is a fast case for 939 // Check cache validity in generated code. This is a fast case for
930 // the JSObject::IsSimpleEnum cache validity checks. If we cannot 940 // the JSObject::IsSimpleEnum cache validity checks. If we cannot
931 // guarantee cache validity, call the runtime system to check cache 941 // guarantee cache validity, call the runtime system to check cache
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
1121 1131
1122 Scope* s = scope(); 1132 Scope* s = scope();
1123 while (s != NULL) { 1133 while (s != NULL) {
1124 if (s->num_heap_slots() > 0) { 1134 if (s->num_heap_slots() > 0) {
1125 if (s->calls_eval()) { 1135 if (s->calls_eval()) {
1126 // Check that extension is NULL. 1136 // Check that extension is NULL.
1127 __ lw(temp, ContextOperand(current, Context::EXTENSION_INDEX)); 1137 __ lw(temp, ContextOperand(current, Context::EXTENSION_INDEX));
1128 __ Branch(slow, ne, temp, Operand(zero_reg)); 1138 __ Branch(slow, ne, temp, Operand(zero_reg));
1129 } 1139 }
1130 // Load next context in chain. 1140 // Load next context in chain.
1131 __ lw(next, ContextOperand(current, Context::CLOSURE_INDEX)); 1141 __ lw(next, ContextOperand(current, Context::PREVIOUS_INDEX));
1132 __ lw(next, FieldMemOperand(next, JSFunction::kContextOffset));
1133 // Walk the rest of the chain without clobbering cp. 1142 // Walk the rest of the chain without clobbering cp.
1134 current = next; 1143 current = next;
1135 } 1144 }
1136 // If no outer scope calls eval, we do not need to check more 1145 // If no outer scope calls eval, we do not need to check more
1137 // context extensions. 1146 // context extensions.
1138 if (!s->outer_scope_calls_eval() || s->is_eval_scope()) break; 1147 if (!s->outer_scope_calls_eval() || s->is_eval_scope()) break;
1139 s = s->outer_scope(); 1148 s = s->outer_scope();
1140 } 1149 }
1141 1150
1142 if (s->is_eval_scope()) { 1151 if (s->is_eval_scope()) {
1143 Label loop, fast; 1152 Label loop, fast;
1144 if (!current.is(next)) { 1153 if (!current.is(next)) {
1145 __ Move(next, current); 1154 __ Move(next, current);
1146 } 1155 }
1147 __ bind(&loop); 1156 __ bind(&loop);
1148 // Terminate at global context. 1157 // Terminate at global context.
1149 __ lw(temp, FieldMemOperand(next, HeapObject::kMapOffset)); 1158 __ lw(temp, FieldMemOperand(next, HeapObject::kMapOffset));
1150 __ LoadRoot(t0, Heap::kGlobalContextMapRootIndex); 1159 __ LoadRoot(t0, Heap::kGlobalContextMapRootIndex);
1151 __ Branch(&fast, eq, temp, Operand(t0)); 1160 __ Branch(&fast, eq, temp, Operand(t0));
1152 // Check that extension is NULL. 1161 // Check that extension is NULL.
1153 __ lw(temp, ContextOperand(next, Context::EXTENSION_INDEX)); 1162 __ lw(temp, ContextOperand(next, Context::EXTENSION_INDEX));
1154 __ Branch(slow, ne, temp, Operand(zero_reg)); 1163 __ Branch(slow, ne, temp, Operand(zero_reg));
1155 // Load next context in chain. 1164 // Load next context in chain.
1156 __ lw(next, ContextOperand(next, Context::CLOSURE_INDEX)); 1165 __ lw(next, ContextOperand(next, Context::PREVIOUS_INDEX));
1157 __ lw(next, FieldMemOperand(next, JSFunction::kContextOffset));
1158 __ Branch(&loop); 1166 __ Branch(&loop);
1159 __ bind(&fast); 1167 __ bind(&fast);
1160 } 1168 }
1161 1169
1162 __ lw(a0, GlobalObjectOperand()); 1170 __ lw(a0, GlobalObjectOperand());
1163 __ li(a2, Operand(slot->var()->name())); 1171 __ li(a2, Operand(slot->var()->name()));
1164 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) 1172 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
1165 ? RelocInfo::CODE_TARGET 1173 ? RelocInfo::CODE_TARGET
1166 : RelocInfo::CODE_TARGET_CONTEXT; 1174 : RelocInfo::CODE_TARGET_CONTEXT;
1167 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 1175 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
1168 EmitCallIC(ic, mode, AstNode::kNoNumber); 1176 __ Call(ic, mode);
1169 } 1177 }
1170 1178
1171 1179
1172 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions( 1180 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(
1173 Slot* slot, 1181 Slot* slot,
1174 Label* slow) { 1182 Label* slow) {
1175 ASSERT(slot->type() == Slot::CONTEXT); 1183 ASSERT(slot->type() == Slot::CONTEXT);
1176 Register context = cp; 1184 Register context = cp;
1177 Register next = a3; 1185 Register next = a3;
1178 Register temp = t0; 1186 Register temp = t0;
1179 1187
1180 for (Scope* s = scope(); s != slot->var()->scope(); s = s->outer_scope()) { 1188 for (Scope* s = scope(); s != slot->var()->scope(); s = s->outer_scope()) {
1181 if (s->num_heap_slots() > 0) { 1189 if (s->num_heap_slots() > 0) {
1182 if (s->calls_eval()) { 1190 if (s->calls_eval()) {
1183 // Check that extension is NULL. 1191 // Check that extension is NULL.
1184 __ lw(temp, ContextOperand(context, Context::EXTENSION_INDEX)); 1192 __ lw(temp, ContextOperand(context, Context::EXTENSION_INDEX));
1185 __ Branch(slow, ne, temp, Operand(zero_reg)); 1193 __ Branch(slow, ne, temp, Operand(zero_reg));
1186 } 1194 }
1187 __ lw(next, ContextOperand(context, Context::CLOSURE_INDEX)); 1195 __ lw(next, ContextOperand(context, Context::PREVIOUS_INDEX));
1188 __ lw(next, FieldMemOperand(next, JSFunction::kContextOffset));
1189 // Walk the rest of the chain without clobbering cp. 1196 // Walk the rest of the chain without clobbering cp.
1190 context = next; 1197 context = next;
1191 } 1198 }
1192 } 1199 }
1193 // Check that last extension is NULL. 1200 // Check that last extension is NULL.
1194 __ lw(temp, ContextOperand(context, Context::EXTENSION_INDEX)); 1201 __ lw(temp, ContextOperand(context, Context::EXTENSION_INDEX));
1195 __ Branch(slow, ne, temp, Operand(zero_reg)); 1202 __ Branch(slow, ne, temp, Operand(zero_reg));
1196 1203
1197 // This function is used only for loads, not stores, so it's safe to 1204 // This function is used only for loads, not stores, so it's safe to
1198 // return an cp-based operand (the write barrier cannot be allowed to 1205 // return an cp-based operand (the write barrier cannot be allowed to
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1239 key_literal->handle()->IsSmi()) { 1246 key_literal->handle()->IsSmi()) {
1240 // Load arguments object if there are no eval-introduced 1247 // Load arguments object if there are no eval-introduced
1241 // variables. Then load the argument from the arguments 1248 // variables. Then load the argument from the arguments
1242 // object using keyed load. 1249 // object using keyed load.
1243 __ lw(a1, 1250 __ lw(a1,
1244 ContextSlotOperandCheckExtensions(obj_proxy->var()->AsSlot(), 1251 ContextSlotOperandCheckExtensions(obj_proxy->var()->AsSlot(),
1245 slow)); 1252 slow));
1246 __ li(a0, Operand(key_literal->handle())); 1253 __ li(a0, Operand(key_literal->handle()));
1247 Handle<Code> ic = 1254 Handle<Code> ic =
1248 isolate()->builtins()->KeyedLoadIC_Initialize(); 1255 isolate()->builtins()->KeyedLoadIC_Initialize();
1249 EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(property)); 1256 __ Call(ic, RelocInfo::CODE_TARGET, GetPropertyId(property));
1250 __ Branch(done); 1257 __ Branch(done);
1251 } 1258 }
1252 } 1259 }
1253 } 1260 }
1254 } 1261 }
1255 } 1262 }
1256 1263
1257 1264
1258 void FullCodeGenerator::EmitVariableLoad(Variable* var) { 1265 void FullCodeGenerator::EmitVariableLoad(Variable* var) {
1259 // Four cases: non-this global variables, lookup slots, all other 1266 // Three cases: non-this global variables, lookup slots, and all other
1260 // types of slots, and parameters that rewrite to explicit property 1267 // types of slots.
1261 // accesses on the arguments object.
1262 Slot* slot = var->AsSlot(); 1268 Slot* slot = var->AsSlot();
1263 Property* property = var->AsProperty(); 1269 ASSERT((var->is_global() && !var->is_this()) == (slot == NULL));
1264 1270
1265 if (var->is_global() && !var->is_this()) { 1271 if (slot == NULL) {
1266 Comment cmnt(masm_, "Global variable"); 1272 Comment cmnt(masm_, "Global variable");
1267 // Use inline caching. Variable name is passed in a2 and the global 1273 // Use inline caching. Variable name is passed in a2 and the global
1268 // object (receiver) in a0. 1274 // object (receiver) in a0.
1269 __ lw(a0, GlobalObjectOperand()); 1275 __ lw(a0, GlobalObjectOperand());
1270 __ li(a2, Operand(var->name())); 1276 __ li(a2, Operand(var->name()));
1271 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 1277 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
1272 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT, AstNode::kNoNumber); 1278 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT);
1273 context()->Plug(v0); 1279 context()->Plug(v0);
1274 1280
1275 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { 1281 } else if (slot->type() == Slot::LOOKUP) {
1276 Label done, slow; 1282 Label done, slow;
1277 1283
1278 // Generate code for loading from variables potentially shadowed 1284 // Generate code for loading from variables potentially shadowed
1279 // by eval-introduced variables. 1285 // by eval-introduced variables.
1280 EmitDynamicLoadFromSlotFastCase(slot, NOT_INSIDE_TYPEOF, &slow, &done); 1286 EmitDynamicLoadFromSlotFastCase(slot, NOT_INSIDE_TYPEOF, &slow, &done);
1281 1287
1282 __ bind(&slow); 1288 __ bind(&slow);
1283 Comment cmnt(masm_, "Lookup slot"); 1289 Comment cmnt(masm_, "Lookup slot");
1284 __ li(a1, Operand(var->name())); 1290 __ li(a1, Operand(var->name()));
1285 __ Push(cp, a1); // Context and name. 1291 __ Push(cp, a1); // Context and name.
1286 __ CallRuntime(Runtime::kLoadContextSlot, 2); 1292 __ CallRuntime(Runtime::kLoadContextSlot, 2);
1287 __ bind(&done); 1293 __ bind(&done);
1288 1294
1289 context()->Plug(v0); 1295 context()->Plug(v0);
1290 1296
1291 } else if (slot != NULL) { 1297 } else {
1292 Comment cmnt(masm_, (slot->type() == Slot::CONTEXT) 1298 Comment cmnt(masm_, (slot->type() == Slot::CONTEXT)
1293 ? "Context slot" 1299 ? "Context slot"
1294 : "Stack slot"); 1300 : "Stack slot");
1295 if (var->mode() == Variable::CONST) { 1301 if (var->mode() == Variable::CONST) {
1296 // Constants may be the hole value if they have not been initialized. 1302 // Constants may be the hole value if they have not been initialized.
1297 // Unhole them. 1303 // Unhole them.
1298 MemOperand slot_operand = EmitSlotSearch(slot, a0); 1304 MemOperand slot_operand = EmitSlotSearch(slot, a0);
1299 __ lw(v0, slot_operand); 1305 __ lw(v0, slot_operand);
1300 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); 1306 __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
1301 __ subu(at, v0, at); // Sub as compare: at == 0 on eq. 1307 __ subu(at, v0, at); // Sub as compare: at == 0 on eq.
1302 __ LoadRoot(a0, Heap::kUndefinedValueRootIndex); 1308 __ LoadRoot(a0, Heap::kUndefinedValueRootIndex);
1303 __ movz(v0, a0, at); // Conditional move. 1309 __ movz(v0, a0, at); // Conditional move.
1304 context()->Plug(v0); 1310 context()->Plug(v0);
1305 } else { 1311 } else {
1306 context()->Plug(slot); 1312 context()->Plug(slot);
1307 } 1313 }
1308 } else {
1309 Comment cmnt(masm_, "Rewritten parameter");
1310 ASSERT_NOT_NULL(property);
1311 // Rewritten parameter accesses are of the form "slot[literal]".
1312 // Assert that the object is in a slot.
1313 Variable* object_var = property->obj()->AsVariableProxy()->AsVariable();
1314 ASSERT_NOT_NULL(object_var);
1315 Slot* object_slot = object_var->AsSlot();
1316 ASSERT_NOT_NULL(object_slot);
1317
1318 // Load the object.
1319 Move(a1, object_slot);
1320
1321 // Assert that the key is a smi.
1322 Literal* key_literal = property->key()->AsLiteral();
1323 ASSERT_NOT_NULL(key_literal);
1324 ASSERT(key_literal->handle()->IsSmi());
1325
1326 // Load the key.
1327 __ li(a0, Operand(key_literal->handle()));
1328
1329 // Call keyed load IC. It has arguments key and receiver in a0 and a1.
1330 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
1331 EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(property));
1332 context()->Plug(v0);
1333 } 1314 }
1334 } 1315 }
1335 1316
1336 1317
1337 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { 1318 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
1338 Comment cmnt(masm_, "[ RegExpLiteral"); 1319 Comment cmnt(masm_, "[ RegExpLiteral");
1339 Label materialized; 1320 Label materialized;
1340 // Registers will be used as follows: 1321 // Registers will be used as follows:
1341 // t1 = materialized value (RegExp literal) 1322 // t1 = materialized value (RegExp literal)
1342 // t0 = JS function, literals array 1323 // t0 = JS function, literals array
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
1433 case ObjectLiteral::Property::COMPUTED: 1414 case ObjectLiteral::Property::COMPUTED:
1434 if (key->handle()->IsSymbol()) { 1415 if (key->handle()->IsSymbol()) {
1435 if (property->emit_store()) { 1416 if (property->emit_store()) {
1436 VisitForAccumulatorValue(value); 1417 VisitForAccumulatorValue(value);
1437 __ mov(a0, result_register()); 1418 __ mov(a0, result_register());
1438 __ li(a2, Operand(key->handle())); 1419 __ li(a2, Operand(key->handle()));
1439 __ lw(a1, MemOperand(sp)); 1420 __ lw(a1, MemOperand(sp));
1440 Handle<Code> ic = is_strict_mode() 1421 Handle<Code> ic = is_strict_mode()
1441 ? isolate()->builtins()->StoreIC_Initialize_Strict() 1422 ? isolate()->builtins()->StoreIC_Initialize_Strict()
1442 : isolate()->builtins()->StoreIC_Initialize(); 1423 : isolate()->builtins()->StoreIC_Initialize();
1443 EmitCallIC(ic, RelocInfo::CODE_TARGET, key->id()); 1424 __ Call(ic, RelocInfo::CODE_TARGET, key->id());
1444 PrepareForBailoutForId(key->id(), NO_REGISTERS); 1425 PrepareForBailoutForId(key->id(), NO_REGISTERS);
1445 } else { 1426 } else {
1446 VisitForEffect(value); 1427 VisitForEffect(value);
1447 } 1428 }
1448 break; 1429 break;
1449 } 1430 }
1450 // Fall through. 1431 // Fall through.
1451 case ObjectLiteral::Property::PROTOTYPE: 1432 case ObjectLiteral::Property::PROTOTYPE:
1452 // Duplicate receiver on stack. 1433 // Duplicate receiver on stack.
1453 __ lw(a0, MemOperand(sp)); 1434 __ lw(a0, MemOperand(sp));
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
1566 void FullCodeGenerator::VisitAssignment(Assignment* expr) { 1547 void FullCodeGenerator::VisitAssignment(Assignment* expr) {
1567 Comment cmnt(masm_, "[ Assignment"); 1548 Comment cmnt(masm_, "[ Assignment");
1568 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' 1549 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
1569 // on the left-hand side. 1550 // on the left-hand side.
1570 if (!expr->target()->IsValidLeftHandSide()) { 1551 if (!expr->target()->IsValidLeftHandSide()) {
1571 VisitForEffect(expr->target()); 1552 VisitForEffect(expr->target());
1572 return; 1553 return;
1573 } 1554 }
1574 1555
1575 // Left-hand side can only be a property, a global or a (parameter or local) 1556 // Left-hand side can only be a property, a global or a (parameter or local)
1576 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. 1557 // slot.
1577 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 1558 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
1578 LhsKind assign_type = VARIABLE; 1559 LhsKind assign_type = VARIABLE;
1579 Property* property = expr->target()->AsProperty(); 1560 Property* property = expr->target()->AsProperty();
1580 if (property != NULL) { 1561 if (property != NULL) {
1581 assign_type = (property->key()->IsPropertyName()) 1562 assign_type = (property->key()->IsPropertyName())
1582 ? NAMED_PROPERTY 1563 ? NAMED_PROPERTY
1583 : KEYED_PROPERTY; 1564 : KEYED_PROPERTY;
1584 } 1565 }
1585 1566
1586 // Evaluate LHS expression. 1567 // Evaluate LHS expression.
1587 switch (assign_type) { 1568 switch (assign_type) {
1588 case VARIABLE: 1569 case VARIABLE:
1589 // Nothing to do here. 1570 // Nothing to do here.
1590 break; 1571 break;
1591 case NAMED_PROPERTY: 1572 case NAMED_PROPERTY:
1592 if (expr->is_compound()) { 1573 if (expr->is_compound()) {
1593 // We need the receiver both on the stack and in the accumulator. 1574 // We need the receiver both on the stack and in the accumulator.
1594 VisitForAccumulatorValue(property->obj()); 1575 VisitForAccumulatorValue(property->obj());
1595 __ push(result_register()); 1576 __ push(result_register());
1596 } else { 1577 } else {
1597 VisitForStackValue(property->obj()); 1578 VisitForStackValue(property->obj());
1598 } 1579 }
1599 break; 1580 break;
1600 case KEYED_PROPERTY: 1581 case KEYED_PROPERTY:
1601 // We need the key and receiver on both the stack and in v0 and a1. 1582 // We need the key and receiver on both the stack and in v0 and a1.
1602 if (expr->is_compound()) { 1583 if (expr->is_compound()) {
1603 if (property->is_arguments_access()) { 1584 VisitForStackValue(property->obj());
1604 VariableProxy* obj_proxy = property->obj()->AsVariableProxy(); 1585 VisitForAccumulatorValue(property->key());
1605 __ lw(v0, EmitSlotSearch(obj_proxy->var()->AsSlot(), v0));
1606 __ push(v0);
1607 __ li(v0, Operand(property->key()->AsLiteral()->handle()));
1608 } else {
1609 VisitForStackValue(property->obj());
1610 VisitForAccumulatorValue(property->key());
1611 }
1612 __ lw(a1, MemOperand(sp, 0)); 1586 __ lw(a1, MemOperand(sp, 0));
1613 __ push(v0); 1587 __ push(v0);
1614 } else { 1588 } else {
1615 if (property->is_arguments_access()) { 1589 VisitForStackValue(property->obj());
1616 VariableProxy* obj_proxy = property->obj()->AsVariableProxy(); 1590 VisitForStackValue(property->key());
1617 __ lw(a1, EmitSlotSearch(obj_proxy->var()->AsSlot(), v0));
1618 __ li(v0, Operand(property->key()->AsLiteral()->handle()));
1619 __ Push(a1, v0);
1620 } else {
1621 VisitForStackValue(property->obj());
1622 VisitForStackValue(property->key());
1623 }
1624 } 1591 }
1625 break; 1592 break;
1626 } 1593 }
1627 1594
1628 // For compound assignments we need another deoptimization point after the 1595 // For compound assignments we need another deoptimization point after the
1629 // variable/property load. 1596 // variable/property load.
1630 if (expr->is_compound()) { 1597 if (expr->is_compound()) {
1631 { AccumulatorValueContext context(this); 1598 { AccumulatorValueContext context(this);
1632 switch (assign_type) { 1599 switch (assign_type) {
1633 case VARIABLE: 1600 case VARIABLE:
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
1691 } 1658 }
1692 1659
1693 1660
1694 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { 1661 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
1695 SetSourcePosition(prop->position()); 1662 SetSourcePosition(prop->position());
1696 Literal* key = prop->key()->AsLiteral(); 1663 Literal* key = prop->key()->AsLiteral();
1697 __ mov(a0, result_register()); 1664 __ mov(a0, result_register());
1698 __ li(a2, Operand(key->handle())); 1665 __ li(a2, Operand(key->handle()));
1699 // Call load IC. It has arguments receiver and property name a0 and a2. 1666 // Call load IC. It has arguments receiver and property name a0 and a2.
1700 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 1667 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
1701 EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(prop)); 1668 __ Call(ic, RelocInfo::CODE_TARGET, GetPropertyId(prop));
1702 } 1669 }
1703 1670
1704 1671
1705 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { 1672 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
1706 SetSourcePosition(prop->position()); 1673 SetSourcePosition(prop->position());
1707 __ mov(a0, result_register()); 1674 __ mov(a0, result_register());
1708 // Call keyed load IC. It has arguments key and receiver in a0 and a1. 1675 // Call keyed load IC. It has arguments key and receiver in a0 and a1.
1709 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); 1676 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
1710 EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(prop)); 1677 __ Call(ic, RelocInfo::CODE_TARGET, GetPropertyId(prop));
1711 } 1678 }
1712 1679
1713 1680
1714 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, 1681 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
1715 Token::Value op, 1682 Token::Value op,
1716 OverwriteMode mode, 1683 OverwriteMode mode,
1717 Expression* left_expr, 1684 Expression* left_expr,
1718 Expression* right_expr) { 1685 Expression* right_expr) {
1719 Label done, smi_case, stub_call; 1686 Label done, smi_case, stub_call;
1720 1687
1721 Register scratch1 = a2; 1688 Register scratch1 = a2;
1722 Register scratch2 = a3; 1689 Register scratch2 = a3;
1723 1690
1724 // Get the arguments. 1691 // Get the arguments.
1725 Register left = a1; 1692 Register left = a1;
1726 Register right = a0; 1693 Register right = a0;
1727 __ pop(left); 1694 __ pop(left);
1728 __ mov(a0, result_register()); 1695 __ mov(a0, result_register());
1729 1696
1730 // Perform combined smi check on both operands. 1697 // Perform combined smi check on both operands.
1731 __ Or(scratch1, left, Operand(right)); 1698 __ Or(scratch1, left, Operand(right));
1732 STATIC_ASSERT(kSmiTag == 0); 1699 STATIC_ASSERT(kSmiTag == 0);
1733 JumpPatchSite patch_site(masm_); 1700 JumpPatchSite patch_site(masm_);
1734 patch_site.EmitJumpIfSmi(scratch1, &smi_case); 1701 patch_site.EmitJumpIfSmi(scratch1, &smi_case);
1735 1702
1736 __ bind(&stub_call); 1703 __ bind(&stub_call);
1737 BinaryOpStub stub(op, mode); 1704 BinaryOpStub stub(op, mode);
1738 EmitCallIC(stub.GetCode(), &patch_site, expr->id()); 1705 __ Call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id());
1706 patch_site.EmitPatchInfo();
1739 __ jmp(&done); 1707 __ jmp(&done);
1740 1708
1741 __ bind(&smi_case); 1709 __ bind(&smi_case);
1742 // Smi case. This code works the same way as the smi-smi case in the type 1710 // Smi case. This code works the same way as the smi-smi case in the type
1743 // recording binary operation stub, see 1711 // recording binary operation stub, see
1744 // BinaryOpStub::GenerateSmiSmiOperation for comments. 1712 // BinaryOpStub::GenerateSmiSmiOperation for comments.
1745 switch (op) { 1713 switch (op) {
1746 case Token::SAR: 1714 case Token::SAR:
1747 __ Branch(&stub_call); 1715 __ Branch(&stub_call);
1748 __ GetLeastBitsFromSmi(scratch1, right, 5); 1716 __ GetLeastBitsFromSmi(scratch1, right, 5);
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
1809 context()->Plug(v0); 1777 context()->Plug(v0);
1810 } 1778 }
1811 1779
1812 1780
1813 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, 1781 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr,
1814 Token::Value op, 1782 Token::Value op,
1815 OverwriteMode mode) { 1783 OverwriteMode mode) {
1816 __ mov(a0, result_register()); 1784 __ mov(a0, result_register());
1817 __ pop(a1); 1785 __ pop(a1);
1818 BinaryOpStub stub(op, mode); 1786 BinaryOpStub stub(op, mode);
1819 EmitCallIC(stub.GetCode(), NULL, expr->id()); 1787 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code.
1788 __ Call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id());
1789 patch_site.EmitPatchInfo();
1820 context()->Plug(v0); 1790 context()->Plug(v0);
1821 } 1791 }
1822 1792
1823 1793
1824 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) { 1794 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) {
1825 // Invalid left-hand sides are rewritten to have a 'throw 1795 // Invalid left-hand sides are rewritten to have a 'throw
1826 // ReferenceError' on the left-hand side. 1796 // ReferenceError' on the left-hand side.
1827 if (!expr->IsValidLeftHandSide()) { 1797 if (!expr->IsValidLeftHandSide()) {
1828 VisitForEffect(expr); 1798 VisitForEffect(expr);
1829 return; 1799 return;
1830 } 1800 }
1831 1801
1832 // Left-hand side can only be a property, a global or a (parameter or local) 1802 // Left-hand side can only be a property, a global or a (parameter or local)
1833 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. 1803 // slot.
1834 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 1804 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
1835 LhsKind assign_type = VARIABLE; 1805 LhsKind assign_type = VARIABLE;
1836 Property* prop = expr->AsProperty(); 1806 Property* prop = expr->AsProperty();
1837 if (prop != NULL) { 1807 if (prop != NULL) {
1838 assign_type = (prop->key()->IsPropertyName()) 1808 assign_type = (prop->key()->IsPropertyName())
1839 ? NAMED_PROPERTY 1809 ? NAMED_PROPERTY
1840 : KEYED_PROPERTY; 1810 : KEYED_PROPERTY;
1841 } 1811 }
1842 1812
1843 switch (assign_type) { 1813 switch (assign_type) {
1844 case VARIABLE: { 1814 case VARIABLE: {
1845 Variable* var = expr->AsVariableProxy()->var(); 1815 Variable* var = expr->AsVariableProxy()->var();
1846 EffectContext context(this); 1816 EffectContext context(this);
1847 EmitVariableAssignment(var, Token::ASSIGN); 1817 EmitVariableAssignment(var, Token::ASSIGN);
1848 break; 1818 break;
1849 } 1819 }
1850 case NAMED_PROPERTY: { 1820 case NAMED_PROPERTY: {
1851 __ push(result_register()); // Preserve value. 1821 __ push(result_register()); // Preserve value.
1852 VisitForAccumulatorValue(prop->obj()); 1822 VisitForAccumulatorValue(prop->obj());
1853 __ mov(a1, result_register()); 1823 __ mov(a1, result_register());
1854 __ pop(a0); // Restore value. 1824 __ pop(a0); // Restore value.
1855 __ li(a2, Operand(prop->key()->AsLiteral()->handle())); 1825 __ li(a2, Operand(prop->key()->AsLiteral()->handle()));
1856 Handle<Code> ic = is_strict_mode() 1826 Handle<Code> ic = is_strict_mode()
1857 ? isolate()->builtins()->StoreIC_Initialize_Strict() 1827 ? isolate()->builtins()->StoreIC_Initialize_Strict()
1858 : isolate()->builtins()->StoreIC_Initialize(); 1828 : isolate()->builtins()->StoreIC_Initialize();
1859 EmitCallIC(ic, RelocInfo::CODE_TARGET, AstNode::kNoNumber); 1829 __ Call(ic);
1860 break; 1830 break;
1861 } 1831 }
1862 case KEYED_PROPERTY: { 1832 case KEYED_PROPERTY: {
1863 __ push(result_register()); // Preserve value. 1833 __ push(result_register()); // Preserve value.
1864 if (prop->is_synthetic()) { 1834 VisitForStackValue(prop->obj());
1865 ASSERT(prop->obj()->AsVariableProxy() != NULL); 1835 VisitForAccumulatorValue(prop->key());
1866 ASSERT(prop->key()->AsLiteral() != NULL); 1836 __ mov(a1, result_register());
1867 { AccumulatorValueContext for_object(this); 1837 __ pop(a2);
1868 EmitVariableLoad(prop->obj()->AsVariableProxy()->var());
1869 }
1870 __ mov(a2, result_register());
1871 __ li(a1, Operand(prop->key()->AsLiteral()->handle()));
1872 } else {
1873 VisitForStackValue(prop->obj());
1874 VisitForAccumulatorValue(prop->key());
1875 __ mov(a1, result_register());
1876 __ pop(a2);
1877 }
1878 __ pop(a0); // Restore value. 1838 __ pop(a0); // Restore value.
1879 Handle<Code> ic = is_strict_mode() 1839 Handle<Code> ic = is_strict_mode()
1880 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() 1840 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
1881 : isolate()->builtins()->KeyedStoreIC_Initialize(); 1841 : isolate()->builtins()->KeyedStoreIC_Initialize();
1882 EmitCallIC(ic, RelocInfo::CODE_TARGET, AstNode::kNoNumber); 1842 __ Call(ic);
1883 break; 1843 break;
1884 } 1844 }
1885 } 1845 }
1886 PrepareForBailoutForId(bailout_ast_id, TOS_REG); 1846 PrepareForBailoutForId(bailout_ast_id, TOS_REG);
1887 context()->Plug(v0); 1847 context()->Plug(v0);
1888 } 1848 }
1889 1849
1890 1850
1891 void FullCodeGenerator::EmitVariableAssignment(Variable* var, 1851 void FullCodeGenerator::EmitVariableAssignment(Variable* var,
1892 Token::Value op) { 1852 Token::Value op) {
1893 // Left-hand sides that rewrite to explicit property accesses do not reach
1894 // here.
1895 ASSERT(var != NULL); 1853 ASSERT(var != NULL);
1896 ASSERT(var->is_global() || var->AsSlot() != NULL); 1854 ASSERT(var->is_global() || var->AsSlot() != NULL);
1897 1855
1898 if (var->is_global()) { 1856 if (var->is_global()) {
1899 ASSERT(!var->is_this()); 1857 ASSERT(!var->is_this());
1900 // Assignment to a global variable. Use inline caching for the 1858 // Assignment to a global variable. Use inline caching for the
1901 // assignment. Right-hand-side value is passed in a0, variable name in 1859 // assignment. Right-hand-side value is passed in a0, variable name in
1902 // a2, and the global object in a1. 1860 // a2, and the global object in a1.
1903 __ mov(a0, result_register()); 1861 __ mov(a0, result_register());
1904 __ li(a2, Operand(var->name())); 1862 __ li(a2, Operand(var->name()));
1905 __ lw(a1, GlobalObjectOperand()); 1863 __ lw(a1, GlobalObjectOperand());
1906 Handle<Code> ic = is_strict_mode() 1864 Handle<Code> ic = is_strict_mode()
1907 ? isolate()->builtins()->StoreIC_Initialize_Strict() 1865 ? isolate()->builtins()->StoreIC_Initialize_Strict()
1908 : isolate()->builtins()->StoreIC_Initialize(); 1866 : isolate()->builtins()->StoreIC_Initialize();
1909 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT, AstNode::kNoNumber); 1867 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT);
1910 1868
1911 } else if (op == Token::INIT_CONST) { 1869 } else if (op == Token::INIT_CONST) {
1912 // Like var declarations, const declarations are hoisted to function 1870 // Like var declarations, const declarations are hoisted to function
1913 // scope. However, unlike var initializers, const initializers are able 1871 // scope. However, unlike var initializers, const initializers are able
1914 // to drill a hole to that function context, even from inside a 'with' 1872 // to drill a hole to that function context, even from inside a 'with'
1915 // context. We thus bypass the normal static scope lookup. 1873 // context. We thus bypass the normal static scope lookup.
1916 Slot* slot = var->AsSlot(); 1874 Slot* slot = var->AsSlot();
1917 Label skip; 1875 Label skip;
1918 switch (slot->type()) { 1876 switch (slot->type()) {
1919 case Slot::PARAMETER: 1877 case Slot::PARAMETER:
1920 // No const parameters. 1878 // No const parameters.
1921 UNREACHABLE(); 1879 UNREACHABLE();
1922 break; 1880 break;
1923 case Slot::LOCAL: 1881 case Slot::LOCAL:
1924 // Detect const reinitialization by checking for the hole value. 1882 // Detect const reinitialization by checking for the hole value.
1925 __ lw(a1, MemOperand(fp, SlotOffset(slot))); 1883 __ lw(a1, MemOperand(fp, SlotOffset(slot)));
1926 __ LoadRoot(t0, Heap::kTheHoleValueRootIndex); 1884 __ LoadRoot(t0, Heap::kTheHoleValueRootIndex);
1927 __ Branch(&skip, ne, a1, Operand(t0)); 1885 __ Branch(&skip, ne, a1, Operand(t0));
1928 __ sw(result_register(), MemOperand(fp, SlotOffset(slot))); 1886 __ sw(result_register(), MemOperand(fp, SlotOffset(slot)));
1929 break; 1887 break;
1930 case Slot::CONTEXT: { 1888 case Slot::CONTEXT:
1931 __ lw(a1, ContextOperand(cp, Context::FCONTEXT_INDEX));
1932 __ lw(a2, ContextOperand(a1, slot->index()));
1933 __ LoadRoot(t0, Heap::kTheHoleValueRootIndex);
1934 __ Branch(&skip, ne, a2, Operand(t0));
1935 __ sw(result_register(), ContextOperand(a1, slot->index()));
1936 int offset = Context::SlotOffset(slot->index());
1937 __ mov(a3, result_register()); // Preserve the stored value in v0.
1938 __ RecordWrite(a1, Operand(offset), a3, a2);
1939 break;
1940 }
1941 case Slot::LOOKUP: 1889 case Slot::LOOKUP:
1942 __ push(result_register()); 1890 __ push(result_register());
1943 __ li(a0, Operand(slot->var()->name())); 1891 __ li(a0, Operand(slot->var()->name()));
1944 __ Push(cp, a0); // Context and name. 1892 __ Push(cp, a0); // Context and name.
1945 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); 1893 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
1946 break; 1894 break;
1947 } 1895 }
1948 __ bind(&skip); 1896 __ bind(&skip);
1949 1897
1950 } else if (var->mode() != Variable::CONST) { 1898 } else if (var->mode() != Variable::CONST) {
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
2007 // receiver into fast case. 1955 // receiver into fast case.
2008 if (expr->ends_initialization_block()) { 1956 if (expr->ends_initialization_block()) {
2009 __ lw(a1, MemOperand(sp)); 1957 __ lw(a1, MemOperand(sp));
2010 } else { 1958 } else {
2011 __ pop(a1); 1959 __ pop(a1);
2012 } 1960 }
2013 1961
2014 Handle<Code> ic = is_strict_mode() 1962 Handle<Code> ic = is_strict_mode()
2015 ? isolate()->builtins()->StoreIC_Initialize_Strict() 1963 ? isolate()->builtins()->StoreIC_Initialize_Strict()
2016 : isolate()->builtins()->StoreIC_Initialize(); 1964 : isolate()->builtins()->StoreIC_Initialize();
2017 EmitCallIC(ic, RelocInfo::CODE_TARGET, expr->id()); 1965 __ Call(ic, RelocInfo::CODE_TARGET, expr->id());
2018 1966
2019 // If the assignment ends an initialization block, revert to fast case. 1967 // If the assignment ends an initialization block, revert to fast case.
2020 if (expr->ends_initialization_block()) { 1968 if (expr->ends_initialization_block()) {
2021 __ push(v0); // Result of assignment, saved even if not needed. 1969 __ push(v0); // Result of assignment, saved even if not needed.
2022 // Receiver is under the result value. 1970 // Receiver is under the result value.
2023 __ lw(t0, MemOperand(sp, kPointerSize)); 1971 __ lw(t0, MemOperand(sp, kPointerSize));
2024 __ push(t0); 1972 __ push(t0);
2025 __ CallRuntime(Runtime::kToFastProperties, 1); 1973 __ CallRuntime(Runtime::kToFastProperties, 1);
2026 __ pop(v0); 1974 __ pop(v0);
2027 __ Drop(1); 1975 __ Drop(1);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
2059 // receiver into fast case. 2007 // receiver into fast case.
2060 if (expr->ends_initialization_block()) { 2008 if (expr->ends_initialization_block()) {
2061 __ lw(a2, MemOperand(sp)); 2009 __ lw(a2, MemOperand(sp));
2062 } else { 2010 } else {
2063 __ pop(a2); 2011 __ pop(a2);
2064 } 2012 }
2065 2013
2066 Handle<Code> ic = is_strict_mode() 2014 Handle<Code> ic = is_strict_mode()
2067 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() 2015 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
2068 : isolate()->builtins()->KeyedStoreIC_Initialize(); 2016 : isolate()->builtins()->KeyedStoreIC_Initialize();
2069 EmitCallIC(ic, RelocInfo::CODE_TARGET, expr->id()); 2017 __ Call(ic, RelocInfo::CODE_TARGET, expr->id());
2070 2018
2071 // If the assignment ends an initialization block, revert to fast case. 2019 // If the assignment ends an initialization block, revert to fast case.
2072 if (expr->ends_initialization_block()) { 2020 if (expr->ends_initialization_block()) {
2073 __ push(v0); // Result of assignment, saved even if not needed. 2021 __ push(v0); // Result of assignment, saved even if not needed.
2074 // Receiver is under the result value. 2022 // Receiver is under the result value.
2075 __ lw(t0, MemOperand(sp, kPointerSize)); 2023 __ lw(t0, MemOperand(sp, kPointerSize));
2076 __ push(t0); 2024 __ push(t0);
2077 __ CallRuntime(Runtime::kToFastProperties, 1); 2025 __ CallRuntime(Runtime::kToFastProperties, 1);
2078 __ pop(v0); 2026 __ pop(v0);
2079 __ Drop(1); 2027 __ Drop(1);
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
2112 VisitForStackValue(args->at(i)); 2060 VisitForStackValue(args->at(i));
2113 } 2061 }
2114 __ li(a2, Operand(name)); 2062 __ li(a2, Operand(name));
2115 } 2063 }
2116 // Record source position for debugger. 2064 // Record source position for debugger.
2117 SetSourcePosition(expr->position()); 2065 SetSourcePosition(expr->position());
2118 // Call the IC initialization code. 2066 // Call the IC initialization code.
2119 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 2067 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
2120 Handle<Code> ic = 2068 Handle<Code> ic =
2121 isolate()->stub_cache()->ComputeCallInitialize(arg_count, in_loop, mode); 2069 isolate()->stub_cache()->ComputeCallInitialize(arg_count, in_loop, mode);
2122 EmitCallIC(ic, mode, expr->id()); 2070 __ Call(ic, mode, expr->id());
2123 RecordJSReturnSite(expr); 2071 RecordJSReturnSite(expr);
2124 // Restore context register. 2072 // Restore context register.
2125 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 2073 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
2126 context()->Plug(v0); 2074 context()->Plug(v0);
2127 } 2075 }
2128 2076
2129 2077
2130 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, 2078 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr,
2131 Expression* key) { 2079 Expression* key) {
2132 // Load the key. 2080 // Load the key.
(...skipping 13 matching lines...) Expand all
2146 VisitForStackValue(args->at(i)); 2094 VisitForStackValue(args->at(i));
2147 } 2095 }
2148 } 2096 }
2149 // Record source position for debugger. 2097 // Record source position for debugger.
2150 SetSourcePosition(expr->position()); 2098 SetSourcePosition(expr->position());
2151 // Call the IC initialization code. 2099 // Call the IC initialization code.
2152 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 2100 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
2153 Handle<Code> ic = 2101 Handle<Code> ic =
2154 isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count, in_loop); 2102 isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count, in_loop);
2155 __ lw(a2, MemOperand(sp, (arg_count + 1) * kPointerSize)); // Key. 2103 __ lw(a2, MemOperand(sp, (arg_count + 1) * kPointerSize)); // Key.
2156 EmitCallIC(ic, RelocInfo::CODE_TARGET, expr->id()); 2104 __ Call(ic, RelocInfo::CODE_TARGET, expr->id());
2157 RecordJSReturnSite(expr); 2105 RecordJSReturnSite(expr);
2158 // Restore context register. 2106 // Restore context register.
2159 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 2107 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
2160 context()->DropAndPlug(1, v0); // Drop the key still on the stack. 2108 context()->DropAndPlug(1, v0); // Drop the key still on the stack.
2161 } 2109 }
2162 2110
2163 2111
2164 void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) { 2112 void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) {
2165 // Code common for calls using the call stub. 2113 // Code common for calls using the call stub.
2166 ZoneList<Expression*>* args = expr->arguments(); 2114 ZoneList<Expression*>* args = expr->arguments();
(...skipping 19 matching lines...) Expand all
2186 int arg_count) { 2134 int arg_count) {
2187 // Push copy of the first argument or undefined if it doesn't exist. 2135 // Push copy of the first argument or undefined if it doesn't exist.
2188 if (arg_count > 0) { 2136 if (arg_count > 0) {
2189 __ lw(a1, MemOperand(sp, arg_count * kPointerSize)); 2137 __ lw(a1, MemOperand(sp, arg_count * kPointerSize));
2190 } else { 2138 } else {
2191 __ LoadRoot(a1, Heap::kUndefinedValueRootIndex); 2139 __ LoadRoot(a1, Heap::kUndefinedValueRootIndex);
2192 } 2140 }
2193 __ push(a1); 2141 __ push(a1);
2194 2142
2195 // Push the receiver of the enclosing function and do runtime call. 2143 // Push the receiver of the enclosing function and do runtime call.
2196 __ lw(a1, MemOperand(fp, (2 + scope()->num_parameters()) * kPointerSize)); 2144 int receiver_offset = 2 + info_->scope()->num_parameters();
2145 __ lw(a1, MemOperand(fp, receiver_offset * kPointerSize));
2197 __ push(a1); 2146 __ push(a1);
2198 // Push the strict mode flag. 2147 // Push the strict mode flag.
2199 __ li(a1, Operand(Smi::FromInt(strict_mode_flag()))); 2148 __ li(a1, Operand(Smi::FromInt(strict_mode_flag())));
2200 __ push(a1); 2149 __ push(a1);
2201 2150
2202 __ CallRuntime(flag == SKIP_CONTEXT_LOOKUP 2151 __ CallRuntime(flag == SKIP_CONTEXT_LOOKUP
2203 ? Runtime::kResolvePossiblyDirectEvalNoLookup 2152 ? Runtime::kResolvePossiblyDirectEvalNoLookup
2204 : Runtime::kResolvePossiblyDirectEval, 4); 2153 : Runtime::kResolvePossiblyDirectEval, 4);
2205 } 2154 }
2206 2155
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
2303 2252
2304 // If fast case code has been generated, emit code to push the 2253 // If fast case code has been generated, emit code to push the
2305 // function and receiver and have the slow path jump around this 2254 // function and receiver and have the slow path jump around this
2306 // code. 2255 // code.
2307 if (done.is_linked()) { 2256 if (done.is_linked()) {
2308 Label call; 2257 Label call;
2309 __ Branch(&call); 2258 __ Branch(&call);
2310 __ bind(&done); 2259 __ bind(&done);
2311 // Push function. 2260 // Push function.
2312 __ push(v0); 2261 __ push(v0);
2313 // Push global receiver. 2262 // The receiver is implicitly the global receiver. Indicate this
2314 __ lw(a1, GlobalObjectOperand()); 2263 // by passing the hole to the call function stub.
2315 __ lw(a1, FieldMemOperand(a1, GlobalObject::kGlobalReceiverOffset)); 2264 __ LoadRoot(a1, Heap::kTheHoleValueRootIndex);
2316 __ push(a1); 2265 __ push(a1);
2317 __ bind(&call); 2266 __ bind(&call);
2318 } 2267 }
2319 2268
2320 // The receiver is either the global receiver or an object found 2269 // The receiver is either the global receiver or an object found
2321 // by LoadContextSlot. That object could be the hole if the 2270 // by LoadContextSlot. That object could be the hole if the
2322 // receiver is implicitly the global object. 2271 // receiver is implicitly the global object.
2323 EmitCallWithStub(expr, RECEIVER_MIGHT_BE_IMPLICIT); 2272 EmitCallWithStub(expr, RECEIVER_MIGHT_BE_IMPLICIT);
2324 } else if (fun->AsProperty() != NULL) { 2273 } else if (fun->AsProperty() != NULL) {
2325 // Call to an object property. 2274 // Call to an object property.
2326 Property* prop = fun->AsProperty(); 2275 Property* prop = fun->AsProperty();
2327 Literal* key = prop->key()->AsLiteral(); 2276 Literal* key = prop->key()->AsLiteral();
2328 if (key != NULL && key->handle()->IsSymbol()) { 2277 if (key != NULL && key->handle()->IsSymbol()) {
2329 // Call to a named property, use call IC. 2278 // Call to a named property, use call IC.
2330 { PreservePositionScope scope(masm()->positions_recorder()); 2279 { PreservePositionScope scope(masm()->positions_recorder());
2331 VisitForStackValue(prop->obj()); 2280 VisitForStackValue(prop->obj());
2332 } 2281 }
2333 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); 2282 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET);
2334 } else { 2283 } else {
2335 // Call to a keyed property. 2284 // Call to a keyed property.
2336 // For a synthetic property use keyed load IC followed by function call, 2285 // For a synthetic property use keyed load IC followed by function call,
2337 // for a regular property use keyed EmitCallIC. 2286 // for a regular property use EmitKeyedCallWithIC.
2338 if (prop->is_synthetic()) { 2287 if (prop->is_synthetic()) {
2339 // Do not visit the object and key subexpressions (they are shared 2288 // Do not visit the object and key subexpressions (they are shared
2340 // by all occurrences of the same rewritten parameter). 2289 // by all occurrences of the same rewritten parameter).
2341 ASSERT(prop->obj()->AsVariableProxy() != NULL); 2290 ASSERT(prop->obj()->AsVariableProxy() != NULL);
2342 ASSERT(prop->obj()->AsVariableProxy()->var()->AsSlot() != NULL); 2291 ASSERT(prop->obj()->AsVariableProxy()->var()->AsSlot() != NULL);
2343 Slot* slot = prop->obj()->AsVariableProxy()->var()->AsSlot(); 2292 Slot* slot = prop->obj()->AsVariableProxy()->var()->AsSlot();
2344 MemOperand operand = EmitSlotSearch(slot, a1); 2293 MemOperand operand = EmitSlotSearch(slot, a1);
2345 __ lw(a1, operand); 2294 __ lw(a1, operand);
2346 2295
2347 ASSERT(prop->key()->AsLiteral() != NULL); 2296 ASSERT(prop->key()->AsLiteral() != NULL);
2348 ASSERT(prop->key()->AsLiteral()->handle()->IsSmi()); 2297 ASSERT(prop->key()->AsLiteral()->handle()->IsSmi());
2349 __ li(a0, Operand(prop->key()->AsLiteral()->handle())); 2298 __ li(a0, Operand(prop->key()->AsLiteral()->handle()));
2350 2299
2351 // Record source code position for IC call. 2300 // Record source code position for IC call.
2352 SetSourcePosition(prop->position()); 2301 SetSourcePosition(prop->position());
2353 2302
2354 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); 2303 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
2355 EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(prop)); 2304 __ Call(ic, RelocInfo::CODE_TARGET, GetPropertyId(prop));
2356 __ lw(a1, GlobalObjectOperand()); 2305 __ lw(a1, GlobalObjectOperand());
2357 __ lw(a1, FieldMemOperand(a1, GlobalObject::kGlobalReceiverOffset)); 2306 __ lw(a1, FieldMemOperand(a1, GlobalObject::kGlobalReceiverOffset));
2358 __ Push(v0, a1); // Function, receiver. 2307 __ Push(v0, a1); // Function, receiver.
2359 EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS); 2308 EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS);
2360 } else { 2309 } else {
2361 { PreservePositionScope scope(masm()->positions_recorder()); 2310 { PreservePositionScope scope(masm()->positions_recorder());
2362 VisitForStackValue(prop->obj()); 2311 VisitForStackValue(prop->obj());
2363 } 2312 }
2364 EmitKeyedCallWithIC(expr, prop->key()); 2313 EmitKeyedCallWithIC(expr, prop->key());
2365 } 2314 }
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
2470 2419
2471 __ JumpIfSmi(v0, if_false); 2420 __ JumpIfSmi(v0, if_false);
2472 __ LoadRoot(at, Heap::kNullValueRootIndex); 2421 __ LoadRoot(at, Heap::kNullValueRootIndex);
2473 __ Branch(if_true, eq, v0, Operand(at)); 2422 __ Branch(if_true, eq, v0, Operand(at));
2474 __ lw(a2, FieldMemOperand(v0, HeapObject::kMapOffset)); 2423 __ lw(a2, FieldMemOperand(v0, HeapObject::kMapOffset));
2475 // Undetectable objects behave like undefined when tested with typeof. 2424 // Undetectable objects behave like undefined when tested with typeof.
2476 __ lbu(a1, FieldMemOperand(a2, Map::kBitFieldOffset)); 2425 __ lbu(a1, FieldMemOperand(a2, Map::kBitFieldOffset));
2477 __ And(at, a1, Operand(1 << Map::kIsUndetectable)); 2426 __ And(at, a1, Operand(1 << Map::kIsUndetectable));
2478 __ Branch(if_false, ne, at, Operand(zero_reg)); 2427 __ Branch(if_false, ne, at, Operand(zero_reg));
2479 __ lbu(a1, FieldMemOperand(a2, Map::kInstanceTypeOffset)); 2428 __ lbu(a1, FieldMemOperand(a2, Map::kInstanceTypeOffset));
2480 __ Branch(if_false, lt, a1, Operand(FIRST_JS_OBJECT_TYPE)); 2429 __ Branch(if_false, lt, a1, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
2481 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 2430 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2482 Split(le, a1, Operand(LAST_JS_OBJECT_TYPE), if_true, if_false, fall_through); 2431 Split(le, a1, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE),
2432 if_true, if_false, fall_through);
2483 2433
2484 context()->Plug(if_true, if_false); 2434 context()->Plug(if_true, if_false);
2485 } 2435 }
2486 2436
2487 2437
2488 void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) { 2438 void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) {
2489 ASSERT(args->length() == 1); 2439 ASSERT(args->length() == 1);
2490 2440
2491 VisitForAccumulatorValue(args->at(0)); 2441 VisitForAccumulatorValue(args->at(0));
2492 2442
2493 Label materialize_true, materialize_false; 2443 Label materialize_true, materialize_false;
2494 Label* if_true = NULL; 2444 Label* if_true = NULL;
2495 Label* if_false = NULL; 2445 Label* if_false = NULL;
2496 Label* fall_through = NULL; 2446 Label* fall_through = NULL;
2497 context()->PrepareTest(&materialize_true, &materialize_false, 2447 context()->PrepareTest(&materialize_true, &materialize_false,
2498 &if_true, &if_false, &fall_through); 2448 &if_true, &if_false, &fall_through);
2499 2449
2500 __ JumpIfSmi(v0, if_false); 2450 __ JumpIfSmi(v0, if_false);
2501 __ GetObjectType(v0, a1, a1); 2451 __ GetObjectType(v0, a1, a1);
2502 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 2452 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2503 Split(ge, a1, Operand(FIRST_JS_OBJECT_TYPE), 2453 Split(ge, a1, Operand(FIRST_SPEC_OBJECT_TYPE),
2504 if_true, if_false, fall_through); 2454 if_true, if_false, fall_through);
2505 2455
2506 context()->Plug(if_true, if_false); 2456 context()->Plug(if_true, if_false);
2507 } 2457 }
2508 2458
2509 2459
2510 void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) { 2460 void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) {
2511 ASSERT(args->length() == 1); 2461 ASSERT(args->length() == 1);
2512 2462
2513 VisitForAccumulatorValue(args->at(0)); 2463 VisitForAccumulatorValue(args->at(0));
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
2731 } 2681 }
2732 2682
2733 2683
2734 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) { 2684 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) {
2735 ASSERT(args->length() == 1); 2685 ASSERT(args->length() == 1);
2736 2686
2737 // ArgumentsAccessStub expects the key in a1 and the formal 2687 // ArgumentsAccessStub expects the key in a1 and the formal
2738 // parameter count in a0. 2688 // parameter count in a0.
2739 VisitForAccumulatorValue(args->at(0)); 2689 VisitForAccumulatorValue(args->at(0));
2740 __ mov(a1, v0); 2690 __ mov(a1, v0);
2741 __ li(a0, Operand(Smi::FromInt(scope()->num_parameters()))); 2691 __ li(a0, Operand(Smi::FromInt(info_->scope()->num_parameters())));
2742 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); 2692 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
2743 __ CallStub(&stub); 2693 __ CallStub(&stub);
2744 context()->Plug(v0); 2694 context()->Plug(v0);
2745 } 2695 }
2746 2696
2747 2697
2748 void FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) { 2698 void FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) {
2749 ASSERT(args->length() == 0); 2699 ASSERT(args->length() == 0);
2750 2700
2751 Label exit; 2701 Label exit;
2752 // Get the number of formal parameters. 2702 // Get the number of formal parameters.
2753 __ li(v0, Operand(Smi::FromInt(scope()->num_parameters()))); 2703 __ li(v0, Operand(Smi::FromInt(info_->scope()->num_parameters())));
2754 2704
2755 // Check if the calling frame is an arguments adaptor frame. 2705 // Check if the calling frame is an arguments adaptor frame.
2756 __ lw(a2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); 2706 __ lw(a2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
2757 __ lw(a3, MemOperand(a2, StandardFrameConstants::kContextOffset)); 2707 __ lw(a3, MemOperand(a2, StandardFrameConstants::kContextOffset));
2758 __ Branch(&exit, ne, a3, 2708 __ Branch(&exit, ne, a3,
2759 Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 2709 Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
2760 2710
2761 // Arguments adaptor case: Read the arguments length from the 2711 // Arguments adaptor case: Read the arguments length from the
2762 // adaptor frame. 2712 // adaptor frame.
2763 __ lw(v0, MemOperand(a2, ArgumentsAdaptorFrameConstants::kLengthOffset)); 2713 __ lw(v0, MemOperand(a2, ArgumentsAdaptorFrameConstants::kLengthOffset));
2764 2714
2765 __ bind(&exit); 2715 __ bind(&exit);
2766 context()->Plug(v0); 2716 context()->Plug(v0);
2767 } 2717 }
2768 2718
2769 2719
2770 void FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) { 2720 void FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) {
2771 ASSERT(args->length() == 1); 2721 ASSERT(args->length() == 1);
2772 Label done, null, function, non_function_constructor; 2722 Label done, null, function, non_function_constructor;
2773 2723
2774 VisitForAccumulatorValue(args->at(0)); 2724 VisitForAccumulatorValue(args->at(0));
2775 2725
2776 // If the object is a smi, we return null. 2726 // If the object is a smi, we return null.
2777 __ JumpIfSmi(v0, &null); 2727 __ JumpIfSmi(v0, &null);
2778 2728
2779 // Check that the object is a JS object but take special care of JS 2729 // Check that the object is a JS object but take special care of JS
2780 // functions to make sure they have 'Function' as their class. 2730 // functions to make sure they have 'Function' as their class.
2781 __ GetObjectType(v0, v0, a1); // Map is now in v0. 2731 __ GetObjectType(v0, v0, a1); // Map is now in v0.
2782 __ Branch(&null, lt, a1, Operand(FIRST_JS_OBJECT_TYPE)); 2732 __ Branch(&null, lt, a1, Operand(FIRST_SPEC_OBJECT_TYPE));
2783 2733
2784 // As long as JS_FUNCTION_TYPE is the last instance type and it is 2734 // As long as LAST_CALLABLE_SPEC_OBJECT_TYPE is the last instance type, and
2785 // right after LAST_JS_OBJECT_TYPE, we can avoid checking for 2735 // FIRST_CALLABLE_SPEC_OBJECT_TYPE comes right after
2786 // LAST_JS_OBJECT_TYPE. 2736 // LAST_NONCALLABLE_SPEC_OBJECT_TYPE, we can avoid checking for the latter.
2787 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); 2737 STATIC_ASSERT(LAST_TYPE == LAST_CALLABLE_SPEC_OBJECT_TYPE);
2788 ASSERT(JS_FUNCTION_TYPE == LAST_JS_OBJECT_TYPE + 1); 2738 STATIC_ASSERT(FIRST_CALLABLE_SPEC_OBJECT_TYPE ==
2789 __ Branch(&function, eq, a1, Operand(JS_FUNCTION_TYPE)); 2739 LAST_NONCALLABLE_SPEC_OBJECT_TYPE + 1);
2740 __ Branch(&function, ge, a1, Operand(FIRST_CALLABLE_SPEC_OBJECT_TYPE));
2790 2741
2791 // Check if the constructor in the map is a function. 2742 // Check if the constructor in the map is a function.
2792 __ lw(v0, FieldMemOperand(v0, Map::kConstructorOffset)); 2743 __ lw(v0, FieldMemOperand(v0, Map::kConstructorOffset));
2793 __ GetObjectType(v0, a1, a1); 2744 __ GetObjectType(v0, a1, a1);
2794 __ Branch(&non_function_constructor, ne, a1, Operand(JS_FUNCTION_TYPE)); 2745 __ Branch(&non_function_constructor, ne, a1, Operand(JS_FUNCTION_TYPE));
2795 2746
2796 // v0 now contains the constructor function. Grab the 2747 // v0 now contains the constructor function. Grab the
2797 // instance class name from there. 2748 // instance class name from there.
2798 __ lw(v0, FieldMemOperand(v0, JSFunction::kSharedFunctionInfoOffset)); 2749 __ lw(v0, FieldMemOperand(v0, JSFunction::kSharedFunctionInfoOffset));
2799 __ lw(v0, FieldMemOperand(v0, SharedFunctionInfo::kInstanceClassNameOffset)); 2750 __ lw(v0, FieldMemOperand(v0, SharedFunctionInfo::kInstanceClassNameOffset));
(...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after
3177 3128
3178 int arg_count = args->length() - 2; // 2 ~ receiver and function. 3129 int arg_count = args->length() - 2; // 2 ~ receiver and function.
3179 for (int i = 0; i < arg_count + 1; i++) { 3130 for (int i = 0; i < arg_count + 1; i++) {
3180 VisitForStackValue(args->at(i)); 3131 VisitForStackValue(args->at(i));
3181 } 3132 }
3182 VisitForAccumulatorValue(args->last()); // Function. 3133 VisitForAccumulatorValue(args->last()); // Function.
3183 3134
3184 // InvokeFunction requires the function in a1. Move it in there. 3135 // InvokeFunction requires the function in a1. Move it in there.
3185 __ mov(a1, result_register()); 3136 __ mov(a1, result_register());
3186 ParameterCount count(arg_count); 3137 ParameterCount count(arg_count);
3187 __ InvokeFunction(a1, count, CALL_FUNCTION); 3138 __ InvokeFunction(a1, count, CALL_FUNCTION,
3139 NullCallWrapper(), CALL_AS_METHOD);
3188 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 3140 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
3189 context()->Plug(v0); 3141 context()->Plug(v0);
3190 } 3142 }
3191 3143
3192 3144
3193 void FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) { 3145 void FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) {
3194 RegExpConstructResultStub stub; 3146 RegExpConstructResultStub stub;
3195 ASSERT(args->length() == 3); 3147 ASSERT(args->length() == 3);
3196 VisitForStackValue(args->at(0)); 3148 VisitForStackValue(args->at(0));
3197 VisitForStackValue(args->at(1)); 3149 VisitForStackValue(args->at(1));
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after
3436 3388
3437 // Separator operand is on the stack. 3389 // Separator operand is on the stack.
3438 __ pop(separator); 3390 __ pop(separator);
3439 3391
3440 // Check that the array is a JSArray. 3392 // Check that the array is a JSArray.
3441 __ JumpIfSmi(array, &bailout); 3393 __ JumpIfSmi(array, &bailout);
3442 __ GetObjectType(array, scratch1, scratch2); 3394 __ GetObjectType(array, scratch1, scratch2);
3443 __ Branch(&bailout, ne, scratch2, Operand(JS_ARRAY_TYPE)); 3395 __ Branch(&bailout, ne, scratch2, Operand(JS_ARRAY_TYPE));
3444 3396
3445 // Check that the array has fast elements. 3397 // Check that the array has fast elements.
3446 __ lbu(scratch2, FieldMemOperand(scratch1, Map::kBitField2Offset)); 3398 __ CheckFastElements(scratch1, scratch2, &bailout);
3447 __ And(scratch3, scratch2, Operand(1 << Map::kHasFastElements));
3448 __ Branch(&bailout, eq, scratch3, Operand(zero_reg));
3449 3399
3450 // If the array has length zero, return the empty string. 3400 // If the array has length zero, return the empty string.
3451 __ lw(array_length, FieldMemOperand(array, JSArray::kLengthOffset)); 3401 __ lw(array_length, FieldMemOperand(array, JSArray::kLengthOffset));
3452 __ SmiUntag(array_length); 3402 __ SmiUntag(array_length);
3453 __ Branch(&non_trivial_array, ne, array_length, Operand(zero_reg)); 3403 __ Branch(&non_trivial_array, ne, array_length, Operand(zero_reg));
3454 __ LoadRoot(v0, Heap::kEmptyStringRootIndex); 3404 __ LoadRoot(v0, Heap::kEmptyStringRootIndex);
3455 __ Branch(&done); 3405 __ Branch(&done);
3456 3406
3457 __ bind(&non_trivial_array); 3407 __ bind(&non_trivial_array);
3458 3408
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
3642 ASSERT(result.is(v0)); 3592 ASSERT(result.is(v0));
3643 __ Branch(&done); 3593 __ Branch(&done);
3644 3594
3645 __ bind(&bailout); 3595 __ bind(&bailout);
3646 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex); 3596 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex);
3647 __ bind(&done); 3597 __ bind(&done);
3648 context()->Plug(v0); 3598 context()->Plug(v0);
3649 } 3599 }
3650 3600
3651 3601
3602 void FullCodeGenerator::EmitIsNativeOrStrictMode(ZoneList<Expression*>* args) {
3603 ASSERT(args->length() == 1);
3604
3605 // Load the function into v0.
3606 VisitForAccumulatorValue(args->at(0));
3607
3608 // Prepare for the test.
3609 Label materialize_true, materialize_false;
3610 Label* if_true = NULL;
3611 Label* if_false = NULL;
3612 Label* fall_through = NULL;
3613 context()->PrepareTest(&materialize_true, &materialize_false,
3614 &if_true, &if_false, &fall_through);
3615
3616 // Test for strict mode function.
3617 __ lw(a1, FieldMemOperand(v0, JSFunction::kSharedFunctionInfoOffset));
3618 __ lw(a1, FieldMemOperand(a1, SharedFunctionInfo::kCompilerHintsOffset));
3619 __ And(at, a1, Operand(1 << (SharedFunctionInfo::kStrictModeFunction +
3620 kSmiTagSize)));
3621 __ Branch(if_true, ne, at, Operand(zero_reg));
3622
3623 // Test for native function.
3624 __ And(at, a1, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize)));
3625 __ Branch(if_true, ne, at, Operand(zero_reg));
3626
3627 // Not native or strict-mode function.
3628 __ Branch(if_false);
3629
3630 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
3631 context()->Plug(if_true, if_false);
3632 }
3633
3634
3652 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { 3635 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
3653 Handle<String> name = expr->name(); 3636 Handle<String> name = expr->name();
3654 if (name->length() > 0 && name->Get(0) == '_') { 3637 if (name->length() > 0 && name->Get(0) == '_') {
3655 Comment cmnt(masm_, "[ InlineRuntimeCall"); 3638 Comment cmnt(masm_, "[ InlineRuntimeCall");
3656 EmitInlineRuntimeCall(expr); 3639 EmitInlineRuntimeCall(expr);
3657 return; 3640 return;
3658 } 3641 }
3659 3642
3660 Comment cmnt(masm_, "[ CallRuntime"); 3643 Comment cmnt(masm_, "[ CallRuntime");
3661 ZoneList<Expression*>* args = expr->arguments(); 3644 ZoneList<Expression*>* args = expr->arguments();
(...skipping 12 matching lines...) Expand all
3674 } 3657 }
3675 3658
3676 if (expr->is_jsruntime()) { 3659 if (expr->is_jsruntime()) {
3677 // Call the JS runtime function. 3660 // Call the JS runtime function.
3678 __ li(a2, Operand(expr->name())); 3661 __ li(a2, Operand(expr->name()));
3679 RelocInfo::Mode mode = RelocInfo::CODE_TARGET; 3662 RelocInfo::Mode mode = RelocInfo::CODE_TARGET;
3680 Handle<Code> ic = 3663 Handle<Code> ic =
3681 isolate()->stub_cache()->ComputeCallInitialize(arg_count, 3664 isolate()->stub_cache()->ComputeCallInitialize(arg_count,
3682 NOT_IN_LOOP, 3665 NOT_IN_LOOP,
3683 mode); 3666 mode);
3684 EmitCallIC(ic, mode, expr->id()); 3667 __ Call(ic, mode, expr->id());
3685 // Restore context register. 3668 // Restore context register.
3686 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 3669 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
3687 } else { 3670 } else {
3688 // Call the C runtime function. 3671 // Call the C runtime function.
3689 __ CallRuntime(expr->function(), arg_count); 3672 __ CallRuntime(expr->function(), arg_count);
3690 } 3673 }
3691 context()->Plug(v0); 3674 context()->Plug(v0);
3692 } 3675 }
3693 3676
3694 3677
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
3817 // TODO(svenpanne): Allowing format strings in Comment would be nice here... 3800 // TODO(svenpanne): Allowing format strings in Comment would be nice here...
3818 Comment cmt(masm_, comment); 3801 Comment cmt(masm_, comment);
3819 bool can_overwrite = expr->expression()->ResultOverwriteAllowed(); 3802 bool can_overwrite = expr->expression()->ResultOverwriteAllowed();
3820 UnaryOverwriteMode overwrite = 3803 UnaryOverwriteMode overwrite =
3821 can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; 3804 can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
3822 UnaryOpStub stub(expr->op(), overwrite); 3805 UnaryOpStub stub(expr->op(), overwrite);
3823 // GenericUnaryOpStub expects the argument to be in a0. 3806 // GenericUnaryOpStub expects the argument to be in a0.
3824 VisitForAccumulatorValue(expr->expression()); 3807 VisitForAccumulatorValue(expr->expression());
3825 SetSourcePosition(expr->position()); 3808 SetSourcePosition(expr->position());
3826 __ mov(a0, result_register()); 3809 __ mov(a0, result_register());
3827 EmitCallIC(stub.GetCode(), NULL, expr->id()); 3810 __ Call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id());
3828 context()->Plug(v0); 3811 context()->Plug(v0);
3829 } 3812 }
3830 3813
3831 3814
3832 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { 3815 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
3833 Comment cmnt(masm_, "[ CountOperation"); 3816 Comment cmnt(masm_, "[ CountOperation");
3834 SetSourcePosition(expr->position()); 3817 SetSourcePosition(expr->position());
3835 3818
3836 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' 3819 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
3837 // as the left-hand side. 3820 // as the left-hand side.
3838 if (!expr->expression()->IsValidLeftHandSide()) { 3821 if (!expr->expression()->IsValidLeftHandSide()) {
3839 VisitForEffect(expr->expression()); 3822 VisitForEffect(expr->expression());
3840 return; 3823 return;
3841 } 3824 }
3842 3825
3843 // Expression can only be a property, a global or a (parameter or local) 3826 // Expression can only be a property, a global or a (parameter or local)
3844 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. 3827 // slot.
3845 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 3828 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
3846 LhsKind assign_type = VARIABLE; 3829 LhsKind assign_type = VARIABLE;
3847 Property* prop = expr->expression()->AsProperty(); 3830 Property* prop = expr->expression()->AsProperty();
3848 // In case of a property we use the uninitialized expression context 3831 // In case of a property we use the uninitialized expression context
3849 // of the key to detect a named property. 3832 // of the key to detect a named property.
3850 if (prop != NULL) { 3833 if (prop != NULL) {
3851 assign_type = 3834 assign_type =
3852 (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; 3835 (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY;
3853 } 3836 }
3854 3837
3855 // Evaluate expression and get value. 3838 // Evaluate expression and get value.
3856 if (assign_type == VARIABLE) { 3839 if (assign_type == VARIABLE) {
3857 ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); 3840 ASSERT(expr->expression()->AsVariableProxy()->var() != NULL);
3858 AccumulatorValueContext context(this); 3841 AccumulatorValueContext context(this);
3859 EmitVariableLoad(expr->expression()->AsVariableProxy()->var()); 3842 EmitVariableLoad(expr->expression()->AsVariableProxy()->var());
3860 } else { 3843 } else {
3861 // Reserve space for result of postfix operation. 3844 // Reserve space for result of postfix operation.
3862 if (expr->is_postfix() && !context()->IsEffect()) { 3845 if (expr->is_postfix() && !context()->IsEffect()) {
3863 __ li(at, Operand(Smi::FromInt(0))); 3846 __ li(at, Operand(Smi::FromInt(0)));
3864 __ push(at); 3847 __ push(at);
3865 } 3848 }
3866 if (assign_type == NAMED_PROPERTY) { 3849 if (assign_type == NAMED_PROPERTY) {
3867 // Put the object both on the stack and in the accumulator. 3850 // Put the object both on the stack and in the accumulator.
3868 VisitForAccumulatorValue(prop->obj()); 3851 VisitForAccumulatorValue(prop->obj());
3869 __ push(v0); 3852 __ push(v0);
3870 EmitNamedPropertyLoad(prop); 3853 EmitNamedPropertyLoad(prop);
3871 } else { 3854 } else {
3872 if (prop->is_arguments_access()) { 3855 VisitForStackValue(prop->obj());
3873 VariableProxy* obj_proxy = prop->obj()->AsVariableProxy(); 3856 VisitForAccumulatorValue(prop->key());
3874 __ lw(v0, EmitSlotSearch(obj_proxy->var()->AsSlot(), v0));
3875 __ push(v0);
3876 __ li(v0, Operand(prop->key()->AsLiteral()->handle()));
3877 } else {
3878 VisitForStackValue(prop->obj());
3879 VisitForAccumulatorValue(prop->key());
3880 }
3881 __ lw(a1, MemOperand(sp, 0)); 3857 __ lw(a1, MemOperand(sp, 0));
3882 __ push(v0); 3858 __ push(v0);
3883 EmitKeyedPropertyLoad(prop); 3859 EmitKeyedPropertyLoad(prop);
3884 } 3860 }
3885 } 3861 }
3886 3862
3887 // We need a second deoptimization point after loading the value 3863 // We need a second deoptimization point after loading the value
3888 // in case evaluating the property load my have a side effect. 3864 // in case evaluating the property load my have a side effect.
3889 if (assign_type == VARIABLE) { 3865 if (assign_type == VARIABLE) {
3890 PrepareForBailout(expr->expression(), TOS_REG); 3866 PrepareForBailout(expr->expression(), TOS_REG);
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
3935 // We could eliminate this smi check if we split the code at 3911 // We could eliminate this smi check if we split the code at
3936 // the first smi check before calling ToNumber. 3912 // the first smi check before calling ToNumber.
3937 patch_site.EmitJumpIfSmi(v0, &done); 3913 patch_site.EmitJumpIfSmi(v0, &done);
3938 __ bind(&stub_call); 3914 __ bind(&stub_call);
3939 } 3915 }
3940 3916
3941 // Record position before stub call. 3917 // Record position before stub call.
3942 SetSourcePosition(expr->position()); 3918 SetSourcePosition(expr->position());
3943 3919
3944 BinaryOpStub stub(Token::ADD, NO_OVERWRITE); 3920 BinaryOpStub stub(Token::ADD, NO_OVERWRITE);
3945 EmitCallIC(stub.GetCode(), &patch_site, expr->CountId()); 3921 __ Call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->CountId());
3922 patch_site.EmitPatchInfo();
3946 __ bind(&done); 3923 __ bind(&done);
3947 3924
3948 // Store the value returned in v0. 3925 // Store the value returned in v0.
3949 switch (assign_type) { 3926 switch (assign_type) {
3950 case VARIABLE: 3927 case VARIABLE:
3951 if (expr->is_postfix()) { 3928 if (expr->is_postfix()) {
3952 { EffectContext context(this); 3929 { EffectContext context(this);
3953 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 3930 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
3954 Token::ASSIGN); 3931 Token::ASSIGN);
3955 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 3932 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
(...skipping 11 matching lines...) Expand all
3967 context()->Plug(v0); 3944 context()->Plug(v0);
3968 } 3945 }
3969 break; 3946 break;
3970 case NAMED_PROPERTY: { 3947 case NAMED_PROPERTY: {
3971 __ mov(a0, result_register()); // Value. 3948 __ mov(a0, result_register()); // Value.
3972 __ li(a2, Operand(prop->key()->AsLiteral()->handle())); // Name. 3949 __ li(a2, Operand(prop->key()->AsLiteral()->handle())); // Name.
3973 __ pop(a1); // Receiver. 3950 __ pop(a1); // Receiver.
3974 Handle<Code> ic = is_strict_mode() 3951 Handle<Code> ic = is_strict_mode()
3975 ? isolate()->builtins()->StoreIC_Initialize_Strict() 3952 ? isolate()->builtins()->StoreIC_Initialize_Strict()
3976 : isolate()->builtins()->StoreIC_Initialize(); 3953 : isolate()->builtins()->StoreIC_Initialize();
3977 EmitCallIC(ic, RelocInfo::CODE_TARGET, expr->id()); 3954 __ Call(ic, RelocInfo::CODE_TARGET, expr->id());
3978 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 3955 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
3979 if (expr->is_postfix()) { 3956 if (expr->is_postfix()) {
3980 if (!context()->IsEffect()) { 3957 if (!context()->IsEffect()) {
3981 context()->PlugTOS(); 3958 context()->PlugTOS();
3982 } 3959 }
3983 } else { 3960 } else {
3984 context()->Plug(v0); 3961 context()->Plug(v0);
3985 } 3962 }
3986 break; 3963 break;
3987 } 3964 }
3988 case KEYED_PROPERTY: { 3965 case KEYED_PROPERTY: {
3989 __ mov(a0, result_register()); // Value. 3966 __ mov(a0, result_register()); // Value.
3990 __ pop(a1); // Key. 3967 __ pop(a1); // Key.
3991 __ pop(a2); // Receiver. 3968 __ pop(a2); // Receiver.
3992 Handle<Code> ic = is_strict_mode() 3969 Handle<Code> ic = is_strict_mode()
3993 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() 3970 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
3994 : isolate()->builtins()->KeyedStoreIC_Initialize(); 3971 : isolate()->builtins()->KeyedStoreIC_Initialize();
3995 EmitCallIC(ic, RelocInfo::CODE_TARGET, expr->id()); 3972 __ Call(ic, RelocInfo::CODE_TARGET, expr->id());
3996 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 3973 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
3997 if (expr->is_postfix()) { 3974 if (expr->is_postfix()) {
3998 if (!context()->IsEffect()) { 3975 if (!context()->IsEffect()) {
3999 context()->PlugTOS(); 3976 context()->PlugTOS();
4000 } 3977 }
4001 } else { 3978 } else {
4002 context()->Plug(v0); 3979 context()->Plug(v0);
4003 } 3980 }
4004 break; 3981 break;
4005 } 3982 }
4006 } 3983 }
4007 } 3984 }
4008 3985
4009 3986
4010 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { 3987 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
4011 VariableProxy* proxy = expr->AsVariableProxy(); 3988 VariableProxy* proxy = expr->AsVariableProxy();
4012 if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) { 3989 if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) {
4013 Comment cmnt(masm_, "Global variable"); 3990 Comment cmnt(masm_, "Global variable");
4014 __ lw(a0, GlobalObjectOperand()); 3991 __ lw(a0, GlobalObjectOperand());
4015 __ li(a2, Operand(proxy->name())); 3992 __ li(a2, Operand(proxy->name()));
4016 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 3993 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
4017 // Use a regular load, not a contextual load, to avoid a reference 3994 // Use a regular load, not a contextual load, to avoid a reference
4018 // error. 3995 // error.
4019 EmitCallIC(ic, RelocInfo::CODE_TARGET, AstNode::kNoNumber); 3996 __ Call(ic);
4020 PrepareForBailout(expr, TOS_REG); 3997 PrepareForBailout(expr, TOS_REG);
4021 context()->Plug(v0); 3998 context()->Plug(v0);
4022 } else if (proxy != NULL && 3999 } else if (proxy != NULL &&
4023 proxy->var()->AsSlot() != NULL && 4000 proxy->var()->AsSlot() != NULL &&
4024 proxy->var()->AsSlot()->type() == Slot::LOOKUP) { 4001 proxy->var()->AsSlot()->type() == Slot::LOOKUP) {
4025 Label done, slow; 4002 Label done, slow;
4026 4003
4027 // Generate code for loading from variables potentially shadowed 4004 // Generate code for loading from variables potentially shadowed
4028 // by eval-introduced variables. 4005 // by eval-introduced variables.
4029 Slot* slot = proxy->var()->AsSlot(); 4006 Slot* slot = proxy->var()->AsSlot();
4030 EmitDynamicLoadFromSlotFastCase(slot, INSIDE_TYPEOF, &slow, &done); 4007 EmitDynamicLoadFromSlotFastCase(slot, INSIDE_TYPEOF, &slow, &done);
4031 4008
4032 __ bind(&slow); 4009 __ bind(&slow);
4033 __ li(a0, Operand(proxy->name())); 4010 __ li(a0, Operand(proxy->name()));
4034 __ Push(cp, a0); 4011 __ Push(cp, a0);
4035 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); 4012 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
4036 PrepareForBailout(expr, TOS_REG); 4013 PrepareForBailout(expr, TOS_REG);
4037 __ bind(&done); 4014 __ bind(&done);
4038 4015
4039 context()->Plug(v0); 4016 context()->Plug(v0);
4040 } else { 4017 } else {
4041 // This expression cannot throw a reference error at the top level. 4018 // This expression cannot throw a reference error at the top level.
4042 context()->HandleExpression(expr); 4019 VisitInCurrentContext(expr);
4043 } 4020 }
4044 } 4021 }
4045 4022
4046 4023 void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
4047 bool FullCodeGenerator::TryLiteralCompare(Token::Value op, 4024 Handle<String> check,
4048 Expression* left, 4025 Label* if_true,
4049 Expression* right, 4026 Label* if_false,
4050 Label* if_true, 4027 Label* fall_through) {
4051 Label* if_false,
4052 Label* fall_through) {
4053 if (op != Token::EQ && op != Token::EQ_STRICT) return false;
4054
4055 // Check for the pattern: typeof <expression> == <string literal>.
4056 Literal* right_literal = right->AsLiteral();
4057 if (right_literal == NULL) return false;
4058 Handle<Object> right_literal_value = right_literal->handle();
4059 if (!right_literal_value->IsString()) return false;
4060 UnaryOperation* left_unary = left->AsUnaryOperation();
4061 if (left_unary == NULL || left_unary->op() != Token::TYPEOF) return false;
4062 Handle<String> check = Handle<String>::cast(right_literal_value);
4063
4064 { AccumulatorValueContext context(this); 4028 { AccumulatorValueContext context(this);
4065 VisitForTypeofValue(left_unary->expression()); 4029 VisitForTypeofValue(expr);
4066 } 4030 }
4067 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 4031 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
4068 4032
4069 if (check->Equals(isolate()->heap()->number_symbol())) { 4033 if (check->Equals(isolate()->heap()->number_symbol())) {
4070 __ JumpIfSmi(v0, if_true); 4034 __ JumpIfSmi(v0, if_true);
4071 __ lw(v0, FieldMemOperand(v0, HeapObject::kMapOffset)); 4035 __ lw(v0, FieldMemOperand(v0, HeapObject::kMapOffset));
4072 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); 4036 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
4073 Split(eq, v0, Operand(at), if_true, if_false, fall_through); 4037 Split(eq, v0, Operand(at), if_true, if_false, fall_through);
4074 } else if (check->Equals(isolate()->heap()->string_symbol())) { 4038 } else if (check->Equals(isolate()->heap()->string_symbol())) {
4075 __ JumpIfSmi(v0, if_false); 4039 __ JumpIfSmi(v0, if_false);
(...skipping 14 matching lines...) Expand all
4090 __ Branch(if_true, eq, v0, Operand(at)); 4054 __ Branch(if_true, eq, v0, Operand(at));
4091 __ JumpIfSmi(v0, if_false); 4055 __ JumpIfSmi(v0, if_false);
4092 // Check for undetectable objects => true. 4056 // Check for undetectable objects => true.
4093 __ lw(v0, FieldMemOperand(v0, HeapObject::kMapOffset)); 4057 __ lw(v0, FieldMemOperand(v0, HeapObject::kMapOffset));
4094 __ lbu(a1, FieldMemOperand(v0, Map::kBitFieldOffset)); 4058 __ lbu(a1, FieldMemOperand(v0, Map::kBitFieldOffset));
4095 __ And(a1, a1, Operand(1 << Map::kIsUndetectable)); 4059 __ And(a1, a1, Operand(1 << Map::kIsUndetectable));
4096 Split(ne, a1, Operand(zero_reg), if_true, if_false, fall_through); 4060 Split(ne, a1, Operand(zero_reg), if_true, if_false, fall_through);
4097 } else if (check->Equals(isolate()->heap()->function_symbol())) { 4061 } else if (check->Equals(isolate()->heap()->function_symbol())) {
4098 __ JumpIfSmi(v0, if_false); 4062 __ JumpIfSmi(v0, if_false);
4099 __ GetObjectType(v0, a1, v0); // Leave map in a1. 4063 __ GetObjectType(v0, a1, v0); // Leave map in a1.
4100 Split(ge, v0, Operand(FIRST_FUNCTION_CLASS_TYPE), 4064 Split(ge, v0, Operand(FIRST_CALLABLE_SPEC_OBJECT_TYPE),
4101 if_true, if_false, fall_through); 4065 if_true, if_false, fall_through);
4102 4066
4103 } else if (check->Equals(isolate()->heap()->object_symbol())) { 4067 } else if (check->Equals(isolate()->heap()->object_symbol())) {
4104 __ JumpIfSmi(v0, if_false); 4068 __ JumpIfSmi(v0, if_false);
4105 __ LoadRoot(at, Heap::kNullValueRootIndex); 4069 __ LoadRoot(at, Heap::kNullValueRootIndex);
4106 __ Branch(if_true, eq, v0, Operand(at)); 4070 __ Branch(if_true, eq, v0, Operand(at));
4107 // Check for JS objects => true. 4071 // Check for JS objects => true.
4108 __ GetObjectType(v0, v0, a1); 4072 __ GetObjectType(v0, v0, a1);
4109 __ Branch(if_false, lo, a1, Operand(FIRST_JS_OBJECT_TYPE)); 4073 __ Branch(if_false, lt, a1, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
4110 __ lbu(a1, FieldMemOperand(v0, Map::kInstanceTypeOffset)); 4074 __ lbu(a1, FieldMemOperand(v0, Map::kInstanceTypeOffset));
4111 __ Branch(if_false, hs, a1, Operand(FIRST_FUNCTION_CLASS_TYPE)); 4075 __ Branch(if_false, gt, a1, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE));
4112 // Check for undetectable objects => false. 4076 // Check for undetectable objects => false.
4113 __ lbu(a1, FieldMemOperand(v0, Map::kBitFieldOffset)); 4077 __ lbu(a1, FieldMemOperand(v0, Map::kBitFieldOffset));
4114 __ And(a1, a1, Operand(1 << Map::kIsUndetectable)); 4078 __ And(a1, a1, Operand(1 << Map::kIsUndetectable));
4115 Split(eq, a1, Operand(zero_reg), if_true, if_false, fall_through); 4079 Split(eq, a1, Operand(zero_reg), if_true, if_false, fall_through);
4116 } else { 4080 } else {
4117 if (if_false != fall_through) __ jmp(if_false); 4081 if (if_false != fall_through) __ jmp(if_false);
4118 } 4082 }
4119
4120 return true;
4121 } 4083 }
4122 4084
4123 4085
4086 void FullCodeGenerator::EmitLiteralCompareUndefined(Expression* expr,
4087 Label* if_true,
4088 Label* if_false,
4089 Label* fall_through) {
4090 VisitForAccumulatorValue(expr);
4091 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
4092
4093 __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
4094 Split(eq, v0, Operand(at), if_true, if_false, fall_through);
4095 }
4096
4097
4124 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { 4098 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
4125 Comment cmnt(masm_, "[ CompareOperation"); 4099 Comment cmnt(masm_, "[ CompareOperation");
4126 SetSourcePosition(expr->position()); 4100 SetSourcePosition(expr->position());
4127 4101
4128 // Always perform the comparison for its control flow. Pack the result 4102 // Always perform the comparison for its control flow. Pack the result
4129 // into the expression's context after the comparison is performed. 4103 // into the expression's context after the comparison is performed.
4130 4104
4131 Label materialize_true, materialize_false; 4105 Label materialize_true, materialize_false;
4132 Label* if_true = NULL; 4106 Label* if_true = NULL;
4133 Label* if_false = NULL; 4107 Label* if_false = NULL;
4134 Label* fall_through = NULL; 4108 Label* fall_through = NULL;
4135 context()->PrepareTest(&materialize_true, &materialize_false, 4109 context()->PrepareTest(&materialize_true, &materialize_false,
4136 &if_true, &if_false, &fall_through); 4110 &if_true, &if_false, &fall_through);
4137 4111
4138 // First we try a fast inlined version of the compare when one of 4112 // First we try a fast inlined version of the compare when one of
4139 // the operands is a literal. 4113 // the operands is a literal.
4140 Token::Value op = expr->op(); 4114 if (TryLiteralCompare(expr, if_true, if_false, fall_through)) {
4141 Expression* left = expr->left();
4142 Expression* right = expr->right();
4143 if (TryLiteralCompare(op, left, right, if_true, if_false, fall_through)) {
4144 context()->Plug(if_true, if_false); 4115 context()->Plug(if_true, if_false);
4145 return; 4116 return;
4146 } 4117 }
4147 4118
4119 Token::Value op = expr->op();
4148 VisitForStackValue(expr->left()); 4120 VisitForStackValue(expr->left());
4149 switch (op) { 4121 switch (op) {
4150 case Token::IN: 4122 case Token::IN:
4151 VisitForStackValue(expr->right()); 4123 VisitForStackValue(expr->right());
4152 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); 4124 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
4153 PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); 4125 PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
4154 __ LoadRoot(t0, Heap::kTrueValueRootIndex); 4126 __ LoadRoot(t0, Heap::kTrueValueRootIndex);
4155 Split(eq, v0, Operand(t0), if_true, if_false, fall_through); 4127 Split(eq, v0, Operand(t0), if_true, if_false, fall_through);
4156 break; 4128 break;
4157 4129
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
4211 if (inline_smi_code) { 4183 if (inline_smi_code) {
4212 Label slow_case; 4184 Label slow_case;
4213 __ Or(a2, a0, Operand(a1)); 4185 __ Or(a2, a0, Operand(a1));
4214 patch_site.EmitJumpIfNotSmi(a2, &slow_case); 4186 patch_site.EmitJumpIfNotSmi(a2, &slow_case);
4215 Split(cc, a1, Operand(a0), if_true, if_false, NULL); 4187 Split(cc, a1, Operand(a0), if_true, if_false, NULL);
4216 __ bind(&slow_case); 4188 __ bind(&slow_case);
4217 } 4189 }
4218 // Record position and call the compare IC. 4190 // Record position and call the compare IC.
4219 SetSourcePosition(expr->position()); 4191 SetSourcePosition(expr->position());
4220 Handle<Code> ic = CompareIC::GetUninitialized(op); 4192 Handle<Code> ic = CompareIC::GetUninitialized(op);
4221 EmitCallIC(ic, &patch_site, expr->id()); 4193 __ Call(ic, RelocInfo::CODE_TARGET, expr->id());
4194 patch_site.EmitPatchInfo();
4222 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 4195 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
4223 Split(cc, v0, Operand(zero_reg), if_true, if_false, fall_through); 4196 Split(cc, v0, Operand(zero_reg), if_true, if_false, fall_through);
4224 } 4197 }
4225 } 4198 }
4226 4199
4227 // Convert the result of the comparison into one expected for this 4200 // Convert the result of the comparison into one expected for this
4228 // expression's context. 4201 // expression's context.
4229 context()->Plug(if_true, if_false); 4202 context()->Plug(if_true, if_false);
4230 } 4203 }
4231 4204
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
4270 Register FullCodeGenerator::result_register() { 4243 Register FullCodeGenerator::result_register() {
4271 return v0; 4244 return v0;
4272 } 4245 }
4273 4246
4274 4247
4275 Register FullCodeGenerator::context_register() { 4248 Register FullCodeGenerator::context_register() {
4276 return cp; 4249 return cp;
4277 } 4250 }
4278 4251
4279 4252
4280 void FullCodeGenerator::EmitCallIC(Handle<Code> ic,
4281 RelocInfo::Mode mode,
4282 unsigned ast_id) {
4283 ASSERT(mode == RelocInfo::CODE_TARGET ||
4284 mode == RelocInfo::CODE_TARGET_CONTEXT);
4285 Counters* counters = isolate()->counters();
4286 switch (ic->kind()) {
4287 case Code::LOAD_IC:
4288 __ IncrementCounter(counters->named_load_full(), 1, a1, a2);
4289 break;
4290 case Code::KEYED_LOAD_IC:
4291 __ IncrementCounter(counters->keyed_load_full(), 1, a1, a2);
4292 break;
4293 case Code::STORE_IC:
4294 __ IncrementCounter(counters->named_store_full(), 1, a1, a2);
4295 break;
4296 case Code::KEYED_STORE_IC:
4297 __ IncrementCounter(counters->keyed_store_full(), 1, a1, a2);
4298 default:
4299 break;
4300 }
4301 if (ast_id == kNoASTId || mode == RelocInfo::CODE_TARGET_CONTEXT) {
4302 __ Call(ic, mode);
4303 } else {
4304 ASSERT(mode == RelocInfo::CODE_TARGET);
4305 mode = RelocInfo::CODE_TARGET_WITH_ID;
4306 __ CallWithAstId(ic, mode, ast_id);
4307 }
4308 }
4309
4310
4311 void FullCodeGenerator::EmitCallIC(Handle<Code> ic,
4312 JumpPatchSite* patch_site,
4313 unsigned ast_id) {
4314 Counters* counters = isolate()->counters();
4315 switch (ic->kind()) {
4316 case Code::LOAD_IC:
4317 __ IncrementCounter(counters->named_load_full(), 1, a1, a2);
4318 break;
4319 case Code::KEYED_LOAD_IC:
4320 __ IncrementCounter(counters->keyed_load_full(), 1, a1, a2);
4321 break;
4322 case Code::STORE_IC:
4323 __ IncrementCounter(counters->named_store_full(), 1, a1, a2);
4324 break;
4325 case Code::KEYED_STORE_IC:
4326 __ IncrementCounter(counters->keyed_store_full(), 1, a1, a2);
4327 default:
4328 break;
4329 }
4330
4331 if (ast_id == kNoASTId) {
4332 __ Call(ic, RelocInfo::CODE_TARGET);
4333 } else {
4334 __ CallWithAstId(ic, RelocInfo::CODE_TARGET_WITH_ID, ast_id);
4335 }
4336 if (patch_site != NULL && patch_site->is_bound()) {
4337 patch_site->EmitPatchInfo();
4338 } else {
4339 __ nop(); // Signals no inlined code.
4340 }
4341 }
4342
4343
4344 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { 4253 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
4345 ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset); 4254 ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset);
4346 __ sw(value, MemOperand(fp, frame_offset)); 4255 __ sw(value, MemOperand(fp, frame_offset));
4347 } 4256 }
4348 4257
4349 4258
4350 void FullCodeGenerator::LoadContextField(Register dst, int context_index) { 4259 void FullCodeGenerator::LoadContextField(Register dst, int context_index) {
4351 __ lw(dst, ContextOperand(cp, context_index)); 4260 __ lw(dst, ContextOperand(cp, context_index));
4352 } 4261 }
4353 4262
4354 4263
4264 void FullCodeGenerator::PushFunctionArgumentForContextAllocation() {
4265 Scope* declaration_scope = scope()->DeclarationScope();
4266 if (declaration_scope->is_global_scope()) {
4267 // Contexts nested in the global context have a canonical empty function
4268 // as their closure, not the anonymous closure containing the global
4269 // code. Pass a smi sentinel and let the runtime look up the empty
4270 // function.
4271 __ li(at, Operand(Smi::FromInt(0)));
4272 } else if (declaration_scope->is_eval_scope()) {
4273 // Contexts created by a call to eval have the same closure as the
4274 // context calling eval, not the anonymous closure containing the eval
4275 // code. Fetch it from the context.
4276 __ lw(at, ContextOperand(cp, Context::CLOSURE_INDEX));
4277 } else {
4278 ASSERT(declaration_scope->is_function_scope());
4279 __ lw(at, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
4280 }
4281 __ push(at);
4282 }
4283
4284
4355 // ---------------------------------------------------------------------------- 4285 // ----------------------------------------------------------------------------
4356 // Non-local control flow support. 4286 // Non-local control flow support.
4357 4287
4358 void FullCodeGenerator::EnterFinallyBlock() { 4288 void FullCodeGenerator::EnterFinallyBlock() {
4359 ASSERT(!result_register().is(a1)); 4289 ASSERT(!result_register().is(a1));
4360 // Store result register while executing finally block. 4290 // Store result register while executing finally block.
4361 __ push(result_register()); 4291 __ push(result_register());
4362 // Cook return address in link register to stack (smi encoded Code* delta). 4292 // Cook return address in link register to stack (smi encoded Code* delta).
4363 __ Subu(a1, ra, Operand(masm_->CodeObject())); 4293 __ Subu(a1, ra, Operand(masm_->CodeObject()));
4364 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); 4294 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize);
(...skipping 14 matching lines...) Expand all
4379 __ Addu(at, a1, Operand(masm_->CodeObject())); 4309 __ Addu(at, a1, Operand(masm_->CodeObject()));
4380 __ Jump(at); 4310 __ Jump(at);
4381 } 4311 }
4382 4312
4383 4313
4384 #undef __ 4314 #undef __
4385 4315
4386 } } // namespace v8::internal 4316 } } // namespace v8::internal
4387 4317
4388 #endif // V8_TARGET_ARCH_MIPS 4318 #endif // V8_TARGET_ARCH_MIPS
OLDNEW
« no previous file with comments | « src/mips/deoptimizer-mips.cc ('k') | src/mips/ic-mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698