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

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

Issue 6529055: [Isolates] Merge crankshaft (r5922 from bleeding_edge). (Closed)
Patch Set: Win32 port Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/arm/frames-arm.cc ('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 2009 the V8 project authors. All rights reserved. 1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution. 11 // with the distribution.
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
164 } 164 }
165 // Visit all the explicit declarations unless there is an illegal 165 // Visit all the explicit declarations unless there is an illegal
166 // redeclaration. 166 // redeclaration.
167 if (scope()->HasIllegalRedeclaration()) { 167 if (scope()->HasIllegalRedeclaration()) {
168 scope()->VisitIllegalRedeclaration(this); 168 scope()->VisitIllegalRedeclaration(this);
169 } else { 169 } else {
170 VisitDeclarations(scope()->declarations()); 170 VisitDeclarations(scope()->declarations());
171 } 171 }
172 } 172 }
173 173
174 // Check the stack for overflow or break request.
175 { Comment cmnt(masm_, "[ Stack check");
176 __ LoadRoot(r2, Heap::kStackLimitRootIndex);
177 __ cmp(sp, Operand(r2));
178 StackCheckStub stub;
179 __ mov(ip,
180 Operand(reinterpret_cast<intptr_t>(stub.GetCode().location()),
181 RelocInfo::CODE_TARGET),
182 LeaveCC,
183 lo);
184 __ Call(ip, lo);
185 }
186
187 if (FLAG_trace) { 174 if (FLAG_trace) {
188 __ CallRuntime(Runtime::kTraceEnter, 0); 175 __ CallRuntime(Runtime::kTraceEnter, 0);
189 } 176 }
190 177
178 // Check the stack for overflow or break request.
179 { Comment cmnt(masm_, "[ Stack check");
180 PrepareForBailout(info->function(), NO_REGISTERS);
181 Label ok;
182 __ LoadRoot(ip, Heap::kStackLimitRootIndex);
183 __ cmp(sp, Operand(ip));
184 __ b(hs, &ok);
185 StackCheckStub stub;
186 __ CallStub(&stub);
187 __ bind(&ok);
188 }
189
191 { Comment cmnt(masm_, "[ Body"); 190 { Comment cmnt(masm_, "[ Body");
192 ASSERT(loop_depth() == 0); 191 ASSERT(loop_depth() == 0);
193 VisitStatements(function()->body()); 192 VisitStatements(function()->body());
194 ASSERT(loop_depth() == 0); 193 ASSERT(loop_depth() == 0);
195 } 194 }
196 195
197 { Comment cmnt(masm_, "[ return <undefined>;"); 196 { Comment cmnt(masm_, "[ return <undefined>;");
198 // Emit a 'return undefined' in case control fell off the end of the 197 // Emit a 'return undefined' in case control fell off the end of the
199 // body. 198 // body.
200 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); 199 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
201 } 200 }
202 EmitReturnSequence(); 201 EmitReturnSequence();
202
203 // Force emit the constant pool, so it doesn't get emitted in the middle
204 // of the stack check table.
205 masm()->CheckConstPool(true, false);
203 } 206 }
204 207
205 208
209 void FullCodeGenerator::EmitStackCheck(IterationStatement* stmt) {
210 Comment cmnt(masm_, "[ Stack check");
211 Label ok;
212 __ LoadRoot(ip, Heap::kStackLimitRootIndex);
213 __ cmp(sp, Operand(ip));
214 __ b(hs, &ok);
215 StackCheckStub stub;
216 __ CallStub(&stub);
217 __ bind(&ok);
218 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
219 PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS);
220 RecordStackCheck(stmt->OsrEntryId());
221 }
222
223
206 void FullCodeGenerator::EmitReturnSequence() { 224 void FullCodeGenerator::EmitReturnSequence() {
207 Comment cmnt(masm_, "[ Return sequence"); 225 Comment cmnt(masm_, "[ Return sequence");
208 if (return_label_.is_bound()) { 226 if (return_label_.is_bound()) {
209 __ b(&return_label_); 227 __ b(&return_label_);
210 } else { 228 } else {
211 __ bind(&return_label_); 229 __ bind(&return_label_);
212 if (FLAG_trace) { 230 if (FLAG_trace) {
213 // Push the return value on the stack as the parameter. 231 // Push the return value on the stack as the parameter.
214 // Runtime::TraceExit returns its parameter in r0. 232 // Runtime::TraceExit returns its parameter in r0.
215 __ push(r0); 233 __ push(r0);
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
268 286
269 void FullCodeGenerator::StackValueContext::Plug(Slot* slot) const { 287 void FullCodeGenerator::StackValueContext::Plug(Slot* slot) const {
270 codegen()->Move(result_register(), slot); 288 codegen()->Move(result_register(), slot);
271 __ push(result_register()); 289 __ push(result_register());
272 } 290 }
273 291
274 292
275 void FullCodeGenerator::TestContext::Plug(Slot* slot) const { 293 void FullCodeGenerator::TestContext::Plug(Slot* slot) const {
276 // For simplicity we always test the accumulator register. 294 // For simplicity we always test the accumulator register.
277 codegen()->Move(result_register(), slot); 295 codegen()->Move(result_register(), slot);
296 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
278 codegen()->DoTest(true_label_, false_label_, fall_through_); 297 codegen()->DoTest(true_label_, false_label_, fall_through_);
279 } 298 }
280 299
281 300
282 void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const { 301 void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const {
283 } 302 }
284 303
285 304
286 void FullCodeGenerator::AccumulatorValueContext::Plug( 305 void FullCodeGenerator::AccumulatorValueContext::Plug(
287 Heap::RootListIndex index) const { 306 Heap::RootListIndex index) const {
288 __ LoadRoot(result_register(), index); 307 __ LoadRoot(result_register(), index);
289 } 308 }
290 309
291 310
292 void FullCodeGenerator::StackValueContext::Plug( 311 void FullCodeGenerator::StackValueContext::Plug(
293 Heap::RootListIndex index) const { 312 Heap::RootListIndex index) const {
294 __ LoadRoot(result_register(), index); 313 __ LoadRoot(result_register(), index);
295 __ push(result_register()); 314 __ push(result_register());
296 } 315 }
297 316
298 317
299 void FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const { 318 void FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const {
319 codegen()->PrepareForBailoutBeforeSplit(TOS_REG,
320 true,
321 true_label_,
322 false_label_);
300 if (index == Heap::kUndefinedValueRootIndex || 323 if (index == Heap::kUndefinedValueRootIndex ||
301 index == Heap::kNullValueRootIndex || 324 index == Heap::kNullValueRootIndex ||
302 index == Heap::kFalseValueRootIndex) { 325 index == Heap::kFalseValueRootIndex) {
303 __ b(false_label_); 326 if (false_label_ != fall_through_) __ b(false_label_);
304 } else if (index == Heap::kTrueValueRootIndex) { 327 } else if (index == Heap::kTrueValueRootIndex) {
305 __ b(true_label_); 328 if (true_label_ != fall_through_) __ b(true_label_);
306 } else { 329 } else {
307 __ LoadRoot(result_register(), index); 330 __ LoadRoot(result_register(), index);
308 codegen()->DoTest(true_label_, false_label_, fall_through_); 331 codegen()->DoTest(true_label_, false_label_, fall_through_);
309 } 332 }
310 } 333 }
311 334
312 335
313 void FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const { 336 void FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const {
314 } 337 }
315 338
316 339
317 void FullCodeGenerator::AccumulatorValueContext::Plug( 340 void FullCodeGenerator::AccumulatorValueContext::Plug(
318 Handle<Object> lit) const { 341 Handle<Object> lit) const {
319 __ mov(result_register(), Operand(lit)); 342 __ mov(result_register(), Operand(lit));
320 } 343 }
321 344
322 345
323 void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const { 346 void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const {
324 // Immediates can be pushed directly. 347 // Immediates cannot be pushed directly.
325 __ mov(result_register(), Operand(lit)); 348 __ mov(result_register(), Operand(lit));
326 __ push(result_register()); 349 __ push(result_register());
327 } 350 }
328 351
329 352
330 void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const { 353 void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const {
354 codegen()->PrepareForBailoutBeforeSplit(TOS_REG,
355 true,
356 true_label_,
357 false_label_);
331 ASSERT(!lit->IsUndetectableObject()); // There are no undetectable literals. 358 ASSERT(!lit->IsUndetectableObject()); // There are no undetectable literals.
332 if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) { 359 if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) {
333 __ b(false_label_); 360 if (false_label_ != fall_through_) __ b(false_label_);
334 } else if (lit->IsTrue() || lit->IsJSObject()) { 361 } else if (lit->IsTrue() || lit->IsJSObject()) {
335 __ b(true_label_); 362 if (true_label_ != fall_through_) __ b(true_label_);
336 } else if (lit->IsString()) { 363 } else if (lit->IsString()) {
337 if (String::cast(*lit)->length() == 0) { 364 if (String::cast(*lit)->length() == 0) {
365 if (false_label_ != fall_through_) __ b(false_label_);
338 __ b(false_label_); 366 __ b(false_label_);
339 } else { 367 } else {
340 __ b(true_label_); 368 if (true_label_ != fall_through_) __ b(true_label_);
341 } 369 }
342 } else if (lit->IsSmi()) { 370 } else if (lit->IsSmi()) {
343 if (Smi::cast(*lit)->value() == 0) { 371 if (Smi::cast(*lit)->value() == 0) {
344 __ b(false_label_); 372 if (false_label_ != fall_through_) __ b(false_label_);
345 } else { 373 } else {
346 __ b(true_label_); 374 if (true_label_ != fall_through_) __ b(true_label_);
347 } 375 }
348 } else { 376 } else {
349 // For simplicity we always test the accumulator register. 377 // For simplicity we always test the accumulator register.
350 __ mov(result_register(), Operand(lit)); 378 __ mov(result_register(), Operand(lit));
351 codegen()->DoTest(true_label_, false_label_, fall_through_); 379 codegen()->DoTest(true_label_, false_label_, fall_through_);
352 } 380 }
353 } 381 }
354 382
355 383
356 void FullCodeGenerator::EffectContext::DropAndPlug(int count, 384 void FullCodeGenerator::EffectContext::DropAndPlug(int count,
(...skipping 19 matching lines...) Expand all
376 __ str(reg, MemOperand(sp, 0)); 404 __ str(reg, MemOperand(sp, 0));
377 } 405 }
378 406
379 407
380 void FullCodeGenerator::TestContext::DropAndPlug(int count, 408 void FullCodeGenerator::TestContext::DropAndPlug(int count,
381 Register reg) const { 409 Register reg) const {
382 ASSERT(count > 0); 410 ASSERT(count > 0);
383 // For simplicity we always test the accumulator register. 411 // For simplicity we always test the accumulator register.
384 __ Drop(count); 412 __ Drop(count);
385 __ Move(result_register(), reg); 413 __ Move(result_register(), reg);
414 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
386 codegen()->DoTest(true_label_, false_label_, fall_through_); 415 codegen()->DoTest(true_label_, false_label_, fall_through_);
387 } 416 }
388 417
389 418
390 void FullCodeGenerator::EffectContext::Plug(Label* materialize_true, 419 void FullCodeGenerator::EffectContext::Plug(Label* materialize_true,
391 Label* materialize_false) const { 420 Label* materialize_false) const {
392 ASSERT_EQ(materialize_true, materialize_false); 421 ASSERT(materialize_true == materialize_false);
393 __ bind(materialize_true); 422 __ bind(materialize_true);
394 } 423 }
395 424
396 425
397 void FullCodeGenerator::AccumulatorValueContext::Plug( 426 void FullCodeGenerator::AccumulatorValueContext::Plug(
398 Label* materialize_true, 427 Label* materialize_true,
399 Label* materialize_false) const { 428 Label* materialize_false) const {
400 Label done; 429 Label done;
401 __ bind(materialize_true); 430 __ bind(materialize_true);
402 __ LoadRoot(result_register(), Heap::kTrueValueRootIndex); 431 __ LoadRoot(result_register(), Heap::kTrueValueRootIndex);
(...skipping 14 matching lines...) Expand all
417 __ jmp(&done); 446 __ jmp(&done);
418 __ bind(materialize_false); 447 __ bind(materialize_false);
419 __ LoadRoot(ip, Heap::kFalseValueRootIndex); 448 __ LoadRoot(ip, Heap::kFalseValueRootIndex);
420 __ push(ip); 449 __ push(ip);
421 __ bind(&done); 450 __ bind(&done);
422 } 451 }
423 452
424 453
425 void FullCodeGenerator::TestContext::Plug(Label* materialize_true, 454 void FullCodeGenerator::TestContext::Plug(Label* materialize_true,
426 Label* materialize_false) const { 455 Label* materialize_false) const {
456 ASSERT(materialize_true == true_label_);
427 ASSERT(materialize_false == false_label_); 457 ASSERT(materialize_false == false_label_);
428 ASSERT(materialize_true == true_label_);
429 } 458 }
430 459
431 460
432 void FullCodeGenerator::EffectContext::Plug(bool flag) const { 461 void FullCodeGenerator::EffectContext::Plug(bool flag) const {
433 } 462 }
434 463
435 464
436 void FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const { 465 void FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const {
437 Heap::RootListIndex value_root_index = 466 Heap::RootListIndex value_root_index =
438 flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; 467 flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
439 __ LoadRoot(result_register(), value_root_index); 468 __ LoadRoot(result_register(), value_root_index);
440 } 469 }
441 470
442 471
443 void FullCodeGenerator::StackValueContext::Plug(bool flag) const { 472 void FullCodeGenerator::StackValueContext::Plug(bool flag) const {
444 Heap::RootListIndex value_root_index = 473 Heap::RootListIndex value_root_index =
445 flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; 474 flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
446 __ LoadRoot(ip, value_root_index); 475 __ LoadRoot(ip, value_root_index);
447 __ push(ip); 476 __ push(ip);
448 } 477 }
449 478
450 479
451 void FullCodeGenerator::TestContext::Plug(bool flag) const { 480 void FullCodeGenerator::TestContext::Plug(bool flag) const {
481 codegen()->PrepareForBailoutBeforeSplit(TOS_REG,
482 true,
483 true_label_,
484 false_label_);
452 if (flag) { 485 if (flag) {
453 if (true_label_ != fall_through_) __ b(true_label_); 486 if (true_label_ != fall_through_) __ b(true_label_);
454 } else { 487 } else {
455 if (false_label_ != fall_through_) __ b(false_label_); 488 if (false_label_ != fall_through_) __ b(false_label_);
456 } 489 }
457 } 490 }
458 491
459 492
460 void FullCodeGenerator::DoTest(Label* if_true, 493 void FullCodeGenerator::DoTest(Label* if_true,
461 Label* if_false, 494 Label* if_false,
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
522 // Emit the write barrier code if the location is in the heap. 555 // Emit the write barrier code if the location is in the heap.
523 if (dst->type() == Slot::CONTEXT) { 556 if (dst->type() == Slot::CONTEXT) {
524 __ RecordWrite(scratch1, 557 __ RecordWrite(scratch1,
525 Operand(Context::SlotOffset(dst->index())), 558 Operand(Context::SlotOffset(dst->index())),
526 scratch2, 559 scratch2,
527 src); 560 src);
528 } 561 }
529 } 562 }
530 563
531 564
565 void FullCodeGenerator::PrepareForBailoutBeforeSplit(State state,
566 bool should_normalize,
567 Label* if_true,
568 Label* if_false) {
569 // Only prepare for bailouts before splits if we're in a test
570 // context. Otherwise, we let the Visit function deal with the
571 // preparation to avoid preparing with the same AST id twice.
572 if (!context()->IsTest() || !info_->IsOptimizable()) return;
573
574 Label skip;
575 if (should_normalize) __ b(&skip);
576
577 ForwardBailoutStack* current = forward_bailout_stack_;
578 while (current != NULL) {
579 PrepareForBailout(current->expr(), state);
580 current = current->parent();
581 }
582
583 if (should_normalize) {
584 __ LoadRoot(ip, Heap::kTrueValueRootIndex);
585 __ cmp(r0, ip);
586 Split(eq, if_true, if_false, NULL);
587 __ bind(&skip);
588 }
589 }
590
591
532 void FullCodeGenerator::EmitDeclaration(Variable* variable, 592 void FullCodeGenerator::EmitDeclaration(Variable* variable,
533 Variable::Mode mode, 593 Variable::Mode mode,
534 FunctionLiteral* function) { 594 FunctionLiteral* function) {
535 Comment cmnt(masm_, "[ Declaration"); 595 Comment cmnt(masm_, "[ Declaration");
536 ASSERT(variable != NULL); // Must have been resolved. 596 ASSERT(variable != NULL); // Must have been resolved.
537 Slot* slot = variable->AsSlot(); 597 Slot* slot = variable->AsSlot();
538 Property* prop = variable->AsProperty(); 598 Property* prop = variable->AsProperty();
539 599
540 if (slot != NULL) { 600 if (slot != NULL) {
541 switch (slot->type()) { 601 switch (slot->type()) {
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
645 } 705 }
646 706
647 707
648 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { 708 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
649 Comment cmnt(masm_, "[ SwitchStatement"); 709 Comment cmnt(masm_, "[ SwitchStatement");
650 Breakable nested_statement(this, stmt); 710 Breakable nested_statement(this, stmt);
651 SetStatementPosition(stmt); 711 SetStatementPosition(stmt);
652 // Keep the switch value on the stack until a case matches. 712 // Keep the switch value on the stack until a case matches.
653 VisitForStackValue(stmt->tag()); 713 VisitForStackValue(stmt->tag());
654 714
715 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
716
655 ZoneList<CaseClause*>* clauses = stmt->cases(); 717 ZoneList<CaseClause*>* clauses = stmt->cases();
656 CaseClause* default_clause = NULL; // Can occur anywhere in the list. 718 CaseClause* default_clause = NULL; // Can occur anywhere in the list.
657 719
658 Label next_test; // Recycled for each test. 720 Label next_test; // Recycled for each test.
659 // Compile all the tests with branches to their bodies. 721 // Compile all the tests with branches to their bodies.
660 for (int i = 0; i < clauses->length(); i++) { 722 for (int i = 0; i < clauses->length(); i++) {
661 CaseClause* clause = clauses->at(i); 723 CaseClause* clause = clauses->at(i);
662 // The default is not a test, but remember it as final fall through. 724 // The default is not a test, but remember it as final fall through.
663 if (clause->is_default()) { 725 if (clause->is_default()) {
664 default_clause = clause; 726 default_clause = clause;
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
710 772
711 // Compile all the case bodies. 773 // Compile all the case bodies.
712 for (int i = 0; i < clauses->length(); i++) { 774 for (int i = 0; i < clauses->length(); i++) {
713 Comment cmnt(masm_, "[ Case body"); 775 Comment cmnt(masm_, "[ Case body");
714 CaseClause* clause = clauses->at(i); 776 CaseClause* clause = clauses->at(i);
715 __ bind(clause->body_target()->entry_label()); 777 __ bind(clause->body_target()->entry_label());
716 VisitStatements(clause->statements()); 778 VisitStatements(clause->statements());
717 } 779 }
718 780
719 __ bind(nested_statement.break_target()); 781 __ bind(nested_statement.break_target());
782 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
720 } 783 }
721 784
722 785
723 void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { 786 void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
724 Comment cmnt(masm_, "[ ForInStatement"); 787 Comment cmnt(masm_, "[ ForInStatement");
725 SetStatementPosition(stmt); 788 SetStatementPosition(stmt);
726 789
727 Label loop, exit; 790 Label loop, exit;
728 ForIn loop_statement(this, stmt); 791 ForIn loop_statement(this, stmt);
729 increment_loop_depth(); 792 increment_loop_depth();
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
824 __ b(eq, loop_statement.continue_target()); 887 __ b(eq, loop_statement.continue_target());
825 888
826 // Update the 'each' property or variable from the possibly filtered 889 // Update the 'each' property or variable from the possibly filtered
827 // entry in register r3. 890 // entry in register r3.
828 __ bind(&update_each); 891 __ bind(&update_each);
829 __ mov(result_register(), r3); 892 __ mov(result_register(), r3);
830 // Perform the assignment as if via '='. 893 // Perform the assignment as if via '='.
831 EmitAssignment(stmt->each()); 894 EmitAssignment(stmt->each());
832 895
833 // Generate code for the body of the loop. 896 // Generate code for the body of the loop.
834 Label stack_limit_hit, stack_check_done;
835 Visit(stmt->body()); 897 Visit(stmt->body());
836 898
837 __ StackLimitCheck(&stack_limit_hit);
838 __ bind(&stack_check_done);
839
840 // Generate code for the going to the next element by incrementing 899 // Generate code for the going to the next element by incrementing
841 // the index (smi) stored on top of the stack. 900 // the index (smi) stored on top of the stack.
842 __ bind(loop_statement.continue_target()); 901 __ bind(loop_statement.continue_target());
843 __ pop(r0); 902 __ pop(r0);
844 __ add(r0, r0, Operand(Smi::FromInt(1))); 903 __ add(r0, r0, Operand(Smi::FromInt(1)));
845 __ push(r0); 904 __ push(r0);
905
906 EmitStackCheck(stmt);
846 __ b(&loop); 907 __ b(&loop);
847 908
848 // Slow case for the stack limit check.
849 StackCheckStub stack_check_stub;
850 __ bind(&stack_limit_hit);
851 __ CallStub(&stack_check_stub);
852 __ b(&stack_check_done);
853
854 // Remove the pointers stored on the stack. 909 // Remove the pointers stored on the stack.
855 __ bind(loop_statement.break_target()); 910 __ bind(loop_statement.break_target());
856 __ Drop(5); 911 __ Drop(5);
857 912
858 // Exit and decrement the loop depth. 913 // Exit and decrement the loop depth.
859 __ bind(&exit); 914 __ bind(&exit);
860 decrement_loop_depth(); 915 decrement_loop_depth();
861 } 916 }
862 917
863 918
(...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after
1193 result_saved = true; 1248 result_saved = true;
1194 } 1249 }
1195 switch (property->kind()) { 1250 switch (property->kind()) {
1196 case ObjectLiteral::Property::CONSTANT: 1251 case ObjectLiteral::Property::CONSTANT:
1197 UNREACHABLE(); 1252 UNREACHABLE();
1198 case ObjectLiteral::Property::MATERIALIZED_LITERAL: 1253 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1199 ASSERT(!CompileTimeValue::IsCompileTimeValue(property->value())); 1254 ASSERT(!CompileTimeValue::IsCompileTimeValue(property->value()));
1200 // Fall through. 1255 // Fall through.
1201 case ObjectLiteral::Property::COMPUTED: 1256 case ObjectLiteral::Property::COMPUTED:
1202 if (key->handle()->IsSymbol()) { 1257 if (key->handle()->IsSymbol()) {
1203 VisitForAccumulatorValue(value);
1204 __ mov(r2, Operand(key->handle()));
1205 __ ldr(r1, MemOperand(sp));
1206 if (property->emit_store()) { 1258 if (property->emit_store()) {
1259 VisitForAccumulatorValue(value);
1260 __ mov(r2, Operand(key->handle()));
1261 __ ldr(r1, MemOperand(sp));
1207 Handle<Code> ic(Isolate::Current()->builtins()->builtin( 1262 Handle<Code> ic(Isolate::Current()->builtins()->builtin(
1208 Builtins::StoreIC_Initialize)); 1263 Builtins::StoreIC_Initialize));
1209 EmitCallIC(ic, RelocInfo::CODE_TARGET); 1264 EmitCallIC(ic, RelocInfo::CODE_TARGET);
1265 PrepareForBailoutForId(key->id(), NO_REGISTERS);
1266 } else {
1267 VisitForEffect(value);
1210 } 1268 }
1211 break; 1269 break;
1212 } 1270 }
1213 // Fall through. 1271 // Fall through.
1214 case ObjectLiteral::Property::PROTOTYPE: 1272 case ObjectLiteral::Property::PROTOTYPE:
1215 // Duplicate receiver on stack. 1273 // Duplicate receiver on stack.
1216 __ ldr(r0, MemOperand(sp)); 1274 __ ldr(r0, MemOperand(sp));
1217 __ push(r0); 1275 __ push(r0);
1218 VisitForStackValue(key); 1276 VisitForStackValue(key);
1219 VisitForStackValue(value); 1277 VisitForStackValue(value);
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
1294 1352
1295 // Store the subexpression value in the array's elements. 1353 // Store the subexpression value in the array's elements.
1296 __ ldr(r1, MemOperand(sp)); // Copy of array literal. 1354 __ ldr(r1, MemOperand(sp)); // Copy of array literal.
1297 __ ldr(r1, FieldMemOperand(r1, JSObject::kElementsOffset)); 1355 __ ldr(r1, FieldMemOperand(r1, JSObject::kElementsOffset));
1298 int offset = FixedArray::kHeaderSize + (i * kPointerSize); 1356 int offset = FixedArray::kHeaderSize + (i * kPointerSize);
1299 __ str(result_register(), FieldMemOperand(r1, offset)); 1357 __ str(result_register(), FieldMemOperand(r1, offset));
1300 1358
1301 // Update the write barrier for the array store with r0 as the scratch 1359 // Update the write barrier for the array store with r0 as the scratch
1302 // register. 1360 // register.
1303 __ RecordWrite(r1, Operand(offset), r2, result_register()); 1361 __ RecordWrite(r1, Operand(offset), r2, result_register());
1362
1363 PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS);
1304 } 1364 }
1305 1365
1306 if (result_saved) { 1366 if (result_saved) {
1307 context()->PlugTOS(); 1367 context()->PlugTOS();
1308 } else { 1368 } else {
1309 context()->Plug(r0); 1369 context()->Plug(r0);
1310 } 1370 }
1311 } 1371 }
1312 1372
1313 1373
(...skipping 26 matching lines...) Expand all
1340 if (expr->is_compound()) { 1400 if (expr->is_compound()) {
1341 // We need the receiver both on the stack and in the accumulator. 1401 // We need the receiver both on the stack and in the accumulator.
1342 VisitForAccumulatorValue(property->obj()); 1402 VisitForAccumulatorValue(property->obj());
1343 __ push(result_register()); 1403 __ push(result_register());
1344 } else { 1404 } else {
1345 VisitForStackValue(property->obj()); 1405 VisitForStackValue(property->obj());
1346 } 1406 }
1347 break; 1407 break;
1348 case KEYED_PROPERTY: 1408 case KEYED_PROPERTY:
1349 if (expr->is_compound()) { 1409 if (expr->is_compound()) {
1350 VisitForStackValue(property->obj()); 1410 if (property->is_arguments_access()) {
1351 VisitForAccumulatorValue(property->key()); 1411 VariableProxy* obj_proxy = property->obj()->AsVariableProxy();
1412 __ ldr(r0, EmitSlotSearch(obj_proxy->var()->AsSlot(), r0));
1413 __ push(r0);
1414 __ mov(r0, Operand(property->key()->AsLiteral()->handle()));
1415 } else {
1416 VisitForStackValue(property->obj());
1417 VisitForAccumulatorValue(property->key());
1418 }
1352 __ ldr(r1, MemOperand(sp, 0)); 1419 __ ldr(r1, MemOperand(sp, 0));
1353 __ push(r0); 1420 __ push(r0);
1354 } else { 1421 } else {
1355 VisitForStackValue(property->obj()); 1422 if (property->is_arguments_access()) {
1356 VisitForStackValue(property->key()); 1423 VariableProxy* obj_proxy = property->obj()->AsVariableProxy();
1424 __ ldr(r1, EmitSlotSearch(obj_proxy->var()->AsSlot(), r0));
1425 __ mov(r0, Operand(property->key()->AsLiteral()->handle()));
1426 __ Push(r1, r0);
1427 } else {
1428 VisitForStackValue(property->obj());
1429 VisitForStackValue(property->key());
1430 }
1357 } 1431 }
1358 break; 1432 break;
1359 } 1433 }
1360 1434
1361 if (expr->is_compound()) { 1435 if (expr->is_compound()) {
1362 { AccumulatorValueContext context(this); 1436 { AccumulatorValueContext context(this);
1363 switch (assign_type) { 1437 switch (assign_type) {
1364 case VARIABLE: 1438 case VARIABLE:
1365 EmitVariableLoad(expr->target()->AsVariableProxy()->var()); 1439 EmitVariableLoad(expr->target()->AsVariableProxy()->var());
1366 break; 1440 break;
1367 case NAMED_PROPERTY: 1441 case NAMED_PROPERTY:
1368 EmitNamedPropertyLoad(property); 1442 EmitNamedPropertyLoad(property);
1369 break; 1443 break;
1370 case KEYED_PROPERTY: 1444 case KEYED_PROPERTY:
1371 EmitKeyedPropertyLoad(property); 1445 EmitKeyedPropertyLoad(property);
1372 break; 1446 break;
1373 } 1447 }
1374 } 1448 }
1375 1449
1450 // For property compound assignments we need another deoptimization
1451 // point after the property load.
1452 if (property != NULL) {
1453 PrepareForBailoutForId(expr->compound_bailout_id(), TOS_REG);
1454 }
1455
1376 Token::Value op = expr->binary_op(); 1456 Token::Value op = expr->binary_op();
1377 ConstantOperand constant = ShouldInlineSmiCase(op) 1457 ConstantOperand constant = ShouldInlineSmiCase(op)
1378 ? GetConstantOperand(op, expr->target(), expr->value()) 1458 ? GetConstantOperand(op, expr->target(), expr->value())
1379 : kNoConstants; 1459 : kNoConstants;
1380 ASSERT(constant == kRightConstant || constant == kNoConstants); 1460 ASSERT(constant == kRightConstant || constant == kNoConstants);
1381 if (constant == kNoConstants) { 1461 if (constant == kNoConstants) {
1382 __ push(r0); // Left operand goes on the stack. 1462 __ push(r0); // Left operand goes on the stack.
1383 VisitForAccumulatorValue(expr->value()); 1463 VisitForAccumulatorValue(expr->value());
1384 } 1464 }
1385 1465
1386 OverwriteMode mode = expr->value()->ResultOverwriteAllowed() 1466 OverwriteMode mode = expr->value()->ResultOverwriteAllowed()
1387 ? OVERWRITE_RIGHT 1467 ? OVERWRITE_RIGHT
1388 : NO_OVERWRITE; 1468 : NO_OVERWRITE;
1389 SetSourcePosition(expr->position() + 1); 1469 SetSourcePosition(expr->position() + 1);
1390 AccumulatorValueContext context(this); 1470 AccumulatorValueContext context(this);
1391 if (ShouldInlineSmiCase(op)) { 1471 if (ShouldInlineSmiCase(op)) {
1392 EmitInlineSmiBinaryOp(expr, 1472 EmitInlineSmiBinaryOp(expr,
1393 op, 1473 op,
1394 mode, 1474 mode,
1395 expr->target(), 1475 expr->target(),
1396 expr->value(), 1476 expr->value(),
1397 constant); 1477 constant);
1398 } else { 1478 } else {
1399 EmitBinaryOp(op, mode); 1479 EmitBinaryOp(op, mode);
1400 } 1480 }
1481
1482 // Deoptimization point in case the binary operation may have side effects.
1483 PrepareForBailout(expr->binary_operation(), TOS_REG);
1401 } else { 1484 } else {
1402 VisitForAccumulatorValue(expr->value()); 1485 VisitForAccumulatorValue(expr->value());
1403 } 1486 }
1404 1487
1405 // Record source position before possible IC call. 1488 // Record source position before possible IC call.
1406 SetSourcePosition(expr->position()); 1489 SetSourcePosition(expr->position());
1407 1490
1408 // Store the value. 1491 // Store the value.
1409 switch (assign_type) { 1492 switch (assign_type) {
1410 case VARIABLE: 1493 case VARIABLE:
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after
1682 } 1765 }
1683 1766
1684 1767
1685 void FullCodeGenerator::VisitProperty(Property* expr) { 1768 void FullCodeGenerator::VisitProperty(Property* expr) {
1686 Comment cmnt(masm_, "[ Property"); 1769 Comment cmnt(masm_, "[ Property");
1687 Expression* key = expr->key(); 1770 Expression* key = expr->key();
1688 1771
1689 if (key->IsPropertyName()) { 1772 if (key->IsPropertyName()) {
1690 VisitForAccumulatorValue(expr->obj()); 1773 VisitForAccumulatorValue(expr->obj());
1691 EmitNamedPropertyLoad(expr); 1774 EmitNamedPropertyLoad(expr);
1775 context()->Plug(r0);
1692 } else { 1776 } else {
1693 VisitForStackValue(expr->obj()); 1777 VisitForStackValue(expr->obj());
1694 VisitForAccumulatorValue(expr->key()); 1778 VisitForAccumulatorValue(expr->key());
1695 __ pop(r1); 1779 __ pop(r1);
1696 EmitKeyedPropertyLoad(expr); 1780 EmitKeyedPropertyLoad(expr);
1781 context()->Plug(r0);
1697 } 1782 }
1698 context()->Plug(r0);
1699 } 1783 }
1700 1784
1701 void FullCodeGenerator::EmitCallWithIC(Call* expr, 1785 void FullCodeGenerator::EmitCallWithIC(Call* expr,
1702 Handle<Object> name, 1786 Handle<Object> name,
1703 RelocInfo::Mode mode) { 1787 RelocInfo::Mode mode) {
1704 // Code common for calls using the IC. 1788 // Code common for calls using the IC.
1705 ZoneList<Expression*>* args = expr->arguments(); 1789 ZoneList<Expression*>* args = expr->arguments();
1706 int arg_count = args->length(); 1790 int arg_count = args->length();
1707 { PreservePositionScope scope(masm()->positions_recorder()); 1791 { PreservePositionScope scope(masm()->positions_recorder());
1708 for (int i = 0; i < arg_count; i++) { 1792 for (int i = 0; i < arg_count; i++) {
1709 VisitForStackValue(args->at(i)); 1793 VisitForStackValue(args->at(i));
1710 } 1794 }
1711 __ mov(r2, Operand(name)); 1795 __ mov(r2, Operand(name));
1712 } 1796 }
1713 // Record source position for debugger. 1797 // Record source position for debugger.
1714 SetSourcePosition(expr->position()); 1798 SetSourcePosition(expr->position());
1715 // Call the IC initialization code. 1799 // Call the IC initialization code.
1716 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 1800 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
1717 Handle<Code> ic = 1801 Handle<Code> ic =
1718 ISOLATE->stub_cache()->ComputeCallInitialize(arg_count, in_loop); 1802 ISOLATE->stub_cache()->ComputeCallInitialize(arg_count, in_loop);
1719 EmitCallIC(ic, mode); 1803 EmitCallIC(ic, mode);
1804 RecordJSReturnSite(expr);
1720 // Restore context register. 1805 // Restore context register.
1721 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 1806 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
1722 context()->Plug(r0); 1807 context()->Plug(r0);
1723 } 1808 }
1724 1809
1725 1810
1726 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, 1811 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr,
1727 Expression* key, 1812 Expression* key,
1728 RelocInfo::Mode mode) { 1813 RelocInfo::Mode mode) {
1729 // Load the key. 1814 // Load the key.
(...skipping 14 matching lines...) Expand all
1744 } 1829 }
1745 } 1830 }
1746 // Record source position for debugger. 1831 // Record source position for debugger.
1747 SetSourcePosition(expr->position()); 1832 SetSourcePosition(expr->position());
1748 // Call the IC initialization code. 1833 // Call the IC initialization code.
1749 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 1834 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
1750 Handle<Code> ic = 1835 Handle<Code> ic =
1751 ISOLATE->stub_cache()->ComputeKeyedCallInitialize(arg_count, in_loop); 1836 ISOLATE->stub_cache()->ComputeKeyedCallInitialize(arg_count, in_loop);
1752 __ ldr(r2, MemOperand(sp, (arg_count + 1) * kPointerSize)); // Key. 1837 __ ldr(r2, MemOperand(sp, (arg_count + 1) * kPointerSize)); // Key.
1753 EmitCallIC(ic, mode); 1838 EmitCallIC(ic, mode);
1839 RecordJSReturnSite(expr);
1754 // Restore context register. 1840 // Restore context register.
1755 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 1841 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
1756 context()->DropAndPlug(1, r0); // Drop the key still on the stack. 1842 context()->DropAndPlug(1, r0); // Drop the key still on the stack.
1757 } 1843 }
1758 1844
1759 1845
1760 void FullCodeGenerator::EmitCallWithStub(Call* expr) { 1846 void FullCodeGenerator::EmitCallWithStub(Call* expr) {
1761 // Code common for calls using the call stub. 1847 // Code common for calls using the call stub.
1762 ZoneList<Expression*>* args = expr->arguments(); 1848 ZoneList<Expression*>* args = expr->arguments();
1763 int arg_count = args->length(); 1849 int arg_count = args->length();
1764 { PreservePositionScope scope(masm()->positions_recorder()); 1850 { PreservePositionScope scope(masm()->positions_recorder());
1765 for (int i = 0; i < arg_count; i++) { 1851 for (int i = 0; i < arg_count; i++) {
1766 VisitForStackValue(args->at(i)); 1852 VisitForStackValue(args->at(i));
1767 } 1853 }
1768 } 1854 }
1769 // Record source position for debugger. 1855 // Record source position for debugger.
1770 SetSourcePosition(expr->position()); 1856 SetSourcePosition(expr->position());
1771 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 1857 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
1772 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); 1858 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE);
1773 __ CallStub(&stub); 1859 __ CallStub(&stub);
1860 RecordJSReturnSite(expr);
1774 // Restore context register. 1861 // Restore context register.
1775 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 1862 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
1776 context()->DropAndPlug(1, r0); 1863 context()->DropAndPlug(1, r0);
1777 } 1864 }
1778 1865
1779 1866
1780 void FullCodeGenerator::VisitCall(Call* expr) { 1867 void FullCodeGenerator::VisitCall(Call* expr) {
1868 #ifdef DEBUG
1869 // We want to verify that RecordJSReturnSite gets called on all paths
1870 // through this function. Avoid early returns.
1871 expr->return_is_recorded_ = false;
1872 #endif
1873
1781 Comment cmnt(masm_, "[ Call"); 1874 Comment cmnt(masm_, "[ Call");
1782 Expression* fun = expr->expression(); 1875 Expression* fun = expr->expression();
1783 Variable* var = fun->AsVariableProxy()->AsVariable(); 1876 Variable* var = fun->AsVariableProxy()->AsVariable();
1784 1877
1785 if (var != NULL && var->is_possibly_eval()) { 1878 if (var != NULL && var->is_possibly_eval()) {
1786 // In a call to eval, we first call %ResolvePossiblyDirectEval to 1879 // In a call to eval, we first call %ResolvePossiblyDirectEval to
1787 // resolve the function we need to call and the receiver of the 1880 // resolve the function we need to call and the receiver of the
1788 // call. Then we call the resolved function using the given 1881 // call. Then we call the resolved function using the given
1789 // arguments. 1882 // arguments.
1790 ZoneList<Expression*>* args = expr->arguments(); 1883 ZoneList<Expression*>* args = expr->arguments();
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1822 // r1 (receiver). Touch up the stack with the right values. 1915 // r1 (receiver). Touch up the stack with the right values.
1823 __ str(r0, MemOperand(sp, (arg_count + 1) * kPointerSize)); 1916 __ str(r0, MemOperand(sp, (arg_count + 1) * kPointerSize));
1824 __ str(r1, MemOperand(sp, arg_count * kPointerSize)); 1917 __ str(r1, MemOperand(sp, arg_count * kPointerSize));
1825 } 1918 }
1826 1919
1827 // Record source position for debugger. 1920 // Record source position for debugger.
1828 SetSourcePosition(expr->position()); 1921 SetSourcePosition(expr->position());
1829 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 1922 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
1830 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); 1923 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE);
1831 __ CallStub(&stub); 1924 __ CallStub(&stub);
1925 RecordJSReturnSite(expr);
1832 // Restore context register. 1926 // Restore context register.
1833 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 1927 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
1834 context()->DropAndPlug(1, r0); 1928 context()->DropAndPlug(1, r0);
1835 } else if (var != NULL && !var->is_this() && var->is_global()) { 1929 } else if (var != NULL && !var->is_this() && var->is_global()) {
1836 // Push global object as receiver for the call IC. 1930 // Push global object as receiver for the call IC.
1837 __ ldr(r0, GlobalObjectOperand()); 1931 __ ldr(r0, GlobalObjectOperand());
1838 __ push(r0); 1932 __ push(r0);
1839 EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); 1933 EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT);
1840 } else if (var != NULL && var->AsSlot() != NULL && 1934 } else if (var != NULL && var->AsSlot() != NULL &&
1841 var->AsSlot()->type() == Slot::LOOKUP) { 1935 var->AsSlot()->type() == Slot::LOOKUP) {
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
1927 { PreservePositionScope scope(masm()->positions_recorder()); 2021 { PreservePositionScope scope(masm()->positions_recorder());
1928 VisitForStackValue(fun); 2022 VisitForStackValue(fun);
1929 } 2023 }
1930 // Load global receiver object. 2024 // Load global receiver object.
1931 __ ldr(r1, GlobalObjectOperand()); 2025 __ ldr(r1, GlobalObjectOperand());
1932 __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); 2026 __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
1933 __ push(r1); 2027 __ push(r1);
1934 // Emit function call. 2028 // Emit function call.
1935 EmitCallWithStub(expr); 2029 EmitCallWithStub(expr);
1936 } 2030 }
2031
2032 #ifdef DEBUG
2033 // RecordJSReturnSite should have been called.
2034 ASSERT(expr->return_is_recorded_);
2035 #endif
1937 } 2036 }
1938 2037
1939 2038
1940 void FullCodeGenerator::VisitCallNew(CallNew* expr) { 2039 void FullCodeGenerator::VisitCallNew(CallNew* expr) {
1941 Comment cmnt(masm_, "[ CallNew"); 2040 Comment cmnt(masm_, "[ CallNew");
1942 // According to ECMA-262, section 11.2.2, page 44, the function 2041 // According to ECMA-262, section 11.2.2, page 44, the function
1943 // expression in new calls must be evaluated before the 2042 // expression in new calls must be evaluated before the
1944 // arguments. 2043 // arguments.
1945 2044
1946 // Push constructor on the stack. If it's not a function it's used as 2045 // Push constructor on the stack. If it's not a function it's used as
(...skipping 28 matching lines...) Expand all
1975 2074
1976 VisitForAccumulatorValue(args->at(0)); 2075 VisitForAccumulatorValue(args->at(0));
1977 2076
1978 Label materialize_true, materialize_false; 2077 Label materialize_true, materialize_false;
1979 Label* if_true = NULL; 2078 Label* if_true = NULL;
1980 Label* if_false = NULL; 2079 Label* if_false = NULL;
1981 Label* fall_through = NULL; 2080 Label* fall_through = NULL;
1982 context()->PrepareTest(&materialize_true, &materialize_false, 2081 context()->PrepareTest(&materialize_true, &materialize_false,
1983 &if_true, &if_false, &fall_through); 2082 &if_true, &if_false, &fall_through);
1984 2083
1985 __ BranchOnSmi(r0, if_true); 2084 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
1986 __ b(if_false); 2085 __ tst(r0, Operand(kSmiTagMask));
2086 Split(eq, if_true, if_false, fall_through);
1987 2087
1988 context()->Plug(if_true, if_false); 2088 context()->Plug(if_true, if_false);
1989 } 2089 }
1990 2090
1991 2091
1992 void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) { 2092 void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) {
1993 ASSERT(args->length() == 1); 2093 ASSERT(args->length() == 1);
1994 2094
1995 VisitForAccumulatorValue(args->at(0)); 2095 VisitForAccumulatorValue(args->at(0));
1996 2096
1997 Label materialize_true, materialize_false; 2097 Label materialize_true, materialize_false;
1998 Label* if_true = NULL; 2098 Label* if_true = NULL;
1999 Label* if_false = NULL; 2099 Label* if_false = NULL;
2000 Label* fall_through = NULL; 2100 Label* fall_through = NULL;
2001 context()->PrepareTest(&materialize_true, &materialize_false, 2101 context()->PrepareTest(&materialize_true, &materialize_false,
2002 &if_true, &if_false, &fall_through); 2102 &if_true, &if_false, &fall_through);
2003 2103
2104 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2004 __ tst(r0, Operand(kSmiTagMask | 0x80000000)); 2105 __ tst(r0, Operand(kSmiTagMask | 0x80000000));
2005 Split(eq, if_true, if_false, fall_through); 2106 Split(eq, if_true, if_false, fall_through);
2006 2107
2007 context()->Plug(if_true, if_false); 2108 context()->Plug(if_true, if_false);
2008 } 2109 }
2009 2110
2010 2111
2011 void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) { 2112 void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) {
2012 ASSERT(args->length() == 1); 2113 ASSERT(args->length() == 1);
2013 2114
(...skipping 12 matching lines...) Expand all
2026 __ b(eq, if_true); 2127 __ b(eq, if_true);
2027 __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); 2128 __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset));
2028 // Undetectable objects behave like undefined when tested with typeof. 2129 // Undetectable objects behave like undefined when tested with typeof.
2029 __ ldrb(r1, FieldMemOperand(r2, Map::kBitFieldOffset)); 2130 __ ldrb(r1, FieldMemOperand(r2, Map::kBitFieldOffset));
2030 __ tst(r1, Operand(1 << Map::kIsUndetectable)); 2131 __ tst(r1, Operand(1 << Map::kIsUndetectable));
2031 __ b(ne, if_false); 2132 __ b(ne, if_false);
2032 __ ldrb(r1, FieldMemOperand(r2, Map::kInstanceTypeOffset)); 2133 __ ldrb(r1, FieldMemOperand(r2, Map::kInstanceTypeOffset));
2033 __ cmp(r1, Operand(FIRST_JS_OBJECT_TYPE)); 2134 __ cmp(r1, Operand(FIRST_JS_OBJECT_TYPE));
2034 __ b(lt, if_false); 2135 __ b(lt, if_false);
2035 __ cmp(r1, Operand(LAST_JS_OBJECT_TYPE)); 2136 __ cmp(r1, Operand(LAST_JS_OBJECT_TYPE));
2137 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2036 Split(le, if_true, if_false, fall_through); 2138 Split(le, if_true, if_false, fall_through);
2037 2139
2038 context()->Plug(if_true, if_false); 2140 context()->Plug(if_true, if_false);
2039 } 2141 }
2040 2142
2041 2143
2042 void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) { 2144 void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) {
2043 ASSERT(args->length() == 1); 2145 ASSERT(args->length() == 1);
2044 2146
2045 VisitForAccumulatorValue(args->at(0)); 2147 VisitForAccumulatorValue(args->at(0));
2046 2148
2047 Label materialize_true, materialize_false; 2149 Label materialize_true, materialize_false;
2048 Label* if_true = NULL; 2150 Label* if_true = NULL;
2049 Label* if_false = NULL; 2151 Label* if_false = NULL;
2050 Label* fall_through = NULL; 2152 Label* fall_through = NULL;
2051 context()->PrepareTest(&materialize_true, &materialize_false, 2153 context()->PrepareTest(&materialize_true, &materialize_false,
2052 &if_true, &if_false, &fall_through); 2154 &if_true, &if_false, &fall_through);
2053 2155
2054 __ BranchOnSmi(r0, if_false); 2156 __ BranchOnSmi(r0, if_false);
2055 __ CompareObjectType(r0, r1, r1, FIRST_JS_OBJECT_TYPE); 2157 __ CompareObjectType(r0, r1, r1, FIRST_JS_OBJECT_TYPE);
2158 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2056 Split(ge, if_true, if_false, fall_through); 2159 Split(ge, if_true, if_false, fall_through);
2057 2160
2058 context()->Plug(if_true, if_false); 2161 context()->Plug(if_true, if_false);
2059 } 2162 }
2060 2163
2061 2164
2062 void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) { 2165 void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) {
2063 ASSERT(args->length() == 1); 2166 ASSERT(args->length() == 1);
2064 2167
2065 VisitForAccumulatorValue(args->at(0)); 2168 VisitForAccumulatorValue(args->at(0));
2066 2169
2067 Label materialize_true, materialize_false; 2170 Label materialize_true, materialize_false;
2068 Label* if_true = NULL; 2171 Label* if_true = NULL;
2069 Label* if_false = NULL; 2172 Label* if_false = NULL;
2070 Label* fall_through = NULL; 2173 Label* fall_through = NULL;
2071 context()->PrepareTest(&materialize_true, &materialize_false, 2174 context()->PrepareTest(&materialize_true, &materialize_false,
2072 &if_true, &if_false, &fall_through); 2175 &if_true, &if_false, &fall_through);
2073 2176
2074 __ BranchOnSmi(r0, if_false); 2177 __ BranchOnSmi(r0, if_false);
2075 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); 2178 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
2076 __ ldrb(r1, FieldMemOperand(r1, Map::kBitFieldOffset)); 2179 __ ldrb(r1, FieldMemOperand(r1, Map::kBitFieldOffset));
2077 __ tst(r1, Operand(1 << Map::kIsUndetectable)); 2180 __ tst(r1, Operand(1 << Map::kIsUndetectable));
2181 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2078 Split(ne, if_true, if_false, fall_through); 2182 Split(ne, if_true, if_false, fall_through);
2079 2183
2080 context()->Plug(if_true, if_false); 2184 context()->Plug(if_true, if_false);
2081 } 2185 }
2082 2186
2083 2187
2084 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( 2188 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
2085 ZoneList<Expression*>* args) { 2189 ZoneList<Expression*>* args) {
2086 2190
2087 ASSERT(args->length() == 1); 2191 ASSERT(args->length() == 1);
2088 2192
2089 VisitForAccumulatorValue(args->at(0)); 2193 VisitForAccumulatorValue(args->at(0));
2090 2194
2091 Label materialize_true, materialize_false; 2195 Label materialize_true, materialize_false;
2092 Label* if_true = NULL; 2196 Label* if_true = NULL;
2093 Label* if_false = NULL; 2197 Label* if_false = NULL;
2094 Label* fall_through = NULL; 2198 Label* fall_through = NULL;
2095 context()->PrepareTest(&materialize_true, &materialize_false, 2199 context()->PrepareTest(&materialize_true, &materialize_false,
2096 &if_true, &if_false, &fall_through); 2200 &if_true, &if_false, &fall_through);
2097 2201
2098 // Just indicate false, as %_IsStringWrapperSafeForDefaultValueOf() is only 2202 // Just indicate false, as %_IsStringWrapperSafeForDefaultValueOf() is only
2099 // used in a few functions in runtime.js which should not normally be hit by 2203 // used in a few functions in runtime.js which should not normally be hit by
2100 // this compiler. 2204 // this compiler.
2205 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2101 __ jmp(if_false); 2206 __ jmp(if_false);
2102 context()->Plug(if_true, if_false); 2207 context()->Plug(if_true, if_false);
2103 } 2208 }
2104 2209
2105 2210
2106 void FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) { 2211 void FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) {
2107 ASSERT(args->length() == 1); 2212 ASSERT(args->length() == 1);
2108 2213
2109 VisitForAccumulatorValue(args->at(0)); 2214 VisitForAccumulatorValue(args->at(0));
2110 2215
2111 Label materialize_true, materialize_false; 2216 Label materialize_true, materialize_false;
2112 Label* if_true = NULL; 2217 Label* if_true = NULL;
2113 Label* if_false = NULL; 2218 Label* if_false = NULL;
2114 Label* fall_through = NULL; 2219 Label* fall_through = NULL;
2115 context()->PrepareTest(&materialize_true, &materialize_false, 2220 context()->PrepareTest(&materialize_true, &materialize_false,
2116 &if_true, &if_false, &fall_through); 2221 &if_true, &if_false, &fall_through);
2117 2222
2118 __ BranchOnSmi(r0, if_false); 2223 __ BranchOnSmi(r0, if_false);
2119 __ CompareObjectType(r0, r1, r1, JS_FUNCTION_TYPE); 2224 __ CompareObjectType(r0, r1, r1, JS_FUNCTION_TYPE);
2225 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2120 Split(eq, if_true, if_false, fall_through); 2226 Split(eq, if_true, if_false, fall_through);
2121 2227
2122 context()->Plug(if_true, if_false); 2228 context()->Plug(if_true, if_false);
2123 } 2229 }
2124 2230
2125 2231
2126 void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) { 2232 void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) {
2127 ASSERT(args->length() == 1); 2233 ASSERT(args->length() == 1);
2128 2234
2129 VisitForAccumulatorValue(args->at(0)); 2235 VisitForAccumulatorValue(args->at(0));
2130 2236
2131 Label materialize_true, materialize_false; 2237 Label materialize_true, materialize_false;
2132 Label* if_true = NULL; 2238 Label* if_true = NULL;
2133 Label* if_false = NULL; 2239 Label* if_false = NULL;
2134 Label* fall_through = NULL; 2240 Label* fall_through = NULL;
2135 context()->PrepareTest(&materialize_true, &materialize_false, 2241 context()->PrepareTest(&materialize_true, &materialize_false,
2136 &if_true, &if_false, &fall_through); 2242 &if_true, &if_false, &fall_through);
2137 2243
2138 __ BranchOnSmi(r0, if_false); 2244 __ BranchOnSmi(r0, if_false);
2139 __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE); 2245 __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE);
2246 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2140 Split(eq, if_true, if_false, fall_through); 2247 Split(eq, if_true, if_false, fall_through);
2141 2248
2142 context()->Plug(if_true, if_false); 2249 context()->Plug(if_true, if_false);
2143 } 2250 }
2144 2251
2145 2252
2146 void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) { 2253 void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) {
2147 ASSERT(args->length() == 1); 2254 ASSERT(args->length() == 1);
2148 2255
2149 VisitForAccumulatorValue(args->at(0)); 2256 VisitForAccumulatorValue(args->at(0));
2150 2257
2151 Label materialize_true, materialize_false; 2258 Label materialize_true, materialize_false;
2152 Label* if_true = NULL; 2259 Label* if_true = NULL;
2153 Label* if_false = NULL; 2260 Label* if_false = NULL;
2154 Label* fall_through = NULL; 2261 Label* fall_through = NULL;
2155 context()->PrepareTest(&materialize_true, &materialize_false, 2262 context()->PrepareTest(&materialize_true, &materialize_false,
2156 &if_true, &if_false, &fall_through); 2263 &if_true, &if_false, &fall_through);
2157 2264
2158 __ BranchOnSmi(r0, if_false); 2265 __ BranchOnSmi(r0, if_false);
2159 __ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE); 2266 __ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE);
2267 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2160 Split(eq, if_true, if_false, fall_through); 2268 Split(eq, if_true, if_false, fall_through);
2161 2269
2162 context()->Plug(if_true, if_false); 2270 context()->Plug(if_true, if_false);
2163 } 2271 }
2164 2272
2165 2273
2166 2274
2167 void FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) { 2275 void FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) {
2168 ASSERT(args->length() == 0); 2276 ASSERT(args->length() == 0);
2169 2277
(...skipping 11 matching lines...) Expand all
2181 Label check_frame_marker; 2289 Label check_frame_marker;
2182 __ ldr(r1, MemOperand(r2, StandardFrameConstants::kContextOffset)); 2290 __ ldr(r1, MemOperand(r2, StandardFrameConstants::kContextOffset));
2183 __ cmp(r1, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 2291 __ cmp(r1, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
2184 __ b(ne, &check_frame_marker); 2292 __ b(ne, &check_frame_marker);
2185 __ ldr(r2, MemOperand(r2, StandardFrameConstants::kCallerFPOffset)); 2293 __ ldr(r2, MemOperand(r2, StandardFrameConstants::kCallerFPOffset));
2186 2294
2187 // Check the marker in the calling frame. 2295 // Check the marker in the calling frame.
2188 __ bind(&check_frame_marker); 2296 __ bind(&check_frame_marker);
2189 __ ldr(r1, MemOperand(r2, StandardFrameConstants::kMarkerOffset)); 2297 __ ldr(r1, MemOperand(r2, StandardFrameConstants::kMarkerOffset));
2190 __ cmp(r1, Operand(Smi::FromInt(StackFrame::CONSTRUCT))); 2298 __ cmp(r1, Operand(Smi::FromInt(StackFrame::CONSTRUCT)));
2299 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2191 Split(eq, if_true, if_false, fall_through); 2300 Split(eq, if_true, if_false, fall_through);
2192 2301
2193 context()->Plug(if_true, if_false); 2302 context()->Plug(if_true, if_false);
2194 } 2303 }
2195 2304
2196 2305
2197 void FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) { 2306 void FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) {
2198 ASSERT(args->length() == 2); 2307 ASSERT(args->length() == 2);
2199 2308
2200 // Load the two objects into registers and perform the comparison. 2309 // Load the two objects into registers and perform the comparison.
2201 VisitForStackValue(args->at(0)); 2310 VisitForStackValue(args->at(0));
2202 VisitForAccumulatorValue(args->at(1)); 2311 VisitForAccumulatorValue(args->at(1));
2203 2312
2204 Label materialize_true, materialize_false; 2313 Label materialize_true, materialize_false;
2205 Label* if_true = NULL; 2314 Label* if_true = NULL;
2206 Label* if_false = NULL; 2315 Label* if_false = NULL;
2207 Label* fall_through = NULL; 2316 Label* fall_through = NULL;
2208 context()->PrepareTest(&materialize_true, &materialize_false, 2317 context()->PrepareTest(&materialize_true, &materialize_false,
2209 &if_true, &if_false, &fall_through); 2318 &if_true, &if_false, &fall_through);
2210 2319
2211 __ pop(r1); 2320 __ pop(r1);
2212 __ cmp(r0, r1); 2321 __ cmp(r0, r1);
2322 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2213 Split(eq, if_true, if_false, fall_through); 2323 Split(eq, if_true, if_false, fall_through);
2214 2324
2215 context()->Plug(if_true, if_false); 2325 context()->Plug(if_true, if_false);
2216 } 2326 }
2217 2327
2218 2328
2219 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) { 2329 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) {
2220 ASSERT(args->length() == 1); 2330 ASSERT(args->length() == 1);
2221 2331
2222 // ArgumentsAccessStub expects the key in edx and the formal 2332 // ArgumentsAccessStub expects the key in edx and the formal
(...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after
2656 // InvokeFunction requires function in r1. Move it in there. 2766 // InvokeFunction requires function in r1. Move it in there.
2657 if (!result_register().is(r1)) __ mov(r1, result_register()); 2767 if (!result_register().is(r1)) __ mov(r1, result_register());
2658 ParameterCount count(arg_count); 2768 ParameterCount count(arg_count);
2659 __ InvokeFunction(r1, count, CALL_FUNCTION); 2769 __ InvokeFunction(r1, count, CALL_FUNCTION);
2660 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 2770 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
2661 context()->Plug(r0); 2771 context()->Plug(r0);
2662 } 2772 }
2663 2773
2664 2774
2665 void FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) { 2775 void FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) {
2776 RegExpConstructResultStub stub;
2666 ASSERT(args->length() == 3); 2777 ASSERT(args->length() == 3);
2667 VisitForStackValue(args->at(0)); 2778 VisitForStackValue(args->at(0));
2668 VisitForStackValue(args->at(1)); 2779 VisitForStackValue(args->at(1));
2669 VisitForStackValue(args->at(2)); 2780 VisitForStackValue(args->at(2));
2670 __ CallRuntime(Runtime::kRegExpConstructResult, 3); 2781 __ CallStub(&stub);
2671 context()->Plug(r0); 2782 context()->Plug(r0);
2672 } 2783 }
2673 2784
2674 2785
2675 void FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) { 2786 void FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) {
2676 ASSERT(args->length() == 3); 2787 ASSERT(args->length() == 3);
2677 VisitForStackValue(args->at(0)); 2788 VisitForStackValue(args->at(0));
2678 VisitForStackValue(args->at(1)); 2789 VisitForStackValue(args->at(1));
2679 VisitForStackValue(args->at(2)); 2790 VisitForStackValue(args->at(2));
2680 __ CallRuntime(Runtime::kSwapElements, 3); 2791 __ CallRuntime(Runtime::kSwapElements, 3);
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
2779 2890
2780 Label materialize_true, materialize_false; 2891 Label materialize_true, materialize_false;
2781 Label* if_true = NULL; 2892 Label* if_true = NULL;
2782 Label* if_false = NULL; 2893 Label* if_false = NULL;
2783 Label* fall_through = NULL; 2894 Label* fall_through = NULL;
2784 context()->PrepareTest(&materialize_true, &materialize_false, 2895 context()->PrepareTest(&materialize_true, &materialize_false,
2785 &if_true, &if_false, &fall_through); 2896 &if_true, &if_false, &fall_through);
2786 2897
2787 __ ldr(r0, FieldMemOperand(r0, String::kHashFieldOffset)); 2898 __ ldr(r0, FieldMemOperand(r0, String::kHashFieldOffset));
2788 __ tst(r0, Operand(String::kContainsCachedArrayIndexMask)); 2899 __ tst(r0, Operand(String::kContainsCachedArrayIndexMask));
2789 2900 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2790 __ b(eq, if_true); 2901 Split(eq, if_true, if_false, fall_through);
2791 __ b(if_false);
2792 2902
2793 context()->Plug(if_true, if_false); 2903 context()->Plug(if_true, if_false);
2794 } 2904 }
2795 2905
2796 2906
2797 void FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList<Expression*>* args) { 2907 void FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList<Expression*>* args) {
2798 ASSERT(args->length() == 1); 2908 ASSERT(args->length() == 1);
2799 VisitForAccumulatorValue(args->at(0)); 2909 VisitForAccumulatorValue(args->at(0));
2800 __ ldr(r0, FieldMemOperand(r0, String::kHashFieldOffset)); 2910 __ ldr(r0, FieldMemOperand(r0, String::kHashFieldOffset));
2801 __ IndexFromHash(r0, r0); 2911 __ IndexFromHash(r0, r0);
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
2905 case Token::NOT: { 3015 case Token::NOT: {
2906 Comment cmnt(masm_, "[ UnaryOperation (NOT)"); 3016 Comment cmnt(masm_, "[ UnaryOperation (NOT)");
2907 Label materialize_true, materialize_false; 3017 Label materialize_true, materialize_false;
2908 Label* if_true = NULL; 3018 Label* if_true = NULL;
2909 Label* if_false = NULL; 3019 Label* if_false = NULL;
2910 Label* fall_through = NULL; 3020 Label* fall_through = NULL;
2911 3021
2912 // Notice that the labels are swapped. 3022 // Notice that the labels are swapped.
2913 context()->PrepareTest(&materialize_true, &materialize_false, 3023 context()->PrepareTest(&materialize_true, &materialize_false,
2914 &if_false, &if_true, &fall_through); 3024 &if_false, &if_true, &fall_through);
3025 if (context()->IsTest()) ForwardBailoutToChild(expr);
2915 VisitForControl(expr->expression(), if_true, if_false, fall_through); 3026 VisitForControl(expr->expression(), if_true, if_false, fall_through);
2916 context()->Plug(if_false, if_true); // Labels swapped. 3027 context()->Plug(if_false, if_true); // Labels swapped.
2917 break; 3028 break;
2918 } 3029 }
2919 3030
2920 case Token::TYPEOF: { 3031 case Token::TYPEOF: {
2921 Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); 3032 Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
2922 { StackValueContext context(this); 3033 { StackValueContext context(this);
2923 VisitForTypeofValue(expr->expression()); 3034 VisitForTypeofValue(expr->expression());
2924 } 3035 }
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
3024 if (expr->is_postfix() && !context()->IsEffect()) { 3135 if (expr->is_postfix() && !context()->IsEffect()) {
3025 __ mov(ip, Operand(Smi::FromInt(0))); 3136 __ mov(ip, Operand(Smi::FromInt(0)));
3026 __ push(ip); 3137 __ push(ip);
3027 } 3138 }
3028 if (assign_type == NAMED_PROPERTY) { 3139 if (assign_type == NAMED_PROPERTY) {
3029 // Put the object both on the stack and in the accumulator. 3140 // Put the object both on the stack and in the accumulator.
3030 VisitForAccumulatorValue(prop->obj()); 3141 VisitForAccumulatorValue(prop->obj());
3031 __ push(r0); 3142 __ push(r0);
3032 EmitNamedPropertyLoad(prop); 3143 EmitNamedPropertyLoad(prop);
3033 } else { 3144 } else {
3034 VisitForStackValue(prop->obj()); 3145 if (prop->is_arguments_access()) {
3035 VisitForAccumulatorValue(prop->key()); 3146 VariableProxy* obj_proxy = prop->obj()->AsVariableProxy();
3147 __ ldr(r0, EmitSlotSearch(obj_proxy->var()->AsSlot(), r0));
3148 __ push(r0);
3149 __ mov(r0, Operand(prop->key()->AsLiteral()->handle()));
3150 } else {
3151 VisitForStackValue(prop->obj());
3152 VisitForAccumulatorValue(prop->key());
3153 }
3036 __ ldr(r1, MemOperand(sp, 0)); 3154 __ ldr(r1, MemOperand(sp, 0));
3037 __ push(r0); 3155 __ push(r0);
3038 EmitKeyedPropertyLoad(prop); 3156 EmitKeyedPropertyLoad(prop);
3039 } 3157 }
3040 } 3158 }
3041 3159
3160 // We need a second deoptimization point after loading the value
3161 // in case evaluating the property load my have a side effect.
3162 PrepareForBailout(expr->increment(), TOS_REG);
3163
3042 // Call ToNumber only if operand is not a smi. 3164 // Call ToNumber only if operand is not a smi.
3043 Label no_conversion; 3165 Label no_conversion;
3044 __ BranchOnSmi(r0, &no_conversion); 3166 __ BranchOnSmi(r0, &no_conversion);
3045 __ push(r0); 3167 __ push(r0);
3046 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS); 3168 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS);
3047 __ bind(&no_conversion); 3169 __ bind(&no_conversion);
3048 3170
3049 // Save result for postfix expressions. 3171 // Save result for postfix expressions.
3050 if (expr->is_postfix()) { 3172 if (expr->is_postfix()) {
3051 if (!context()->IsEffect()) { 3173 if (!context()->IsEffect()) {
(...skipping 22 matching lines...) Expand all
3074 __ add(r0, r0, Operand(Smi::FromInt(count_value)), SetCC); 3196 __ add(r0, r0, Operand(Smi::FromInt(count_value)), SetCC);
3075 __ b(vs, &stub_call); 3197 __ b(vs, &stub_call);
3076 // We could eliminate this smi check if we split the code at 3198 // We could eliminate this smi check if we split the code at
3077 // the first smi check before calling ToNumber. 3199 // the first smi check before calling ToNumber.
3078 __ BranchOnSmi(r0, &done); 3200 __ BranchOnSmi(r0, &done);
3079 __ bind(&stub_call); 3201 __ bind(&stub_call);
3080 // Call stub. Undo operation first. 3202 // Call stub. Undo operation first.
3081 __ sub(r0, r0, Operand(Smi::FromInt(count_value))); 3203 __ sub(r0, r0, Operand(Smi::FromInt(count_value)));
3082 } 3204 }
3083 __ mov(r1, Operand(Smi::FromInt(count_value))); 3205 __ mov(r1, Operand(Smi::FromInt(count_value)));
3206
3207 // Record position before stub call.
3208 SetSourcePosition(expr->position());
3209
3084 GenericBinaryOpStub stub(Token::ADD, NO_OVERWRITE, r1, r0); 3210 GenericBinaryOpStub stub(Token::ADD, NO_OVERWRITE, r1, r0);
3085 __ CallStub(&stub); 3211 __ CallStub(&stub);
3086 __ bind(&done); 3212 __ bind(&done);
3087 3213
3088 // Store the value returned in r0. 3214 // Store the value returned in r0.
3089 switch (assign_type) { 3215 switch (assign_type) {
3090 case VARIABLE: 3216 case VARIABLE:
3091 if (expr->is_postfix()) { 3217 if (expr->is_postfix()) {
3092 { EffectContext context(this); 3218 { EffectContext context(this);
3093 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 3219 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
3143 VariableProxy* proxy = expr->AsVariableProxy(); 3269 VariableProxy* proxy = expr->AsVariableProxy();
3144 if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) { 3270 if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) {
3145 Comment cmnt(masm_, "Global variable"); 3271 Comment cmnt(masm_, "Global variable");
3146 __ ldr(r0, GlobalObjectOperand()); 3272 __ ldr(r0, GlobalObjectOperand());
3147 __ mov(r2, Operand(proxy->name())); 3273 __ mov(r2, Operand(proxy->name()));
3148 Handle<Code> ic(Isolate::Current()->builtins()->builtin( 3274 Handle<Code> ic(Isolate::Current()->builtins()->builtin(
3149 Builtins::LoadIC_Initialize)); 3275 Builtins::LoadIC_Initialize));
3150 // Use a regular load, not a contextual load, to avoid a reference 3276 // Use a regular load, not a contextual load, to avoid a reference
3151 // error. 3277 // error.
3152 EmitCallIC(ic, RelocInfo::CODE_TARGET); 3278 EmitCallIC(ic, RelocInfo::CODE_TARGET);
3279 PrepareForBailout(expr, TOS_REG);
3153 context()->Plug(r0); 3280 context()->Plug(r0);
3154 } else if (proxy != NULL && 3281 } else if (proxy != NULL &&
3155 proxy->var()->AsSlot() != NULL && 3282 proxy->var()->AsSlot() != NULL &&
3156 proxy->var()->AsSlot()->type() == Slot::LOOKUP) { 3283 proxy->var()->AsSlot()->type() == Slot::LOOKUP) {
3157 Label done, slow; 3284 Label done, slow;
3158 3285
3159 // Generate code for loading from variables potentially shadowed 3286 // Generate code for loading from variables potentially shadowed
3160 // by eval-introduced variables. 3287 // by eval-introduced variables.
3161 Slot* slot = proxy->var()->AsSlot(); 3288 Slot* slot = proxy->var()->AsSlot();
3162 EmitDynamicLoadFromSlotFastCase(slot, INSIDE_TYPEOF, &slow, &done); 3289 EmitDynamicLoadFromSlotFastCase(slot, INSIDE_TYPEOF, &slow, &done);
3163 3290
3164 __ bind(&slow); 3291 __ bind(&slow);
3165 __ mov(r0, Operand(proxy->name())); 3292 __ mov(r0, Operand(proxy->name()));
3166 __ Push(cp, r0); 3293 __ Push(cp, r0);
3167 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); 3294 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
3295 PrepareForBailout(expr, TOS_REG);
3168 __ bind(&done); 3296 __ bind(&done);
3169 3297
3170 context()->Plug(r0); 3298 context()->Plug(r0);
3171 } else { 3299 } else {
3172 // This expression cannot throw a reference error at the top level. 3300 // This expression cannot throw a reference error at the top level.
3173 Visit(expr); 3301 context()->HandleExpression(expr);
3174 } 3302 }
3175 } 3303 }
3176 3304
3177 3305
3178 bool FullCodeGenerator::TryLiteralCompare(Token::Value op, 3306 bool FullCodeGenerator::TryLiteralCompare(Token::Value op,
3179 Expression* left, 3307 Expression* left,
3180 Expression* right, 3308 Expression* right,
3181 Label* if_true, 3309 Label* if_true,
3182 Label* if_false, 3310 Label* if_false,
3183 Label* fall_through) { 3311 Label* fall_through) {
3184 if (op != Token::EQ && op != Token::EQ_STRICT) return false; 3312 if (op != Token::EQ && op != Token::EQ_STRICT) return false;
3185 3313
3186 // Check for the pattern: typeof <expression> == <string literal>. 3314 // Check for the pattern: typeof <expression> == <string literal>.
3187 Literal* right_literal = right->AsLiteral(); 3315 Literal* right_literal = right->AsLiteral();
3188 if (right_literal == NULL) return false; 3316 if (right_literal == NULL) return false;
3189 Handle<Object> right_literal_value = right_literal->handle(); 3317 Handle<Object> right_literal_value = right_literal->handle();
3190 if (!right_literal_value->IsString()) return false; 3318 if (!right_literal_value->IsString()) return false;
3191 UnaryOperation* left_unary = left->AsUnaryOperation(); 3319 UnaryOperation* left_unary = left->AsUnaryOperation();
3192 if (left_unary == NULL || left_unary->op() != Token::TYPEOF) return false; 3320 if (left_unary == NULL || left_unary->op() != Token::TYPEOF) return false;
3193 Handle<String> check = Handle<String>::cast(right_literal_value); 3321 Handle<String> check = Handle<String>::cast(right_literal_value);
3194 3322
3195 { AccumulatorValueContext context(this); 3323 { AccumulatorValueContext context(this);
3196 VisitForTypeofValue(left_unary->expression()); 3324 VisitForTypeofValue(left_unary->expression());
3197 } 3325 }
3326 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
3327
3198 if (check->Equals(HEAP->number_symbol())) { 3328 if (check->Equals(HEAP->number_symbol())) {
3199 __ tst(r0, Operand(kSmiTagMask)); 3329 __ tst(r0, Operand(kSmiTagMask));
3200 __ b(eq, if_true); 3330 __ b(eq, if_true);
3201 __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset)); 3331 __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
3202 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); 3332 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
3203 __ cmp(r0, ip); 3333 __ cmp(r0, ip);
3204 Split(eq, if_true, if_false, fall_through); 3334 Split(eq, if_true, if_false, fall_through);
3205 } else if (check->Equals(HEAP->string_symbol())) { 3335 } else if (check->Equals(HEAP->string_symbol())) {
3206 __ tst(r0, Operand(kSmiTagMask)); 3336 __ tst(r0, Operand(kSmiTagMask));
3207 __ b(eq, if_false); 3337 __ b(eq, if_false);
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
3291 if (TryLiteralCompare(op, left, right, if_true, if_false, fall_through)) { 3421 if (TryLiteralCompare(op, left, right, if_true, if_false, fall_through)) {
3292 context()->Plug(if_true, if_false); 3422 context()->Plug(if_true, if_false);
3293 return; 3423 return;
3294 } 3424 }
3295 3425
3296 VisitForStackValue(expr->left()); 3426 VisitForStackValue(expr->left());
3297 switch (op) { 3427 switch (op) {
3298 case Token::IN: 3428 case Token::IN:
3299 VisitForStackValue(expr->right()); 3429 VisitForStackValue(expr->right());
3300 __ InvokeBuiltin(Builtins::IN, CALL_JS); 3430 __ InvokeBuiltin(Builtins::IN, CALL_JS);
3431 PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
3301 __ LoadRoot(ip, Heap::kTrueValueRootIndex); 3432 __ LoadRoot(ip, Heap::kTrueValueRootIndex);
3302 __ cmp(r0, ip); 3433 __ cmp(r0, ip);
3303 Split(eq, if_true, if_false, fall_through); 3434 Split(eq, if_true, if_false, fall_through);
3304 break; 3435 break;
3305 3436
3306 case Token::INSTANCEOF: { 3437 case Token::INSTANCEOF: {
3307 VisitForStackValue(expr->right()); 3438 VisitForStackValue(expr->right());
3308 InstanceofStub stub; 3439 InstanceofStub stub;
3309 __ CallStub(&stub); 3440 __ CallStub(&stub);
3441 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
3310 // The stub returns 0 for true. 3442 // The stub returns 0 for true.
3311 __ tst(r0, r0); 3443 __ tst(r0, r0);
3312 Split(eq, if_true, if_false, fall_through); 3444 Split(eq, if_true, if_false, fall_through);
3313 break; 3445 break;
3314 } 3446 }
3315 3447
3316 default: { 3448 default: {
3317 VisitForAccumulatorValue(expr->right()); 3449 VisitForAccumulatorValue(expr->right());
3318 Condition cc = eq; 3450 Condition cc = eq;
3319 bool strict = false; 3451 bool strict = false;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
3358 __ BranchOnNotSmi(r2, &slow_case); 3490 __ BranchOnNotSmi(r2, &slow_case);
3359 __ cmp(r1, r0); 3491 __ cmp(r1, r0);
3360 Split(cc, if_true, if_false, NULL); 3492 Split(cc, if_true, if_false, NULL);
3361 __ bind(&slow_case); 3493 __ bind(&slow_case);
3362 } 3494 }
3363 CompareFlags flags = inline_smi_code 3495 CompareFlags flags = inline_smi_code
3364 ? NO_SMI_COMPARE_IN_STUB 3496 ? NO_SMI_COMPARE_IN_STUB
3365 : NO_COMPARE_FLAGS; 3497 : NO_COMPARE_FLAGS;
3366 CompareStub stub(cc, strict, flags, r1, r0); 3498 CompareStub stub(cc, strict, flags, r1, r0);
3367 __ CallStub(&stub); 3499 __ CallStub(&stub);
3500 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
3368 __ cmp(r0, Operand(0, RelocInfo::NONE)); 3501 __ cmp(r0, Operand(0, RelocInfo::NONE));
3369 Split(cc, if_true, if_false, fall_through); 3502 Split(cc, if_true, if_false, fall_through);
3370 } 3503 }
3371 } 3504 }
3372 3505
3373 // Convert the result of the comparison into one expected for this 3506 // Convert the result of the comparison into one expected for this
3374 // expression's context. 3507 // expression's context.
3375 context()->Plug(if_true, if_false); 3508 context()->Plug(if_true, if_false);
3376 } 3509 }
3377 3510
3378 3511
3379 void FullCodeGenerator::VisitCompareToNull(CompareToNull* expr) { 3512 void FullCodeGenerator::VisitCompareToNull(CompareToNull* expr) {
3380 Comment cmnt(masm_, "[ CompareToNull"); 3513 Comment cmnt(masm_, "[ CompareToNull");
3381 Label materialize_true, materialize_false; 3514 Label materialize_true, materialize_false;
3382 Label* if_true = NULL; 3515 Label* if_true = NULL;
3383 Label* if_false = NULL; 3516 Label* if_false = NULL;
3384 Label* fall_through = NULL; 3517 Label* fall_through = NULL;
3385 context()->PrepareTest(&materialize_true, &materialize_false, 3518 context()->PrepareTest(&materialize_true, &materialize_false,
3386 &if_true, &if_false, &fall_through); 3519 &if_true, &if_false, &fall_through);
3387 3520
3388 VisitForAccumulatorValue(expr->expression()); 3521 VisitForAccumulatorValue(expr->expression());
3522 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
3389 __ LoadRoot(r1, Heap::kNullValueRootIndex); 3523 __ LoadRoot(r1, Heap::kNullValueRootIndex);
3390 __ cmp(r0, r1); 3524 __ cmp(r0, r1);
3391 if (expr->is_strict()) { 3525 if (expr->is_strict()) {
3392 Split(eq, if_true, if_false, fall_through); 3526 Split(eq, if_true, if_false, fall_through);
3393 } else { 3527 } else {
3394 __ b(eq, if_true); 3528 __ b(eq, if_true);
3395 __ LoadRoot(r1, Heap::kUndefinedValueRootIndex); 3529 __ LoadRoot(r1, Heap::kUndefinedValueRootIndex);
3396 __ cmp(r0, r1); 3530 __ cmp(r0, r1);
3397 __ b(eq, if_true); 3531 __ b(eq, if_true);
3398 __ tst(r0, Operand(kSmiTagMask)); 3532 __ tst(r0, Operand(kSmiTagMask));
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
3468 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. 3602 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value.
3469 __ add(pc, r1, Operand(masm_->CodeObject())); 3603 __ add(pc, r1, Operand(masm_->CodeObject()));
3470 } 3604 }
3471 3605
3472 3606
3473 #undef __ 3607 #undef __
3474 3608
3475 } } // namespace v8::internal 3609 } } // namespace v8::internal
3476 3610
3477 #endif // V8_TARGET_ARCH_ARM 3611 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « src/arm/frames-arm.cc ('k') | src/arm/ic-arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698