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

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

Powered by Google App Engine
This is Rietveld 408576698