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

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

Issue 8386037: Remove the forward-bailout stack from the non-optimizing compiler. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 9 years, 1 month 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 | « no previous file | src/ast.h » ('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 376 matching lines...) Expand 10 before | Expand all | Expand 10 after
387 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); 387 ASSERT(var->IsStackAllocated() || var->IsContextSlot());
388 codegen()->GetVar(result_register(), var); 388 codegen()->GetVar(result_register(), var);
389 __ push(result_register()); 389 __ push(result_register());
390 } 390 }
391 391
392 392
393 void FullCodeGenerator::TestContext::Plug(Variable* var) const { 393 void FullCodeGenerator::TestContext::Plug(Variable* var) const {
394 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); 394 ASSERT(var->IsStackAllocated() || var->IsContextSlot());
395 // For simplicity we always test the accumulator register. 395 // For simplicity we always test the accumulator register.
396 codegen()->GetVar(result_register(), var); 396 codegen()->GetVar(result_register(), var);
397 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); 397 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
398 codegen()->DoTest(this); 398 codegen()->DoTest(this);
399 } 399 }
400 400
401 401
402 void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const { 402 void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const {
403 } 403 }
404 404
405 405
406 void FullCodeGenerator::AccumulatorValueContext::Plug( 406 void FullCodeGenerator::AccumulatorValueContext::Plug(
407 Heap::RootListIndex index) const { 407 Heap::RootListIndex index) const {
408 __ LoadRoot(result_register(), index); 408 __ LoadRoot(result_register(), index);
409 } 409 }
410 410
411 411
412 void FullCodeGenerator::StackValueContext::Plug( 412 void FullCodeGenerator::StackValueContext::Plug(
413 Heap::RootListIndex index) const { 413 Heap::RootListIndex index) const {
414 __ LoadRoot(result_register(), index); 414 __ LoadRoot(result_register(), index);
415 __ push(result_register()); 415 __ push(result_register());
416 } 416 }
417 417
418 418
419 void FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const { 419 void FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const {
420 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, 420 codegen()->PrepareForBailoutBeforeSplit(condition(),
421 true, 421 true,
422 true_label_, 422 true_label_,
423 false_label_); 423 false_label_);
424 if (index == Heap::kUndefinedValueRootIndex || 424 if (index == Heap::kUndefinedValueRootIndex ||
425 index == Heap::kNullValueRootIndex || 425 index == Heap::kNullValueRootIndex ||
426 index == Heap::kFalseValueRootIndex) { 426 index == Heap::kFalseValueRootIndex) {
427 if (false_label_ != fall_through_) __ b(false_label_); 427 if (false_label_ != fall_through_) __ b(false_label_);
428 } else if (index == Heap::kTrueValueRootIndex) { 428 } else if (index == Heap::kTrueValueRootIndex) {
429 if (true_label_ != fall_through_) __ b(true_label_); 429 if (true_label_ != fall_through_) __ b(true_label_);
430 } else { 430 } else {
(...skipping 14 matching lines...) Expand all
445 445
446 446
447 void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const { 447 void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const {
448 // Immediates cannot be pushed directly. 448 // Immediates cannot be pushed directly.
449 __ mov(result_register(), Operand(lit)); 449 __ mov(result_register(), Operand(lit));
450 __ push(result_register()); 450 __ push(result_register());
451 } 451 }
452 452
453 453
454 void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const { 454 void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const {
455 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, 455 codegen()->PrepareForBailoutBeforeSplit(condition(),
456 true, 456 true,
457 true_label_, 457 true_label_,
458 false_label_); 458 false_label_);
459 ASSERT(!lit->IsUndetectableObject()); // There are no undetectable literals. 459 ASSERT(!lit->IsUndetectableObject()); // There are no undetectable literals.
460 if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) { 460 if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) {
461 if (false_label_ != fall_through_) __ b(false_label_); 461 if (false_label_ != fall_through_) __ b(false_label_);
462 } else if (lit->IsTrue() || lit->IsJSObject()) { 462 } else if (lit->IsTrue() || lit->IsJSObject()) {
463 if (true_label_ != fall_through_) __ b(true_label_); 463 if (true_label_ != fall_through_) __ b(true_label_);
464 } else if (lit->IsString()) { 464 } else if (lit->IsString()) {
465 if (String::cast(*lit)->length() == 0) { 465 if (String::cast(*lit)->length() == 0) {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
504 __ str(reg, MemOperand(sp, 0)); 504 __ str(reg, MemOperand(sp, 0));
505 } 505 }
506 506
507 507
508 void FullCodeGenerator::TestContext::DropAndPlug(int count, 508 void FullCodeGenerator::TestContext::DropAndPlug(int count,
509 Register reg) const { 509 Register reg) const {
510 ASSERT(count > 0); 510 ASSERT(count > 0);
511 // For simplicity we always test the accumulator register. 511 // For simplicity we always test the accumulator register.
512 __ Drop(count); 512 __ Drop(count);
513 __ Move(result_register(), reg); 513 __ Move(result_register(), reg);
514 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); 514 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
515 codegen()->DoTest(this); 515 codegen()->DoTest(this);
516 } 516 }
517 517
518 518
519 void FullCodeGenerator::EffectContext::Plug(Label* materialize_true, 519 void FullCodeGenerator::EffectContext::Plug(Label* materialize_true,
520 Label* materialize_false) const { 520 Label* materialize_false) const {
521 ASSERT(materialize_true == materialize_false); 521 ASSERT(materialize_true == materialize_false);
522 __ bind(materialize_true); 522 __ bind(materialize_true);
523 } 523 }
524 524
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
571 571
572 void FullCodeGenerator::StackValueContext::Plug(bool flag) const { 572 void FullCodeGenerator::StackValueContext::Plug(bool flag) const {
573 Heap::RootListIndex value_root_index = 573 Heap::RootListIndex value_root_index =
574 flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; 574 flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
575 __ LoadRoot(ip, value_root_index); 575 __ LoadRoot(ip, value_root_index);
576 __ push(ip); 576 __ push(ip);
577 } 577 }
578 578
579 579
580 void FullCodeGenerator::TestContext::Plug(bool flag) const { 580 void FullCodeGenerator::TestContext::Plug(bool flag) const {
581 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, 581 codegen()->PrepareForBailoutBeforeSplit(condition(),
582 true, 582 true,
583 true_label_, 583 true_label_,
584 false_label_); 584 false_label_);
585 if (flag) { 585 if (flag) {
586 if (true_label_ != fall_through_) __ b(true_label_); 586 if (true_label_ != fall_through_) __ b(true_label_);
587 } else { 587 } else {
588 if (false_label_ != fall_through_) __ b(false_label_); 588 if (false_label_ != fall_through_) __ b(false_label_);
589 } 589 }
590 } 590 }
591 591
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
674 __ RecordWriteContextSlot(scratch0, 674 __ RecordWriteContextSlot(scratch0,
675 location.offset(), 675 location.offset(),
676 src, 676 src,
677 scratch1, 677 scratch1,
678 kLRHasBeenSaved, 678 kLRHasBeenSaved,
679 kDontSaveFPRegs); 679 kDontSaveFPRegs);
680 } 680 }
681 } 681 }
682 682
683 683
684 void FullCodeGenerator::PrepareForBailoutBeforeSplit(State state, 684 void FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr,
685 bool should_normalize, 685 bool should_normalize,
686 Label* if_true, 686 Label* if_true,
687 Label* if_false) { 687 Label* if_false) {
688 // Only prepare for bailouts before splits if we're in a test 688 // Only prepare for bailouts before splits if we're in a test
689 // context. Otherwise, we let the Visit function deal with the 689 // context. Otherwise, we let the Visit function deal with the
690 // preparation to avoid preparing with the same AST id twice. 690 // preparation to avoid preparing with the same AST id twice.
691 if (!context()->IsTest() || !info_->IsOptimizable()) return; 691 if (!context()->IsTest() || !info_->IsOptimizable()) return;
692 692
693 Label skip; 693 Label skip;
694 if (should_normalize) __ b(&skip); 694 if (should_normalize) __ b(&skip);
695 695 PrepareForBailout(expr, TOS_REG);
696 ForwardBailoutStack* current = forward_bailout_stack_;
697 while (current != NULL) {
698 PrepareForBailout(current->expr(), state);
699 current = current->parent();
700 }
701
702 if (should_normalize) { 696 if (should_normalize) {
703 __ LoadRoot(ip, Heap::kTrueValueRootIndex); 697 __ LoadRoot(ip, Heap::kTrueValueRootIndex);
704 __ cmp(r0, ip); 698 __ cmp(r0, ip);
705 Split(eq, if_true, if_false, NULL); 699 Split(eq, if_true, if_false, NULL);
706 __ bind(&skip); 700 __ bind(&skip);
707 } 701 }
708 } 702 }
709 703
710 704
711 void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy, 705 void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy,
(...skipping 1658 matching lines...) Expand 10 before | Expand all | Expand 10 after
2370 __ mov(r0, Operand(arg_count)); 2364 __ mov(r0, Operand(arg_count));
2371 __ ldr(r1, MemOperand(sp, arg_count * kPointerSize)); 2365 __ ldr(r1, MemOperand(sp, arg_count * kPointerSize));
2372 2366
2373 Handle<Code> construct_builtin = 2367 Handle<Code> construct_builtin =
2374 isolate()->builtins()->JSConstructCall(); 2368 isolate()->builtins()->JSConstructCall();
2375 __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL); 2369 __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL);
2376 context()->Plug(r0); 2370 context()->Plug(r0);
2377 } 2371 }
2378 2372
2379 2373
2380 void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) { 2374 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) {
2375 ZoneList<Expression*>* args = expr->arguments();
2381 ASSERT(args->length() == 1); 2376 ASSERT(args->length() == 1);
2382 2377
2383 VisitForAccumulatorValue(args->at(0)); 2378 VisitForAccumulatorValue(args->at(0));
2384 2379
2385 Label materialize_true, materialize_false; 2380 Label materialize_true, materialize_false;
2386 Label* if_true = NULL; 2381 Label* if_true = NULL;
2387 Label* if_false = NULL; 2382 Label* if_false = NULL;
2388 Label* fall_through = NULL; 2383 Label* fall_through = NULL;
2389 context()->PrepareTest(&materialize_true, &materialize_false, 2384 context()->PrepareTest(&materialize_true, &materialize_false,
2390 &if_true, &if_false, &fall_through); 2385 &if_true, &if_false, &fall_through);
2391 2386
2392 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 2387 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2393 __ tst(r0, Operand(kSmiTagMask)); 2388 __ tst(r0, Operand(kSmiTagMask));
2394 Split(eq, if_true, if_false, fall_through); 2389 Split(eq, if_true, if_false, fall_through);
2395 2390
2396 context()->Plug(if_true, if_false); 2391 context()->Plug(if_true, if_false);
2397 } 2392 }
2398 2393
2399 2394
2400 void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) { 2395 void FullCodeGenerator::EmitIsNonNegativeSmi(CallRuntime* expr) {
2396 ZoneList<Expression*>* args = expr->arguments();
2401 ASSERT(args->length() == 1); 2397 ASSERT(args->length() == 1);
2402 2398
2403 VisitForAccumulatorValue(args->at(0)); 2399 VisitForAccumulatorValue(args->at(0));
2404 2400
2405 Label materialize_true, materialize_false; 2401 Label materialize_true, materialize_false;
2406 Label* if_true = NULL; 2402 Label* if_true = NULL;
2407 Label* if_false = NULL; 2403 Label* if_false = NULL;
2408 Label* fall_through = NULL; 2404 Label* fall_through = NULL;
2409 context()->PrepareTest(&materialize_true, &materialize_false, 2405 context()->PrepareTest(&materialize_true, &materialize_false,
2410 &if_true, &if_false, &fall_through); 2406 &if_true, &if_false, &fall_through);
2411 2407
2412 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 2408 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2413 __ tst(r0, Operand(kSmiTagMask | 0x80000000)); 2409 __ tst(r0, Operand(kSmiTagMask | 0x80000000));
2414 Split(eq, if_true, if_false, fall_through); 2410 Split(eq, if_true, if_false, fall_through);
2415 2411
2416 context()->Plug(if_true, if_false); 2412 context()->Plug(if_true, if_false);
2417 } 2413 }
2418 2414
2419 2415
2420 void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) { 2416 void FullCodeGenerator::EmitIsObject(CallRuntime* expr) {
2417 ZoneList<Expression*>* args = expr->arguments();
2421 ASSERT(args->length() == 1); 2418 ASSERT(args->length() == 1);
2422 2419
2423 VisitForAccumulatorValue(args->at(0)); 2420 VisitForAccumulatorValue(args->at(0));
2424 2421
2425 Label materialize_true, materialize_false; 2422 Label materialize_true, materialize_false;
2426 Label* if_true = NULL; 2423 Label* if_true = NULL;
2427 Label* if_false = NULL; 2424 Label* if_false = NULL;
2428 Label* fall_through = NULL; 2425 Label* fall_through = NULL;
2429 context()->PrepareTest(&materialize_true, &materialize_false, 2426 context()->PrepareTest(&materialize_true, &materialize_false,
2430 &if_true, &if_false, &fall_through); 2427 &if_true, &if_false, &fall_through);
2431 2428
2432 __ JumpIfSmi(r0, if_false); 2429 __ JumpIfSmi(r0, if_false);
2433 __ LoadRoot(ip, Heap::kNullValueRootIndex); 2430 __ LoadRoot(ip, Heap::kNullValueRootIndex);
2434 __ cmp(r0, ip); 2431 __ cmp(r0, ip);
2435 __ b(eq, if_true); 2432 __ b(eq, if_true);
2436 __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); 2433 __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset));
2437 // Undetectable objects behave like undefined when tested with typeof. 2434 // Undetectable objects behave like undefined when tested with typeof.
2438 __ ldrb(r1, FieldMemOperand(r2, Map::kBitFieldOffset)); 2435 __ ldrb(r1, FieldMemOperand(r2, Map::kBitFieldOffset));
2439 __ tst(r1, Operand(1 << Map::kIsUndetectable)); 2436 __ tst(r1, Operand(1 << Map::kIsUndetectable));
2440 __ b(ne, if_false); 2437 __ b(ne, if_false);
2441 __ ldrb(r1, FieldMemOperand(r2, Map::kInstanceTypeOffset)); 2438 __ ldrb(r1, FieldMemOperand(r2, Map::kInstanceTypeOffset));
2442 __ cmp(r1, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); 2439 __ cmp(r1, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
2443 __ b(lt, if_false); 2440 __ b(lt, if_false);
2444 __ cmp(r1, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); 2441 __ cmp(r1, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE));
2445 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 2442 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2446 Split(le, if_true, if_false, fall_through); 2443 Split(le, if_true, if_false, fall_through);
2447 2444
2448 context()->Plug(if_true, if_false); 2445 context()->Plug(if_true, if_false);
2449 } 2446 }
2450 2447
2451 2448
2452 void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) { 2449 void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) {
2450 ZoneList<Expression*>* args = expr->arguments();
2453 ASSERT(args->length() == 1); 2451 ASSERT(args->length() == 1);
2454 2452
2455 VisitForAccumulatorValue(args->at(0)); 2453 VisitForAccumulatorValue(args->at(0));
2456 2454
2457 Label materialize_true, materialize_false; 2455 Label materialize_true, materialize_false;
2458 Label* if_true = NULL; 2456 Label* if_true = NULL;
2459 Label* if_false = NULL; 2457 Label* if_false = NULL;
2460 Label* fall_through = NULL; 2458 Label* fall_through = NULL;
2461 context()->PrepareTest(&materialize_true, &materialize_false, 2459 context()->PrepareTest(&materialize_true, &materialize_false,
2462 &if_true, &if_false, &fall_through); 2460 &if_true, &if_false, &fall_through);
2463 2461
2464 __ JumpIfSmi(r0, if_false); 2462 __ JumpIfSmi(r0, if_false);
2465 __ CompareObjectType(r0, r1, r1, FIRST_SPEC_OBJECT_TYPE); 2463 __ CompareObjectType(r0, r1, r1, FIRST_SPEC_OBJECT_TYPE);
2466 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 2464 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2467 Split(ge, if_true, if_false, fall_through); 2465 Split(ge, if_true, if_false, fall_through);
2468 2466
2469 context()->Plug(if_true, if_false); 2467 context()->Plug(if_true, if_false);
2470 } 2468 }
2471 2469
2472 2470
2473 void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) { 2471 void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) {
2472 ZoneList<Expression*>* args = expr->arguments();
2474 ASSERT(args->length() == 1); 2473 ASSERT(args->length() == 1);
2475 2474
2476 VisitForAccumulatorValue(args->at(0)); 2475 VisitForAccumulatorValue(args->at(0));
2477 2476
2478 Label materialize_true, materialize_false; 2477 Label materialize_true, materialize_false;
2479 Label* if_true = NULL; 2478 Label* if_true = NULL;
2480 Label* if_false = NULL; 2479 Label* if_false = NULL;
2481 Label* fall_through = NULL; 2480 Label* fall_through = NULL;
2482 context()->PrepareTest(&materialize_true, &materialize_false, 2481 context()->PrepareTest(&materialize_true, &materialize_false,
2483 &if_true, &if_false, &fall_through); 2482 &if_true, &if_false, &fall_through);
2484 2483
2485 __ JumpIfSmi(r0, if_false); 2484 __ JumpIfSmi(r0, if_false);
2486 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); 2485 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
2487 __ ldrb(r1, FieldMemOperand(r1, Map::kBitFieldOffset)); 2486 __ ldrb(r1, FieldMemOperand(r1, Map::kBitFieldOffset));
2488 __ tst(r1, Operand(1 << Map::kIsUndetectable)); 2487 __ tst(r1, Operand(1 << Map::kIsUndetectable));
2489 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 2488 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2490 Split(ne, if_true, if_false, fall_through); 2489 Split(ne, if_true, if_false, fall_through);
2491 2490
2492 context()->Plug(if_true, if_false); 2491 context()->Plug(if_true, if_false);
2493 } 2492 }
2494 2493
2495 2494
2496 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( 2495 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
2497 ZoneList<Expression*>* args) { 2496 CallRuntime* expr) {
2498 2497 ZoneList<Expression*>* args = expr->arguments();
2499 ASSERT(args->length() == 1); 2498 ASSERT(args->length() == 1);
2500 2499
2501 VisitForAccumulatorValue(args->at(0)); 2500 VisitForAccumulatorValue(args->at(0));
2502 2501
2503 Label materialize_true, materialize_false; 2502 Label materialize_true, materialize_false;
2504 Label* if_true = NULL; 2503 Label* if_true = NULL;
2505 Label* if_false = NULL; 2504 Label* if_false = NULL;
2506 Label* fall_through = NULL; 2505 Label* fall_through = NULL;
2507 context()->PrepareTest(&materialize_true, &materialize_false, 2506 context()->PrepareTest(&materialize_true, &materialize_false,
2508 &if_true, &if_false, &fall_through); 2507 &if_true, &if_false, &fall_through);
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
2567 __ cmp(r2, r3); 2566 __ cmp(r2, r3);
2568 __ b(ne, if_false); 2567 __ b(ne, if_false);
2569 2568
2570 // Set the bit in the map to indicate that it has been checked safe for 2569 // Set the bit in the map to indicate that it has been checked safe for
2571 // default valueOf and set true result. 2570 // default valueOf and set true result.
2572 __ ldrb(r2, FieldMemOperand(r1, Map::kBitField2Offset)); 2571 __ ldrb(r2, FieldMemOperand(r1, Map::kBitField2Offset));
2573 __ orr(r2, r2, Operand(1 << Map::kStringWrapperSafeForDefaultValueOf)); 2572 __ orr(r2, r2, Operand(1 << Map::kStringWrapperSafeForDefaultValueOf));
2574 __ strb(r2, FieldMemOperand(r1, Map::kBitField2Offset)); 2573 __ strb(r2, FieldMemOperand(r1, Map::kBitField2Offset));
2575 __ jmp(if_true); 2574 __ jmp(if_true);
2576 2575
2577 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 2576 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2578 context()->Plug(if_true, if_false); 2577 context()->Plug(if_true, if_false);
2579 } 2578 }
2580 2579
2581 2580
2582 void FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) { 2581 void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) {
2582 ZoneList<Expression*>* args = expr->arguments();
2583 ASSERT(args->length() == 1); 2583 ASSERT(args->length() == 1);
2584 2584
2585 VisitForAccumulatorValue(args->at(0)); 2585 VisitForAccumulatorValue(args->at(0));
2586 2586
2587 Label materialize_true, materialize_false; 2587 Label materialize_true, materialize_false;
2588 Label* if_true = NULL; 2588 Label* if_true = NULL;
2589 Label* if_false = NULL; 2589 Label* if_false = NULL;
2590 Label* fall_through = NULL; 2590 Label* fall_through = NULL;
2591 context()->PrepareTest(&materialize_true, &materialize_false, 2591 context()->PrepareTest(&materialize_true, &materialize_false,
2592 &if_true, &if_false, &fall_through); 2592 &if_true, &if_false, &fall_through);
2593 2593
2594 __ JumpIfSmi(r0, if_false); 2594 __ JumpIfSmi(r0, if_false);
2595 __ CompareObjectType(r0, r1, r2, JS_FUNCTION_TYPE); 2595 __ CompareObjectType(r0, r1, r2, JS_FUNCTION_TYPE);
2596 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 2596 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2597 Split(eq, if_true, if_false, fall_through); 2597 Split(eq, if_true, if_false, fall_through);
2598 2598
2599 context()->Plug(if_true, if_false); 2599 context()->Plug(if_true, if_false);
2600 } 2600 }
2601 2601
2602 2602
2603 void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) { 2603 void FullCodeGenerator::EmitIsArray(CallRuntime* expr) {
2604 ZoneList<Expression*>* args = expr->arguments();
2604 ASSERT(args->length() == 1); 2605 ASSERT(args->length() == 1);
2605 2606
2606 VisitForAccumulatorValue(args->at(0)); 2607 VisitForAccumulatorValue(args->at(0));
2607 2608
2608 Label materialize_true, materialize_false; 2609 Label materialize_true, materialize_false;
2609 Label* if_true = NULL; 2610 Label* if_true = NULL;
2610 Label* if_false = NULL; 2611 Label* if_false = NULL;
2611 Label* fall_through = NULL; 2612 Label* fall_through = NULL;
2612 context()->PrepareTest(&materialize_true, &materialize_false, 2613 context()->PrepareTest(&materialize_true, &materialize_false,
2613 &if_true, &if_false, &fall_through); 2614 &if_true, &if_false, &fall_through);
2614 2615
2615 __ JumpIfSmi(r0, if_false); 2616 __ JumpIfSmi(r0, if_false);
2616 __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE); 2617 __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE);
2617 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 2618 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2618 Split(eq, if_true, if_false, fall_through); 2619 Split(eq, if_true, if_false, fall_through);
2619 2620
2620 context()->Plug(if_true, if_false); 2621 context()->Plug(if_true, if_false);
2621 } 2622 }
2622 2623
2623 2624
2624 void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) { 2625 void FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) {
2626 ZoneList<Expression*>* args = expr->arguments();
2625 ASSERT(args->length() == 1); 2627 ASSERT(args->length() == 1);
2626 2628
2627 VisitForAccumulatorValue(args->at(0)); 2629 VisitForAccumulatorValue(args->at(0));
2628 2630
2629 Label materialize_true, materialize_false; 2631 Label materialize_true, materialize_false;
2630 Label* if_true = NULL; 2632 Label* if_true = NULL;
2631 Label* if_false = NULL; 2633 Label* if_false = NULL;
2632 Label* fall_through = NULL; 2634 Label* fall_through = NULL;
2633 context()->PrepareTest(&materialize_true, &materialize_false, 2635 context()->PrepareTest(&materialize_true, &materialize_false,
2634 &if_true, &if_false, &fall_through); 2636 &if_true, &if_false, &fall_through);
2635 2637
2636 __ JumpIfSmi(r0, if_false); 2638 __ JumpIfSmi(r0, if_false);
2637 __ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE); 2639 __ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE);
2638 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 2640 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2639 Split(eq, if_true, if_false, fall_through); 2641 Split(eq, if_true, if_false, fall_through);
2640 2642
2641 context()->Plug(if_true, if_false); 2643 context()->Plug(if_true, if_false);
2642 } 2644 }
2643 2645
2644 2646
2645 2647
2646 void FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) { 2648 void FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) {
2647 ASSERT(args->length() == 0); 2649 ASSERT(expr->arguments()->length() == 0);
2648 2650
2649 Label materialize_true, materialize_false; 2651 Label materialize_true, materialize_false;
2650 Label* if_true = NULL; 2652 Label* if_true = NULL;
2651 Label* if_false = NULL; 2653 Label* if_false = NULL;
2652 Label* fall_through = NULL; 2654 Label* fall_through = NULL;
2653 context()->PrepareTest(&materialize_true, &materialize_false, 2655 context()->PrepareTest(&materialize_true, &materialize_false,
2654 &if_true, &if_false, &fall_through); 2656 &if_true, &if_false, &fall_through);
2655 2657
2656 // Get the frame pointer for the calling frame. 2658 // Get the frame pointer for the calling frame.
2657 __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); 2659 __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
2658 2660
2659 // Skip the arguments adaptor frame if it exists. 2661 // Skip the arguments adaptor frame if it exists.
2660 Label check_frame_marker; 2662 Label check_frame_marker;
2661 __ ldr(r1, MemOperand(r2, StandardFrameConstants::kContextOffset)); 2663 __ ldr(r1, MemOperand(r2, StandardFrameConstants::kContextOffset));
2662 __ cmp(r1, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 2664 __ cmp(r1, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
2663 __ b(ne, &check_frame_marker); 2665 __ b(ne, &check_frame_marker);
2664 __ ldr(r2, MemOperand(r2, StandardFrameConstants::kCallerFPOffset)); 2666 __ ldr(r2, MemOperand(r2, StandardFrameConstants::kCallerFPOffset));
2665 2667
2666 // Check the marker in the calling frame. 2668 // Check the marker in the calling frame.
2667 __ bind(&check_frame_marker); 2669 __ bind(&check_frame_marker);
2668 __ ldr(r1, MemOperand(r2, StandardFrameConstants::kMarkerOffset)); 2670 __ ldr(r1, MemOperand(r2, StandardFrameConstants::kMarkerOffset));
2669 __ cmp(r1, Operand(Smi::FromInt(StackFrame::CONSTRUCT))); 2671 __ cmp(r1, Operand(Smi::FromInt(StackFrame::CONSTRUCT)));
2670 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 2672 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2671 Split(eq, if_true, if_false, fall_through); 2673 Split(eq, if_true, if_false, fall_through);
2672 2674
2673 context()->Plug(if_true, if_false); 2675 context()->Plug(if_true, if_false);
2674 } 2676 }
2675 2677
2676 2678
2677 void FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) { 2679 void FullCodeGenerator::EmitObjectEquals(CallRuntime* expr) {
2680 ZoneList<Expression*>* args = expr->arguments();
2678 ASSERT(args->length() == 2); 2681 ASSERT(args->length() == 2);
2679 2682
2680 // Load the two objects into registers and perform the comparison. 2683 // Load the two objects into registers and perform the comparison.
2681 VisitForStackValue(args->at(0)); 2684 VisitForStackValue(args->at(0));
2682 VisitForAccumulatorValue(args->at(1)); 2685 VisitForAccumulatorValue(args->at(1));
2683 2686
2684 Label materialize_true, materialize_false; 2687 Label materialize_true, materialize_false;
2685 Label* if_true = NULL; 2688 Label* if_true = NULL;
2686 Label* if_false = NULL; 2689 Label* if_false = NULL;
2687 Label* fall_through = NULL; 2690 Label* fall_through = NULL;
2688 context()->PrepareTest(&materialize_true, &materialize_false, 2691 context()->PrepareTest(&materialize_true, &materialize_false,
2689 &if_true, &if_false, &fall_through); 2692 &if_true, &if_false, &fall_through);
2690 2693
2691 __ pop(r1); 2694 __ pop(r1);
2692 __ cmp(r0, r1); 2695 __ cmp(r0, r1);
2693 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 2696 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2694 Split(eq, if_true, if_false, fall_through); 2697 Split(eq, if_true, if_false, fall_through);
2695 2698
2696 context()->Plug(if_true, if_false); 2699 context()->Plug(if_true, if_false);
2697 } 2700 }
2698 2701
2699 2702
2700 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) { 2703 void FullCodeGenerator::EmitArguments(CallRuntime* expr) {
2704 ZoneList<Expression*>* args = expr->arguments();
2701 ASSERT(args->length() == 1); 2705 ASSERT(args->length() == 1);
2702 2706
2703 // ArgumentsAccessStub expects the key in edx and the formal 2707 // ArgumentsAccessStub expects the key in edx and the formal
2704 // parameter count in r0. 2708 // parameter count in r0.
2705 VisitForAccumulatorValue(args->at(0)); 2709 VisitForAccumulatorValue(args->at(0));
2706 __ mov(r1, r0); 2710 __ mov(r1, r0);
2707 __ mov(r0, Operand(Smi::FromInt(info_->scope()->num_parameters()))); 2711 __ mov(r0, Operand(Smi::FromInt(info_->scope()->num_parameters())));
2708 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); 2712 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
2709 __ CallStub(&stub); 2713 __ CallStub(&stub);
2710 context()->Plug(r0); 2714 context()->Plug(r0);
2711 } 2715 }
2712 2716
2713 2717
2714 void FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) { 2718 void FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) {
2715 ASSERT(args->length() == 0); 2719 ASSERT(expr->arguments()->length() == 0);
2716
2717 Label exit; 2720 Label exit;
2718 // Get the number of formal parameters. 2721 // Get the number of formal parameters.
2719 __ mov(r0, Operand(Smi::FromInt(info_->scope()->num_parameters()))); 2722 __ mov(r0, Operand(Smi::FromInt(info_->scope()->num_parameters())));
2720 2723
2721 // Check if the calling frame is an arguments adaptor frame. 2724 // Check if the calling frame is an arguments adaptor frame.
2722 __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); 2725 __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
2723 __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset)); 2726 __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset));
2724 __ cmp(r3, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 2727 __ cmp(r3, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
2725 __ b(ne, &exit); 2728 __ b(ne, &exit);
2726 2729
2727 // Arguments adaptor case: Read the arguments length from the 2730 // Arguments adaptor case: Read the arguments length from the
2728 // adaptor frame. 2731 // adaptor frame.
2729 __ ldr(r0, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset)); 2732 __ ldr(r0, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset));
2730 2733
2731 __ bind(&exit); 2734 __ bind(&exit);
2732 context()->Plug(r0); 2735 context()->Plug(r0);
2733 } 2736 }
2734 2737
2735 2738
2736 void FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) { 2739 void FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
2740 ZoneList<Expression*>* args = expr->arguments();
2737 ASSERT(args->length() == 1); 2741 ASSERT(args->length() == 1);
2738 Label done, null, function, non_function_constructor; 2742 Label done, null, function, non_function_constructor;
2739 2743
2740 VisitForAccumulatorValue(args->at(0)); 2744 VisitForAccumulatorValue(args->at(0));
2741 2745
2742 // If the object is a smi, we return null. 2746 // If the object is a smi, we return null.
2743 __ JumpIfSmi(r0, &null); 2747 __ JumpIfSmi(r0, &null);
2744 2748
2745 // Check that the object is a JS object but take special care of JS 2749 // Check that the object is a JS object but take special care of JS
2746 // functions to make sure they have 'Function' as their class. 2750 // functions to make sure they have 'Function' as their class.
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
2786 __ bind(&null); 2790 __ bind(&null);
2787 __ LoadRoot(r0, Heap::kNullValueRootIndex); 2791 __ LoadRoot(r0, Heap::kNullValueRootIndex);
2788 2792
2789 // All done. 2793 // All done.
2790 __ bind(&done); 2794 __ bind(&done);
2791 2795
2792 context()->Plug(r0); 2796 context()->Plug(r0);
2793 } 2797 }
2794 2798
2795 2799
2796 void FullCodeGenerator::EmitLog(ZoneList<Expression*>* args) { 2800 void FullCodeGenerator::EmitLog(CallRuntime* expr) {
2797 // Conditionally generate a log call. 2801 // Conditionally generate a log call.
2798 // Args: 2802 // Args:
2799 // 0 (literal string): The type of logging (corresponds to the flags). 2803 // 0 (literal string): The type of logging (corresponds to the flags).
2800 // This is used to determine whether or not to generate the log call. 2804 // This is used to determine whether or not to generate the log call.
2801 // 1 (string): Format string. Access the string at argument index 2 2805 // 1 (string): Format string. Access the string at argument index 2
2802 // with '%2s' (see Logger::LogRuntime for all the formats). 2806 // with '%2s' (see Logger::LogRuntime for all the formats).
2803 // 2 (array): Arguments to the format string. 2807 // 2 (array): Arguments to the format string.
2808 ZoneList<Expression*>* args = expr->arguments();
2804 ASSERT_EQ(args->length(), 3); 2809 ASSERT_EQ(args->length(), 3);
2805 if (CodeGenerator::ShouldGenerateLog(args->at(0))) { 2810 if (CodeGenerator::ShouldGenerateLog(args->at(0))) {
2806 VisitForStackValue(args->at(1)); 2811 VisitForStackValue(args->at(1));
2807 VisitForStackValue(args->at(2)); 2812 VisitForStackValue(args->at(2));
2808 __ CallRuntime(Runtime::kLog, 2); 2813 __ CallRuntime(Runtime::kLog, 2);
2809 } 2814 }
2810 2815
2811 // Finally, we're expected to leave a value on the top of the stack. 2816 // Finally, we're expected to leave a value on the top of the stack.
2812 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); 2817 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
2813 context()->Plug(r0); 2818 context()->Plug(r0);
2814 } 2819 }
2815 2820
2816 2821
2817 void FullCodeGenerator::EmitRandomHeapNumber(ZoneList<Expression*>* args) { 2822 void FullCodeGenerator::EmitRandomHeapNumber(CallRuntime* expr) {
2818 ASSERT(args->length() == 0); 2823 ASSERT(expr->arguments()->length() == 0);
2819
2820 Label slow_allocate_heapnumber; 2824 Label slow_allocate_heapnumber;
2821 Label heapnumber_allocated; 2825 Label heapnumber_allocated;
2822 2826
2823 __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); 2827 __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex);
2824 __ AllocateHeapNumber(r4, r1, r2, r6, &slow_allocate_heapnumber); 2828 __ AllocateHeapNumber(r4, r1, r2, r6, &slow_allocate_heapnumber);
2825 __ jmp(&heapnumber_allocated); 2829 __ jmp(&heapnumber_allocated);
2826 2830
2827 __ bind(&slow_allocate_heapnumber); 2831 __ bind(&slow_allocate_heapnumber);
2828 // Allocate a heap number. 2832 // Allocate a heap number.
2829 __ CallRuntime(Runtime::kNumberAlloc, 0); 2833 __ CallRuntime(Runtime::kNumberAlloc, 0);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
2861 __ mov(r0, Operand(r4)); 2865 __ mov(r0, Operand(r4));
2862 __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalContextOffset)); 2866 __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalContextOffset));
2863 __ CallCFunction( 2867 __ CallCFunction(
2864 ExternalReference::fill_heap_number_with_random_function(isolate()), 2); 2868 ExternalReference::fill_heap_number_with_random_function(isolate()), 2);
2865 } 2869 }
2866 2870
2867 context()->Plug(r0); 2871 context()->Plug(r0);
2868 } 2872 }
2869 2873
2870 2874
2871 void FullCodeGenerator::EmitSubString(ZoneList<Expression*>* args) { 2875 void FullCodeGenerator::EmitSubString(CallRuntime* expr) {
2872 // Load the arguments on the stack and call the stub. 2876 // Load the arguments on the stack and call the stub.
2873 SubStringStub stub; 2877 SubStringStub stub;
2878 ZoneList<Expression*>* args = expr->arguments();
2874 ASSERT(args->length() == 3); 2879 ASSERT(args->length() == 3);
2875 VisitForStackValue(args->at(0)); 2880 VisitForStackValue(args->at(0));
2876 VisitForStackValue(args->at(1)); 2881 VisitForStackValue(args->at(1));
2877 VisitForStackValue(args->at(2)); 2882 VisitForStackValue(args->at(2));
2878 __ CallStub(&stub); 2883 __ CallStub(&stub);
2879 context()->Plug(r0); 2884 context()->Plug(r0);
2880 } 2885 }
2881 2886
2882 2887
2883 void FullCodeGenerator::EmitRegExpExec(ZoneList<Expression*>* args) { 2888 void FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) {
2884 // Load the arguments on the stack and call the stub. 2889 // Load the arguments on the stack and call the stub.
2885 RegExpExecStub stub; 2890 RegExpExecStub stub;
2891 ZoneList<Expression*>* args = expr->arguments();
2886 ASSERT(args->length() == 4); 2892 ASSERT(args->length() == 4);
2887 VisitForStackValue(args->at(0)); 2893 VisitForStackValue(args->at(0));
2888 VisitForStackValue(args->at(1)); 2894 VisitForStackValue(args->at(1));
2889 VisitForStackValue(args->at(2)); 2895 VisitForStackValue(args->at(2));
2890 VisitForStackValue(args->at(3)); 2896 VisitForStackValue(args->at(3));
2891 __ CallStub(&stub); 2897 __ CallStub(&stub);
2892 context()->Plug(r0); 2898 context()->Plug(r0);
2893 } 2899 }
2894 2900
2895 2901
2896 void FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) { 2902 void FullCodeGenerator::EmitValueOf(CallRuntime* expr) {
2903 ZoneList<Expression*>* args = expr->arguments();
2897 ASSERT(args->length() == 1); 2904 ASSERT(args->length() == 1);
2898
2899 VisitForAccumulatorValue(args->at(0)); // Load the object. 2905 VisitForAccumulatorValue(args->at(0)); // Load the object.
2900 2906
2901 Label done; 2907 Label done;
2902 // If the object is a smi return the object. 2908 // If the object is a smi return the object.
2903 __ JumpIfSmi(r0, &done); 2909 __ JumpIfSmi(r0, &done);
2904 // If the object is not a value type, return the object. 2910 // If the object is not a value type, return the object.
2905 __ CompareObjectType(r0, r1, r1, JS_VALUE_TYPE); 2911 __ CompareObjectType(r0, r1, r1, JS_VALUE_TYPE);
2906 __ b(ne, &done); 2912 __ b(ne, &done);
2907 __ ldr(r0, FieldMemOperand(r0, JSValue::kValueOffset)); 2913 __ ldr(r0, FieldMemOperand(r0, JSValue::kValueOffset));
2908 2914
2909 __ bind(&done); 2915 __ bind(&done);
2910 context()->Plug(r0); 2916 context()->Plug(r0);
2911 } 2917 }
2912 2918
2913 2919
2914 void FullCodeGenerator::EmitMathPow(ZoneList<Expression*>* args) { 2920 void FullCodeGenerator::EmitMathPow(CallRuntime* expr) {
2915 // Load the arguments on the stack and call the runtime function. 2921 // Load the arguments on the stack and call the runtime function.
2922 ZoneList<Expression*>* args = expr->arguments();
2916 ASSERT(args->length() == 2); 2923 ASSERT(args->length() == 2);
2917 VisitForStackValue(args->at(0)); 2924 VisitForStackValue(args->at(0));
2918 VisitForStackValue(args->at(1)); 2925 VisitForStackValue(args->at(1));
2919 MathPowStub stub; 2926 MathPowStub stub;
2920 __ CallStub(&stub); 2927 __ CallStub(&stub);
2921 context()->Plug(r0); 2928 context()->Plug(r0);
2922 } 2929 }
2923 2930
2924 2931
2925 void FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) { 2932 void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) {
2933 ZoneList<Expression*>* args = expr->arguments();
2926 ASSERT(args->length() == 2); 2934 ASSERT(args->length() == 2);
2927
2928 VisitForStackValue(args->at(0)); // Load the object. 2935 VisitForStackValue(args->at(0)); // Load the object.
2929 VisitForAccumulatorValue(args->at(1)); // Load the value. 2936 VisitForAccumulatorValue(args->at(1)); // Load the value.
2930 __ pop(r1); // r0 = value. r1 = object. 2937 __ pop(r1); // r0 = value. r1 = object.
2931 2938
2932 Label done; 2939 Label done;
2933 // If the object is a smi, return the value. 2940 // If the object is a smi, return the value.
2934 __ JumpIfSmi(r1, &done); 2941 __ JumpIfSmi(r1, &done);
2935 2942
2936 // If the object is not a value type, return the value. 2943 // If the object is not a value type, return the value.
2937 __ CompareObjectType(r1, r2, r2, JS_VALUE_TYPE); 2944 __ CompareObjectType(r1, r2, r2, JS_VALUE_TYPE);
2938 __ b(ne, &done); 2945 __ b(ne, &done);
2939 2946
2940 // Store the value. 2947 // Store the value.
2941 __ str(r0, FieldMemOperand(r1, JSValue::kValueOffset)); 2948 __ str(r0, FieldMemOperand(r1, JSValue::kValueOffset));
2942 // Update the write barrier. Save the value as it will be 2949 // Update the write barrier. Save the value as it will be
2943 // overwritten by the write barrier code and is needed afterward. 2950 // overwritten by the write barrier code and is needed afterward.
2944 __ mov(r2, r0); 2951 __ mov(r2, r0);
2945 __ RecordWriteField( 2952 __ RecordWriteField(
2946 r1, JSValue::kValueOffset, r2, r3, kLRHasBeenSaved, kDontSaveFPRegs); 2953 r1, JSValue::kValueOffset, r2, r3, kLRHasBeenSaved, kDontSaveFPRegs);
2947 2954
2948 __ bind(&done); 2955 __ bind(&done);
2949 context()->Plug(r0); 2956 context()->Plug(r0);
2950 } 2957 }
2951 2958
2952 2959
2953 void FullCodeGenerator::EmitNumberToString(ZoneList<Expression*>* args) { 2960 void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
2961 ZoneList<Expression*>* args = expr->arguments();
2954 ASSERT_EQ(args->length(), 1); 2962 ASSERT_EQ(args->length(), 1);
2955
2956 // Load the argument on the stack and call the stub. 2963 // Load the argument on the stack and call the stub.
2957 VisitForStackValue(args->at(0)); 2964 VisitForStackValue(args->at(0));
2958 2965
2959 NumberToStringStub stub; 2966 NumberToStringStub stub;
2960 __ CallStub(&stub); 2967 __ CallStub(&stub);
2961 context()->Plug(r0); 2968 context()->Plug(r0);
2962 } 2969 }
2963 2970
2964 2971
2965 void FullCodeGenerator::EmitStringCharFromCode(ZoneList<Expression*>* args) { 2972 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
2973 ZoneList<Expression*>* args = expr->arguments();
2966 ASSERT(args->length() == 1); 2974 ASSERT(args->length() == 1);
2967
2968 VisitForAccumulatorValue(args->at(0)); 2975 VisitForAccumulatorValue(args->at(0));
2969 2976
2970 Label done; 2977 Label done;
2971 StringCharFromCodeGenerator generator(r0, r1); 2978 StringCharFromCodeGenerator generator(r0, r1);
2972 generator.GenerateFast(masm_); 2979 generator.GenerateFast(masm_);
2973 __ jmp(&done); 2980 __ jmp(&done);
2974 2981
2975 NopRuntimeCallHelper call_helper; 2982 NopRuntimeCallHelper call_helper;
2976 generator.GenerateSlow(masm_, call_helper); 2983 generator.GenerateSlow(masm_, call_helper);
2977 2984
2978 __ bind(&done); 2985 __ bind(&done);
2979 context()->Plug(r1); 2986 context()->Plug(r1);
2980 } 2987 }
2981 2988
2982 2989
2983 void FullCodeGenerator::EmitStringCharCodeAt(ZoneList<Expression*>* args) { 2990 void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) {
2991 ZoneList<Expression*>* args = expr->arguments();
2984 ASSERT(args->length() == 2); 2992 ASSERT(args->length() == 2);
2985
2986 VisitForStackValue(args->at(0)); 2993 VisitForStackValue(args->at(0));
2987 VisitForAccumulatorValue(args->at(1)); 2994 VisitForAccumulatorValue(args->at(1));
2988 2995
2989 Register object = r1; 2996 Register object = r1;
2990 Register index = r0; 2997 Register index = r0;
2991 Register scratch = r2; 2998 Register scratch = r2;
2992 Register result = r3; 2999 Register result = r3;
2993 3000
2994 __ pop(object); 3001 __ pop(object);
2995 3002
(...skipping 24 matching lines...) Expand all
3020 __ jmp(&done); 3027 __ jmp(&done);
3021 3028
3022 NopRuntimeCallHelper call_helper; 3029 NopRuntimeCallHelper call_helper;
3023 generator.GenerateSlow(masm_, call_helper); 3030 generator.GenerateSlow(masm_, call_helper);
3024 3031
3025 __ bind(&done); 3032 __ bind(&done);
3026 context()->Plug(result); 3033 context()->Plug(result);
3027 } 3034 }
3028 3035
3029 3036
3030 void FullCodeGenerator::EmitStringCharAt(ZoneList<Expression*>* args) { 3037 void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) {
3038 ZoneList<Expression*>* args = expr->arguments();
3031 ASSERT(args->length() == 2); 3039 ASSERT(args->length() == 2);
3032
3033 VisitForStackValue(args->at(0)); 3040 VisitForStackValue(args->at(0));
3034 VisitForAccumulatorValue(args->at(1)); 3041 VisitForAccumulatorValue(args->at(1));
3035 3042
3036 Register object = r1; 3043 Register object = r1;
3037 Register index = r0; 3044 Register index = r0;
3038 Register scratch1 = r2; 3045 Register scratch1 = r2;
3039 Register scratch2 = r3; 3046 Register scratch2 = r3;
3040 Register result = r0; 3047 Register result = r0;
3041 3048
3042 __ pop(object); 3049 __ pop(object);
(...skipping 26 matching lines...) Expand all
3069 __ jmp(&done); 3076 __ jmp(&done);
3070 3077
3071 NopRuntimeCallHelper call_helper; 3078 NopRuntimeCallHelper call_helper;
3072 generator.GenerateSlow(masm_, call_helper); 3079 generator.GenerateSlow(masm_, call_helper);
3073 3080
3074 __ bind(&done); 3081 __ bind(&done);
3075 context()->Plug(result); 3082 context()->Plug(result);
3076 } 3083 }
3077 3084
3078 3085
3079 void FullCodeGenerator::EmitStringAdd(ZoneList<Expression*>* args) { 3086 void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) {
3087 ZoneList<Expression*>* args = expr->arguments();
3080 ASSERT_EQ(2, args->length()); 3088 ASSERT_EQ(2, args->length());
3081
3082 VisitForStackValue(args->at(0)); 3089 VisitForStackValue(args->at(0));
3083 VisitForStackValue(args->at(1)); 3090 VisitForStackValue(args->at(1));
3084 3091
3085 StringAddStub stub(NO_STRING_ADD_FLAGS); 3092 StringAddStub stub(NO_STRING_ADD_FLAGS);
3086 __ CallStub(&stub); 3093 __ CallStub(&stub);
3087 context()->Plug(r0); 3094 context()->Plug(r0);
3088 } 3095 }
3089 3096
3090 3097
3091 void FullCodeGenerator::EmitStringCompare(ZoneList<Expression*>* args) { 3098 void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) {
3099 ZoneList<Expression*>* args = expr->arguments();
3092 ASSERT_EQ(2, args->length()); 3100 ASSERT_EQ(2, args->length());
3093
3094 VisitForStackValue(args->at(0)); 3101 VisitForStackValue(args->at(0));
3095 VisitForStackValue(args->at(1)); 3102 VisitForStackValue(args->at(1));
3096 3103
3097 StringCompareStub stub; 3104 StringCompareStub stub;
3098 __ CallStub(&stub); 3105 __ CallStub(&stub);
3099 context()->Plug(r0); 3106 context()->Plug(r0);
3100 } 3107 }
3101 3108
3102 3109
3103 void FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) { 3110 void FullCodeGenerator::EmitMathSin(CallRuntime* expr) {
3104 // Load the argument on the stack and call the stub. 3111 // Load the argument on the stack and call the stub.
3105 TranscendentalCacheStub stub(TranscendentalCache::SIN, 3112 TranscendentalCacheStub stub(TranscendentalCache::SIN,
3106 TranscendentalCacheStub::TAGGED); 3113 TranscendentalCacheStub::TAGGED);
3114 ZoneList<Expression*>* args = expr->arguments();
3107 ASSERT(args->length() == 1); 3115 ASSERT(args->length() == 1);
3108 VisitForStackValue(args->at(0)); 3116 VisitForStackValue(args->at(0));
3109 __ CallStub(&stub); 3117 __ CallStub(&stub);
3110 context()->Plug(r0); 3118 context()->Plug(r0);
3111 } 3119 }
3112 3120
3113 3121
3114 void FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) { 3122 void FullCodeGenerator::EmitMathCos(CallRuntime* expr) {
3115 // Load the argument on the stack and call the stub. 3123 // Load the argument on the stack and call the stub.
3116 TranscendentalCacheStub stub(TranscendentalCache::COS, 3124 TranscendentalCacheStub stub(TranscendentalCache::COS,
3117 TranscendentalCacheStub::TAGGED); 3125 TranscendentalCacheStub::TAGGED);
3126 ZoneList<Expression*>* args = expr->arguments();
3118 ASSERT(args->length() == 1); 3127 ASSERT(args->length() == 1);
3119 VisitForStackValue(args->at(0)); 3128 VisitForStackValue(args->at(0));
3120 __ CallStub(&stub); 3129 __ CallStub(&stub);
3121 context()->Plug(r0); 3130 context()->Plug(r0);
3122 } 3131 }
3123 3132
3124 3133
3125 void FullCodeGenerator::EmitMathLog(ZoneList<Expression*>* args) { 3134 void FullCodeGenerator::EmitMathLog(CallRuntime* expr) {
3126 // Load the argument on the stack and call the stub. 3135 // Load the argument on the stack and call the stub.
3127 TranscendentalCacheStub stub(TranscendentalCache::LOG, 3136 TranscendentalCacheStub stub(TranscendentalCache::LOG,
3128 TranscendentalCacheStub::TAGGED); 3137 TranscendentalCacheStub::TAGGED);
3138 ZoneList<Expression*>* args = expr->arguments();
3129 ASSERT(args->length() == 1); 3139 ASSERT(args->length() == 1);
3130 VisitForStackValue(args->at(0)); 3140 VisitForStackValue(args->at(0));
3131 __ CallStub(&stub); 3141 __ CallStub(&stub);
3132 context()->Plug(r0); 3142 context()->Plug(r0);
3133 } 3143 }
3134 3144
3135 3145
3136 void FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) { 3146 void FullCodeGenerator::EmitMathSqrt(CallRuntime* expr) {
3137 // Load the argument on the stack and call the runtime function. 3147 // Load the argument on the stack and call the runtime function.
3148 ZoneList<Expression*>* args = expr->arguments();
3138 ASSERT(args->length() == 1); 3149 ASSERT(args->length() == 1);
3139 VisitForStackValue(args->at(0)); 3150 VisitForStackValue(args->at(0));
3140 __ CallRuntime(Runtime::kMath_sqrt, 1); 3151 __ CallRuntime(Runtime::kMath_sqrt, 1);
3141 context()->Plug(r0); 3152 context()->Plug(r0);
3142 } 3153 }
3143 3154
3144 3155
3145 void FullCodeGenerator::EmitCallFunction(ZoneList<Expression*>* args) { 3156 void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
3157 ZoneList<Expression*>* args = expr->arguments();
3146 ASSERT(args->length() >= 2); 3158 ASSERT(args->length() >= 2);
3147 3159
3148 int arg_count = args->length() - 2; // 2 ~ receiver and function. 3160 int arg_count = args->length() - 2; // 2 ~ receiver and function.
3149 for (int i = 0; i < arg_count + 1; i++) { 3161 for (int i = 0; i < arg_count + 1; i++) {
3150 VisitForStackValue(args->at(i)); 3162 VisitForStackValue(args->at(i));
3151 } 3163 }
3152 VisitForAccumulatorValue(args->last()); // Function. 3164 VisitForAccumulatorValue(args->last()); // Function.
3153 3165
3154 // InvokeFunction requires the function in r1. Move it in there. 3166 // InvokeFunction requires the function in r1. Move it in there.
3155 __ mov(r1, result_register()); 3167 __ mov(r1, result_register());
3156 ParameterCount count(arg_count); 3168 ParameterCount count(arg_count);
3157 __ InvokeFunction(r1, count, CALL_FUNCTION, 3169 __ InvokeFunction(r1, count, CALL_FUNCTION,
3158 NullCallWrapper(), CALL_AS_METHOD); 3170 NullCallWrapper(), CALL_AS_METHOD);
3159 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 3171 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
3160 context()->Plug(r0); 3172 context()->Plug(r0);
3161 } 3173 }
3162 3174
3163 3175
3164 void FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) { 3176 void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) {
3165 RegExpConstructResultStub stub; 3177 RegExpConstructResultStub stub;
3178 ZoneList<Expression*>* args = expr->arguments();
3166 ASSERT(args->length() == 3); 3179 ASSERT(args->length() == 3);
3167 VisitForStackValue(args->at(0)); 3180 VisitForStackValue(args->at(0));
3168 VisitForStackValue(args->at(1)); 3181 VisitForStackValue(args->at(1));
3169 VisitForStackValue(args->at(2)); 3182 VisitForStackValue(args->at(2));
3170 __ CallStub(&stub); 3183 __ CallStub(&stub);
3171 context()->Plug(r0); 3184 context()->Plug(r0);
3172 } 3185 }
3173 3186
3174 3187
3175 void FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) { 3188 void FullCodeGenerator::EmitSwapElements(CallRuntime* expr) {
3189 ZoneList<Expression*>* args = expr->arguments();
3176 ASSERT(args->length() == 3); 3190 ASSERT(args->length() == 3);
3177 VisitForStackValue(args->at(0)); 3191 VisitForStackValue(args->at(0));
3178 VisitForStackValue(args->at(1)); 3192 VisitForStackValue(args->at(1));
3179 VisitForStackValue(args->at(2)); 3193 VisitForStackValue(args->at(2));
3180 Label done; 3194 Label done;
3181 Label slow_case; 3195 Label slow_case;
3182 Register object = r0; 3196 Register object = r0;
3183 Register index1 = r1; 3197 Register index1 = r1;
3184 Register index2 = r2; 3198 Register index2 = r2;
3185 Register elements = r3; 3199 Register elements = r3;
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
3262 __ jmp(&done); 3276 __ jmp(&done);
3263 3277
3264 __ bind(&slow_case); 3278 __ bind(&slow_case);
3265 __ CallRuntime(Runtime::kSwapElements, 3); 3279 __ CallRuntime(Runtime::kSwapElements, 3);
3266 3280
3267 __ bind(&done); 3281 __ bind(&done);
3268 context()->Plug(r0); 3282 context()->Plug(r0);
3269 } 3283 }
3270 3284
3271 3285
3272 void FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) { 3286 void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) {
3287 ZoneList<Expression*>* args = expr->arguments();
3273 ASSERT_EQ(2, args->length()); 3288 ASSERT_EQ(2, args->length());
3274
3275 ASSERT_NE(NULL, args->at(0)->AsLiteral()); 3289 ASSERT_NE(NULL, args->at(0)->AsLiteral());
3276 int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value(); 3290 int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value();
3277 3291
3278 Handle<FixedArray> jsfunction_result_caches( 3292 Handle<FixedArray> jsfunction_result_caches(
3279 isolate()->global_context()->jsfunction_result_caches()); 3293 isolate()->global_context()->jsfunction_result_caches());
3280 if (jsfunction_result_caches->length() <= cache_id) { 3294 if (jsfunction_result_caches->length() <= cache_id) {
3281 __ Abort("Attempt to use undefined cache."); 3295 __ Abort("Attempt to use undefined cache.");
3282 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); 3296 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
3283 context()->Plug(r0); 3297 context()->Plug(r0);
3284 return; 3298 return;
(...skipping 28 matching lines...) Expand all
3313 __ bind(&not_found); 3327 __ bind(&not_found);
3314 // Call runtime to perform the lookup. 3328 // Call runtime to perform the lookup.
3315 __ Push(cache, key); 3329 __ Push(cache, key);
3316 __ CallRuntime(Runtime::kGetFromCache, 2); 3330 __ CallRuntime(Runtime::kGetFromCache, 2);
3317 3331
3318 __ bind(&done); 3332 __ bind(&done);
3319 context()->Plug(r0); 3333 context()->Plug(r0);
3320 } 3334 }
3321 3335
3322 3336
3323 void FullCodeGenerator::EmitIsRegExpEquivalent(ZoneList<Expression*>* args) { 3337 void FullCodeGenerator::EmitIsRegExpEquivalent(CallRuntime* expr) {
3338 ZoneList<Expression*>* args = expr->arguments();
3324 ASSERT_EQ(2, args->length()); 3339 ASSERT_EQ(2, args->length());
3325 3340
3326 Register right = r0; 3341 Register right = r0;
3327 Register left = r1; 3342 Register left = r1;
3328 Register tmp = r2; 3343 Register tmp = r2;
3329 Register tmp2 = r3; 3344 Register tmp2 = r3;
3330 3345
3331 VisitForStackValue(args->at(0)); 3346 VisitForStackValue(args->at(0));
3332 VisitForAccumulatorValue(args->at(1)); 3347 VisitForAccumulatorValue(args->at(1));
3333 __ pop(left); 3348 __ pop(left);
(...skipping 19 matching lines...) Expand all
3353 __ LoadRoot(r0, Heap::kFalseValueRootIndex); 3368 __ LoadRoot(r0, Heap::kFalseValueRootIndex);
3354 __ jmp(&done); 3369 __ jmp(&done);
3355 __ bind(&ok); 3370 __ bind(&ok);
3356 __ LoadRoot(r0, Heap::kTrueValueRootIndex); 3371 __ LoadRoot(r0, Heap::kTrueValueRootIndex);
3357 __ bind(&done); 3372 __ bind(&done);
3358 3373
3359 context()->Plug(r0); 3374 context()->Plug(r0);
3360 } 3375 }
3361 3376
3362 3377
3363 void FullCodeGenerator::EmitHasCachedArrayIndex(ZoneList<Expression*>* args) { 3378 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) {
3379 ZoneList<Expression*>* args = expr->arguments();
3364 VisitForAccumulatorValue(args->at(0)); 3380 VisitForAccumulatorValue(args->at(0));
3365 3381
3366 Label materialize_true, materialize_false; 3382 Label materialize_true, materialize_false;
3367 Label* if_true = NULL; 3383 Label* if_true = NULL;
3368 Label* if_false = NULL; 3384 Label* if_false = NULL;
3369 Label* fall_through = NULL; 3385 Label* fall_through = NULL;
3370 context()->PrepareTest(&materialize_true, &materialize_false, 3386 context()->PrepareTest(&materialize_true, &materialize_false,
3371 &if_true, &if_false, &fall_through); 3387 &if_true, &if_false, &fall_through);
3372 3388
3373 __ ldr(r0, FieldMemOperand(r0, String::kHashFieldOffset)); 3389 __ ldr(r0, FieldMemOperand(r0, String::kHashFieldOffset));
3374 __ tst(r0, Operand(String::kContainsCachedArrayIndexMask)); 3390 __ tst(r0, Operand(String::kContainsCachedArrayIndexMask));
3375 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 3391 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3376 Split(eq, if_true, if_false, fall_through); 3392 Split(eq, if_true, if_false, fall_through);
3377 3393
3378 context()->Plug(if_true, if_false); 3394 context()->Plug(if_true, if_false);
3379 } 3395 }
3380 3396
3381 3397
3382 void FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList<Expression*>* args) { 3398 void FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) {
3399 ZoneList<Expression*>* args = expr->arguments();
3383 ASSERT(args->length() == 1); 3400 ASSERT(args->length() == 1);
3384 VisitForAccumulatorValue(args->at(0)); 3401 VisitForAccumulatorValue(args->at(0));
3385 3402
3386 if (FLAG_debug_code) { 3403 if (FLAG_debug_code) {
3387 __ AbortIfNotString(r0); 3404 __ AbortIfNotString(r0);
3388 } 3405 }
3389 3406
3390 __ ldr(r0, FieldMemOperand(r0, String::kHashFieldOffset)); 3407 __ ldr(r0, FieldMemOperand(r0, String::kHashFieldOffset));
3391 __ IndexFromHash(r0, r0); 3408 __ IndexFromHash(r0, r0);
3392 3409
3393 context()->Plug(r0); 3410 context()->Plug(r0);
3394 } 3411 }
3395 3412
3396 3413
3397 void FullCodeGenerator::EmitFastAsciiArrayJoin(ZoneList<Expression*>* args) { 3414 void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) {
3398 Label bailout, done, one_char_separator, long_separator, 3415 Label bailout, done, one_char_separator, long_separator,
3399 non_trivial_array, not_size_one_array, loop, 3416 non_trivial_array, not_size_one_array, loop,
3400 empty_separator_loop, one_char_separator_loop, 3417 empty_separator_loop, one_char_separator_loop,
3401 one_char_separator_loop_entry, long_separator_loop; 3418 one_char_separator_loop_entry, long_separator_loop;
3402 3419 ZoneList<Expression*>* args = expr->arguments();
3403 ASSERT(args->length() == 2); 3420 ASSERT(args->length() == 2);
3404 VisitForStackValue(args->at(1)); 3421 VisitForStackValue(args->at(1));
3405 VisitForAccumulatorValue(args->at(0)); 3422 VisitForAccumulatorValue(args->at(0));
3406 3423
3407 // All aliases of the same register have disjoint lifetimes. 3424 // All aliases of the same register have disjoint lifetimes.
3408 Register array = r0; 3425 Register array = r0;
3409 Register elements = no_reg; // Will be r0. 3426 Register elements = no_reg; // Will be r0.
3410 Register result = no_reg; // Will be r0. 3427 Register result = no_reg; // Will be r0.
3411 Register separator = r1; 3428 Register separator = r1;
3412 Register array_length = r2; 3429 Register array_length = r2;
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after
3720 context()->Plug(Heap::kUndefinedValueRootIndex); 3737 context()->Plug(Heap::kUndefinedValueRootIndex);
3721 break; 3738 break;
3722 } 3739 }
3723 3740
3724 case Token::NOT: { 3741 case Token::NOT: {
3725 Comment cmnt(masm_, "[ UnaryOperation (NOT)"); 3742 Comment cmnt(masm_, "[ UnaryOperation (NOT)");
3726 if (context()->IsEffect()) { 3743 if (context()->IsEffect()) {
3727 // Unary NOT has no side effects so it's only necessary to visit the 3744 // Unary NOT has no side effects so it's only necessary to visit the
3728 // subexpression. Match the optimizing compiler by not branching. 3745 // subexpression. Match the optimizing compiler by not branching.
3729 VisitForEffect(expr->expression()); 3746 VisitForEffect(expr->expression());
3747 } else if (context()->IsTest()) {
3748 const TestContext* test = TestContext::cast(context());
3749 // The labels are swapped for the recursive call.
3750 VisitForControl(expr->expression(),
3751 test->false_label(),
3752 test->true_label(),
3753 test->fall_through());
3754 context()->Plug(test->true_label(), test->false_label());
3730 } else { 3755 } else {
3731 Label materialize_true, materialize_false; 3756 // We handle value contexts explicitly rather than simply visiting
3732 Label* if_true = NULL; 3757 // for control and plugging the control flow into the context,
3733 Label* if_false = NULL; 3758 // because we need to prepare a pair of extra administrative AST ids
3734 Label* fall_through = NULL; 3759 // for the optimizing compiler.
3735 3760 ASSERT(context()->IsAccumulatorValue() || context()->IsStackValue());
3736 // Notice that the labels are swapped. 3761 Label materialize_true, materialize_false, done;
3737 context()->PrepareTest(&materialize_true, &materialize_false, 3762 VisitForControl(expr->expression(),
3738 &if_false, &if_true, &fall_through); 3763 &materialize_false,
3739 if (context()->IsTest()) ForwardBailoutToChild(expr); 3764 &materialize_true,
3740 VisitForControl(expr->expression(), if_true, if_false, fall_through); 3765 &materialize_true);
3741 context()->Plug(if_false, if_true); // Labels swapped. 3766 __ bind(&materialize_true);
3767 PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS);
3768 __ LoadRoot(r0, Heap::kTrueValueRootIndex);
3769 if (context()->IsStackValue()) __ push(r0);
3770 __ jmp(&done);
3771 __ bind(&materialize_false);
3772 PrepareForBailoutForId(expr->MaterializeFalseId(), NO_REGISTERS);
3773 __ LoadRoot(r0, Heap::kFalseValueRootIndex);
3774 if (context()->IsStackValue()) __ push(r0);
3775 __ bind(&done);
3742 } 3776 }
3743 break; 3777 break;
3744 } 3778 }
3745 3779
3746 case Token::TYPEOF: { 3780 case Token::TYPEOF: {
3747 Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); 3781 Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
3748 { StackValueContext context(this); 3782 { StackValueContext context(this);
3749 VisitForTypeofValue(expr->expression()); 3783 VisitForTypeofValue(expr->expression());
3750 } 3784 }
3751 __ CallRuntime(Runtime::kTypeof, 1); 3785 __ CallRuntime(Runtime::kTypeof, 1);
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after
3990 __ bind(&slow); 4024 __ bind(&slow);
3991 __ mov(r0, Operand(proxy->name())); 4025 __ mov(r0, Operand(proxy->name()));
3992 __ Push(cp, r0); 4026 __ Push(cp, r0);
3993 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); 4027 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
3994 PrepareForBailout(expr, TOS_REG); 4028 PrepareForBailout(expr, TOS_REG);
3995 __ bind(&done); 4029 __ bind(&done);
3996 4030
3997 context()->Plug(r0); 4031 context()->Plug(r0);
3998 } else { 4032 } else {
3999 // This expression cannot throw a reference error at the top level. 4033 // This expression cannot throw a reference error at the top level.
4000 VisitInCurrentContext(expr); 4034 VisitInDuplicateContext(expr);
4001 } 4035 }
4002 } 4036 }
4003 4037
4004 4038
4005 void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr, 4039 void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
4040 Expression* sub_expr,
4006 Handle<String> check) { 4041 Handle<String> check) {
4007 Label materialize_true, materialize_false; 4042 Label materialize_true, materialize_false;
4008 Label* if_true = NULL; 4043 Label* if_true = NULL;
4009 Label* if_false = NULL; 4044 Label* if_false = NULL;
4010 Label* fall_through = NULL; 4045 Label* fall_through = NULL;
4011 context()->PrepareTest(&materialize_true, &materialize_false, 4046 context()->PrepareTest(&materialize_true, &materialize_false,
4012 &if_true, &if_false, &fall_through); 4047 &if_true, &if_false, &fall_through);
4013 4048
4014 { AccumulatorValueContext context(this); 4049 { AccumulatorValueContext context(this);
4015 VisitForTypeofValue(expr); 4050 VisitForTypeofValue(sub_expr);
4016 } 4051 }
4017 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 4052 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
4018 4053
4019 if (check->Equals(isolate()->heap()->number_symbol())) { 4054 if (check->Equals(isolate()->heap()->number_symbol())) {
4020 __ JumpIfSmi(r0, if_true); 4055 __ JumpIfSmi(r0, if_true);
4021 __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset)); 4056 __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
4022 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); 4057 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
4023 __ cmp(r0, ip); 4058 __ cmp(r0, ip);
4024 Split(eq, if_true, if_false, fall_through); 4059 Split(eq, if_true, if_false, fall_through);
4025 } else if (check->Equals(isolate()->heap()->string_symbol())) { 4060 } else if (check->Equals(isolate()->heap()->string_symbol())) {
4026 __ JumpIfSmi(r0, if_false); 4061 __ JumpIfSmi(r0, if_false);
4027 // Check for undetectable objects => false. 4062 // Check for undetectable objects => false.
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
4094 Label* fall_through = NULL; 4129 Label* fall_through = NULL;
4095 context()->PrepareTest(&materialize_true, &materialize_false, 4130 context()->PrepareTest(&materialize_true, &materialize_false,
4096 &if_true, &if_false, &fall_through); 4131 &if_true, &if_false, &fall_through);
4097 4132
4098 Token::Value op = expr->op(); 4133 Token::Value op = expr->op();
4099 VisitForStackValue(expr->left()); 4134 VisitForStackValue(expr->left());
4100 switch (op) { 4135 switch (op) {
4101 case Token::IN: 4136 case Token::IN:
4102 VisitForStackValue(expr->right()); 4137 VisitForStackValue(expr->right());
4103 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); 4138 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
4104 PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); 4139 PrepareForBailoutBeforeSplit(expr, false, NULL, NULL);
4105 __ LoadRoot(ip, Heap::kTrueValueRootIndex); 4140 __ LoadRoot(ip, Heap::kTrueValueRootIndex);
4106 __ cmp(r0, ip); 4141 __ cmp(r0, ip);
4107 Split(eq, if_true, if_false, fall_through); 4142 Split(eq, if_true, if_false, fall_through);
4108 break; 4143 break;
4109 4144
4110 case Token::INSTANCEOF: { 4145 case Token::INSTANCEOF: {
4111 VisitForStackValue(expr->right()); 4146 VisitForStackValue(expr->right());
4112 InstanceofStub stub(InstanceofStub::kNoFlags); 4147 InstanceofStub stub(InstanceofStub::kNoFlags);
4113 __ CallStub(&stub); 4148 __ CallStub(&stub);
4114 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 4149 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
4115 // The stub returns 0 for true. 4150 // The stub returns 0 for true.
4116 __ tst(r0, r0); 4151 __ tst(r0, r0);
4117 Split(eq, if_true, if_false, fall_through); 4152 Split(eq, if_true, if_false, fall_through);
4118 break; 4153 break;
4119 } 4154 }
4120 4155
4121 default: { 4156 default: {
4122 VisitForAccumulatorValue(expr->right()); 4157 VisitForAccumulatorValue(expr->right());
4123 Condition cond = eq; 4158 Condition cond = eq;
4124 switch (op) { 4159 switch (op) {
(...skipping 29 matching lines...) Expand all
4154 __ cmp(r1, r0); 4189 __ cmp(r1, r0);
4155 Split(cond, if_true, if_false, NULL); 4190 Split(cond, if_true, if_false, NULL);
4156 __ bind(&slow_case); 4191 __ bind(&slow_case);
4157 } 4192 }
4158 4193
4159 // Record position and call the compare IC. 4194 // Record position and call the compare IC.
4160 SetSourcePosition(expr->position()); 4195 SetSourcePosition(expr->position());
4161 Handle<Code> ic = CompareIC::GetUninitialized(op); 4196 Handle<Code> ic = CompareIC::GetUninitialized(op);
4162 __ Call(ic, RelocInfo::CODE_TARGET, expr->id()); 4197 __ Call(ic, RelocInfo::CODE_TARGET, expr->id());
4163 patch_site.EmitPatchInfo(); 4198 patch_site.EmitPatchInfo();
4164 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 4199 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
4165 __ cmp(r0, Operand(0)); 4200 __ cmp(r0, Operand(0));
4166 Split(cond, if_true, if_false, fall_through); 4201 Split(cond, if_true, if_false, fall_through);
4167 } 4202 }
4168 } 4203 }
4169 4204
4170 // Convert the result of the comparison into one expected for this 4205 // Convert the result of the comparison into one expected for this
4171 // expression's context. 4206 // expression's context.
4172 context()->Plug(if_true, if_false); 4207 context()->Plug(if_true, if_false);
4173 } 4208 }
4174 4209
4175 4210
4176 void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr, 4211 void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr,
4177 Expression* sub_expr, 4212 Expression* sub_expr,
4178 NilValue nil) { 4213 NilValue nil) {
4179 Label materialize_true, materialize_false; 4214 Label materialize_true, materialize_false;
4180 Label* if_true = NULL; 4215 Label* if_true = NULL;
4181 Label* if_false = NULL; 4216 Label* if_false = NULL;
4182 Label* fall_through = NULL; 4217 Label* fall_through = NULL;
4183 context()->PrepareTest(&materialize_true, &materialize_false, 4218 context()->PrepareTest(&materialize_true, &materialize_false,
4184 &if_true, &if_false, &fall_through); 4219 &if_true, &if_false, &fall_through);
4185 4220
4186 VisitForAccumulatorValue(sub_expr); 4221 VisitForAccumulatorValue(sub_expr);
4187 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 4222 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
4188 Heap::RootListIndex nil_value = nil == kNullValue ? 4223 Heap::RootListIndex nil_value = nil == kNullValue ?
4189 Heap::kNullValueRootIndex : 4224 Heap::kNullValueRootIndex :
4190 Heap::kUndefinedValueRootIndex; 4225 Heap::kUndefinedValueRootIndex;
4191 __ LoadRoot(r1, nil_value); 4226 __ LoadRoot(r1, nil_value);
4192 __ cmp(r0, r1); 4227 __ cmp(r0, r1);
4193 if (expr->op() == Token::EQ_STRICT) { 4228 if (expr->op() == Token::EQ_STRICT) {
4194 Split(eq, if_true, if_false, fall_through); 4229 Split(eq, if_true, if_false, fall_through);
4195 } else { 4230 } else {
4196 Heap::RootListIndex other_nil_value = nil == kNullValue ? 4231 Heap::RootListIndex other_nil_value = nil == kNullValue ?
4197 Heap::kUndefinedValueRootIndex : 4232 Heap::kUndefinedValueRootIndex :
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
4314 *context_length = 0; 4349 *context_length = 0;
4315 return previous_; 4350 return previous_;
4316 } 4351 }
4317 4352
4318 4353
4319 #undef __ 4354 #undef __
4320 4355
4321 } } // namespace v8::internal 4356 } } // namespace v8::internal
4322 4357
4323 #endif // V8_TARGET_ARCH_ARM 4358 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « no previous file | src/ast.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698