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

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

Issue 8372085: MIPS: Remove the forward-bailout stack from the non-optimizing compiler. (Closed)
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
« no previous file with comments | « no previous file | no next file » | 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 387 matching lines...) Expand 10 before | Expand all | Expand 10 after
398 void FullCodeGenerator::StackValueContext::Plug(Variable* var) const { 398 void FullCodeGenerator::StackValueContext::Plug(Variable* var) const {
399 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); 399 ASSERT(var->IsStackAllocated() || var->IsContextSlot());
400 codegen()->GetVar(result_register(), var); 400 codegen()->GetVar(result_register(), var);
401 __ push(result_register()); 401 __ push(result_register());
402 } 402 }
403 403
404 404
405 void FullCodeGenerator::TestContext::Plug(Variable* var) const { 405 void FullCodeGenerator::TestContext::Plug(Variable* var) const {
406 // For simplicity we always test the accumulator register. 406 // For simplicity we always test the accumulator register.
407 codegen()->GetVar(result_register(), var); 407 codegen()->GetVar(result_register(), var);
408 codegen()->PrepareForBailoutBeforeSplit(false, NULL, NULL); 408 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
409 codegen()->DoTest(this); 409 codegen()->DoTest(this);
410 } 410 }
411 411
412 412
413 void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const { 413 void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const {
414 } 414 }
415 415
416 416
417 void FullCodeGenerator::AccumulatorValueContext::Plug( 417 void FullCodeGenerator::AccumulatorValueContext::Plug(
418 Heap::RootListIndex index) const { 418 Heap::RootListIndex index) const {
419 __ LoadRoot(result_register(), index); 419 __ LoadRoot(result_register(), index);
420 } 420 }
421 421
422 422
423 void FullCodeGenerator::StackValueContext::Plug( 423 void FullCodeGenerator::StackValueContext::Plug(
424 Heap::RootListIndex index) const { 424 Heap::RootListIndex index) const {
425 __ LoadRoot(result_register(), index); 425 __ LoadRoot(result_register(), index);
426 __ push(result_register()); 426 __ push(result_register());
427 } 427 }
428 428
429 429
430 void FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const { 430 void FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const {
431 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, 431 codegen()->PrepareForBailoutBeforeSplit(condition(),
432 true, 432 true,
433 true_label_, 433 true_label_,
434 false_label_); 434 false_label_);
435 if (index == Heap::kUndefinedValueRootIndex || 435 if (index == Heap::kUndefinedValueRootIndex ||
436 index == Heap::kNullValueRootIndex || 436 index == Heap::kNullValueRootIndex ||
437 index == Heap::kFalseValueRootIndex) { 437 index == Heap::kFalseValueRootIndex) {
438 if (false_label_ != fall_through_) __ Branch(false_label_); 438 if (false_label_ != fall_through_) __ Branch(false_label_);
439 } else if (index == Heap::kTrueValueRootIndex) { 439 } else if (index == Heap::kTrueValueRootIndex) {
440 if (true_label_ != fall_through_) __ Branch(true_label_); 440 if (true_label_ != fall_through_) __ Branch(true_label_);
441 } else { 441 } else {
(...skipping 14 matching lines...) Expand all
456 456
457 457
458 void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const { 458 void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const {
459 // Immediates cannot be pushed directly. 459 // Immediates cannot be pushed directly.
460 __ li(result_register(), Operand(lit)); 460 __ li(result_register(), Operand(lit));
461 __ push(result_register()); 461 __ push(result_register());
462 } 462 }
463 463
464 464
465 void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const { 465 void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const {
466 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, 466 codegen()->PrepareForBailoutBeforeSplit(condition(),
467 true, 467 true,
468 true_label_, 468 true_label_,
469 false_label_); 469 false_label_);
470 ASSERT(!lit->IsUndetectableObject()); // There are no undetectable literals. 470 ASSERT(!lit->IsUndetectableObject()); // There are no undetectable literals.
471 if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) { 471 if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) {
472 if (false_label_ != fall_through_) __ Branch(false_label_); 472 if (false_label_ != fall_through_) __ Branch(false_label_);
473 } else if (lit->IsTrue() || lit->IsJSObject()) { 473 } else if (lit->IsTrue() || lit->IsJSObject()) {
474 if (true_label_ != fall_through_) __ Branch(true_label_); 474 if (true_label_ != fall_through_) __ Branch(true_label_);
475 } else if (lit->IsString()) { 475 } else if (lit->IsString()) {
476 if (String::cast(*lit)->length() == 0) { 476 if (String::cast(*lit)->length() == 0) {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
515 __ sw(reg, MemOperand(sp, 0)); 515 __ sw(reg, MemOperand(sp, 0));
516 } 516 }
517 517
518 518
519 void FullCodeGenerator::TestContext::DropAndPlug(int count, 519 void FullCodeGenerator::TestContext::DropAndPlug(int count,
520 Register reg) const { 520 Register reg) const {
521 ASSERT(count > 0); 521 ASSERT(count > 0);
522 // For simplicity we always test the accumulator register. 522 // For simplicity we always test the accumulator register.
523 __ Drop(count); 523 __ Drop(count);
524 __ Move(result_register(), reg); 524 __ Move(result_register(), reg);
525 codegen()->PrepareForBailoutBeforeSplit(false, NULL, NULL); 525 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
526 codegen()->DoTest(this); 526 codegen()->DoTest(this);
527 } 527 }
528 528
529 529
530 void FullCodeGenerator::EffectContext::Plug(Label* materialize_true, 530 void FullCodeGenerator::EffectContext::Plug(Label* materialize_true,
531 Label* materialize_false) const { 531 Label* materialize_false) const {
532 ASSERT(materialize_true == materialize_false); 532 ASSERT(materialize_true == materialize_false);
533 __ bind(materialize_true); 533 __ bind(materialize_true);
534 } 534 }
535 535
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
582 582
583 void FullCodeGenerator::StackValueContext::Plug(bool flag) const { 583 void FullCodeGenerator::StackValueContext::Plug(bool flag) const {
584 Heap::RootListIndex value_root_index = 584 Heap::RootListIndex value_root_index =
585 flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; 585 flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
586 __ LoadRoot(at, value_root_index); 586 __ LoadRoot(at, value_root_index);
587 __ push(at); 587 __ push(at);
588 } 588 }
589 589
590 590
591 void FullCodeGenerator::TestContext::Plug(bool flag) const { 591 void FullCodeGenerator::TestContext::Plug(bool flag) const {
592 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, 592 codegen()->PrepareForBailoutBeforeSplit(condition(),
593 true, 593 true,
594 true_label_, 594 true_label_,
595 false_label_); 595 false_label_);
596 if (flag) { 596 if (flag) {
597 if (true_label_ != fall_through_) __ Branch(true_label_); 597 if (true_label_ != fall_through_) __ Branch(true_label_);
598 } else { 598 } else {
599 if (false_label_ != fall_through_) __ Branch(false_label_); 599 if (false_label_ != fall_through_) __ Branch(false_label_);
600 } 600 }
601 } 601 }
602 602
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
685 __ RecordWriteContextSlot(scratch0, 685 __ RecordWriteContextSlot(scratch0,
686 location.offset(), 686 location.offset(),
687 src, 687 src,
688 scratch1, 688 scratch1,
689 kRAHasBeenSaved, 689 kRAHasBeenSaved,
690 kDontSaveFPRegs); 690 kDontSaveFPRegs);
691 } 691 }
692 } 692 }
693 693
694 694
695 void FullCodeGenerator::PrepareForBailoutBeforeSplit(State state, 695 void FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr,
696 bool should_normalize, 696 bool should_normalize,
697 Label* if_true, 697 Label* if_true,
698 Label* if_false) { 698 Label* if_false) {
699 // Only prepare for bailouts before splits if we're in a test 699 // Only prepare for bailouts before splits if we're in a test
700 // context. Otherwise, we let the Visit function deal with the 700 // context. Otherwise, we let the Visit function deal with the
701 // preparation to avoid preparing with the same AST id twice. 701 // preparation to avoid preparing with the same AST id twice.
702 if (!context()->IsTest() || !info_->IsOptimizable()) return; 702 if (!context()->IsTest() || !info_->IsOptimizable()) return;
703 703
704 Label skip; 704 Label skip;
705 if (should_normalize) __ Branch(&skip); 705 if (should_normalize) __ Branch(&skip);
706 706 PrepareForBailout(expr, TOS_REG);
707 ForwardBailoutStack* current = forward_bailout_stack_;
708 while (current != NULL) {
709 PrepareForBailout(current->expr(), state);
710 current = current->parent();
711 }
712
713 if (should_normalize) { 707 if (should_normalize) {
714 __ LoadRoot(t0, Heap::kTrueValueRootIndex); 708 __ LoadRoot(t0, Heap::kTrueValueRootIndex);
715 Split(eq, a0, Operand(t0), if_true, if_false, NULL); 709 Split(eq, a0, Operand(t0), if_true, if_false, NULL);
716 __ bind(&skip); 710 __ bind(&skip);
717 } 711 }
718 } 712 }
719 713
720 714
721 void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy, 715 void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy,
722 VariableMode mode, 716 VariableMode mode,
(...skipping 1671 matching lines...) Expand 10 before | Expand all | Expand 10 after
2394 __ li(a0, Operand(arg_count)); 2388 __ li(a0, Operand(arg_count));
2395 __ lw(a1, MemOperand(sp, arg_count * kPointerSize)); 2389 __ lw(a1, MemOperand(sp, arg_count * kPointerSize));
2396 2390
2397 Handle<Code> construct_builtin = 2391 Handle<Code> construct_builtin =
2398 isolate()->builtins()->JSConstructCall(); 2392 isolate()->builtins()->JSConstructCall();
2399 __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL); 2393 __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL);
2400 context()->Plug(v0); 2394 context()->Plug(v0);
2401 } 2395 }
2402 2396
2403 2397
2404 void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) { 2398 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) {
2399 ZoneList<Expression*>* args = expr->arguments();
2405 ASSERT(args->length() == 1); 2400 ASSERT(args->length() == 1);
2406 2401
2407 VisitForAccumulatorValue(args->at(0)); 2402 VisitForAccumulatorValue(args->at(0));
2408 2403
2409 Label materialize_true, materialize_false; 2404 Label materialize_true, materialize_false;
2410 Label* if_true = NULL; 2405 Label* if_true = NULL;
2411 Label* if_false = NULL; 2406 Label* if_false = NULL;
2412 Label* fall_through = NULL; 2407 Label* fall_through = NULL;
2413 context()->PrepareTest(&materialize_true, &materialize_false, 2408 context()->PrepareTest(&materialize_true, &materialize_false,
2414 &if_true, &if_false, &fall_through); 2409 &if_true, &if_false, &fall_through);
2415 2410
2416 PrepareForBailoutBeforeSplit(true, if_true, if_false); 2411 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2417 __ And(t0, v0, Operand(kSmiTagMask)); 2412 __ And(t0, v0, Operand(kSmiTagMask));
2418 Split(eq, t0, Operand(zero_reg), if_true, if_false, fall_through); 2413 Split(eq, t0, Operand(zero_reg), if_true, if_false, fall_through);
2419 2414
2420 context()->Plug(if_true, if_false); 2415 context()->Plug(if_true, if_false);
2421 } 2416 }
2422 2417
2423 2418
2424 void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) { 2419 void FullCodeGenerator::EmitIsNonNegativeSmi(CallRuntime* expr) {
2420 ZoneList<Expression*>* args = expr->arguments();
2425 ASSERT(args->length() == 1); 2421 ASSERT(args->length() == 1);
2426 2422
2427 VisitForAccumulatorValue(args->at(0)); 2423 VisitForAccumulatorValue(args->at(0));
2428 2424
2429 Label materialize_true, materialize_false; 2425 Label materialize_true, materialize_false;
2430 Label* if_true = NULL; 2426 Label* if_true = NULL;
2431 Label* if_false = NULL; 2427 Label* if_false = NULL;
2432 Label* fall_through = NULL; 2428 Label* fall_through = NULL;
2433 context()->PrepareTest(&materialize_true, &materialize_false, 2429 context()->PrepareTest(&materialize_true, &materialize_false,
2434 &if_true, &if_false, &fall_through); 2430 &if_true, &if_false, &fall_through);
2435 2431
2436 PrepareForBailoutBeforeSplit(true, if_true, if_false); 2432 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2437 __ And(at, v0, Operand(kSmiTagMask | 0x80000000)); 2433 __ And(at, v0, Operand(kSmiTagMask | 0x80000000));
2438 Split(eq, at, Operand(zero_reg), if_true, if_false, fall_through); 2434 Split(eq, at, Operand(zero_reg), if_true, if_false, fall_through);
2439 2435
2440 context()->Plug(if_true, if_false); 2436 context()->Plug(if_true, if_false);
2441 } 2437 }
2442 2438
2443 2439
2444 void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) { 2440 void FullCodeGenerator::EmitIsObject(CallRuntime* expr) {
2441 ZoneList<Expression*>* args = expr->arguments();
2445 ASSERT(args->length() == 1); 2442 ASSERT(args->length() == 1);
2446 2443
2447 VisitForAccumulatorValue(args->at(0)); 2444 VisitForAccumulatorValue(args->at(0));
2448 2445
2449 Label materialize_true, materialize_false; 2446 Label materialize_true, materialize_false;
2450 Label* if_true = NULL; 2447 Label* if_true = NULL;
2451 Label* if_false = NULL; 2448 Label* if_false = NULL;
2452 Label* fall_through = NULL; 2449 Label* fall_through = NULL;
2453 context()->PrepareTest(&materialize_true, &materialize_false, 2450 context()->PrepareTest(&materialize_true, &materialize_false,
2454 &if_true, &if_false, &fall_through); 2451 &if_true, &if_false, &fall_through);
2455 2452
2456 __ JumpIfSmi(v0, if_false); 2453 __ JumpIfSmi(v0, if_false);
2457 __ LoadRoot(at, Heap::kNullValueRootIndex); 2454 __ LoadRoot(at, Heap::kNullValueRootIndex);
2458 __ Branch(if_true, eq, v0, Operand(at)); 2455 __ Branch(if_true, eq, v0, Operand(at));
2459 __ lw(a2, FieldMemOperand(v0, HeapObject::kMapOffset)); 2456 __ lw(a2, FieldMemOperand(v0, HeapObject::kMapOffset));
2460 // Undetectable objects behave like undefined when tested with typeof. 2457 // Undetectable objects behave like undefined when tested with typeof.
2461 __ lbu(a1, FieldMemOperand(a2, Map::kBitFieldOffset)); 2458 __ lbu(a1, FieldMemOperand(a2, Map::kBitFieldOffset));
2462 __ And(at, a1, Operand(1 << Map::kIsUndetectable)); 2459 __ And(at, a1, Operand(1 << Map::kIsUndetectable));
2463 __ Branch(if_false, ne, at, Operand(zero_reg)); 2460 __ Branch(if_false, ne, at, Operand(zero_reg));
2464 __ lbu(a1, FieldMemOperand(a2, Map::kInstanceTypeOffset)); 2461 __ lbu(a1, FieldMemOperand(a2, Map::kInstanceTypeOffset));
2465 __ Branch(if_false, lt, a1, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); 2462 __ Branch(if_false, lt, a1, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
2466 PrepareForBailoutBeforeSplit(true, if_true, if_false); 2463 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2467 Split(le, a1, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE), 2464 Split(le, a1, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE),
2468 if_true, if_false, fall_through); 2465 if_true, if_false, fall_through);
2469 2466
2470 context()->Plug(if_true, if_false); 2467 context()->Plug(if_true, if_false);
2471 } 2468 }
2472 2469
2473 2470
2474 void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) { 2471 void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) {
2472 ZoneList<Expression*>* args = expr->arguments();
2475 ASSERT(args->length() == 1); 2473 ASSERT(args->length() == 1);
2476 2474
2477 VisitForAccumulatorValue(args->at(0)); 2475 VisitForAccumulatorValue(args->at(0));
2478 2476
2479 Label materialize_true, materialize_false; 2477 Label materialize_true, materialize_false;
2480 Label* if_true = NULL; 2478 Label* if_true = NULL;
2481 Label* if_false = NULL; 2479 Label* if_false = NULL;
2482 Label* fall_through = NULL; 2480 Label* fall_through = NULL;
2483 context()->PrepareTest(&materialize_true, &materialize_false, 2481 context()->PrepareTest(&materialize_true, &materialize_false,
2484 &if_true, &if_false, &fall_through); 2482 &if_true, &if_false, &fall_through);
2485 2483
2486 __ JumpIfSmi(v0, if_false); 2484 __ JumpIfSmi(v0, if_false);
2487 __ GetObjectType(v0, a1, a1); 2485 __ GetObjectType(v0, a1, a1);
2488 PrepareForBailoutBeforeSplit(true, if_true, if_false); 2486 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2489 Split(ge, a1, Operand(FIRST_SPEC_OBJECT_TYPE), 2487 Split(ge, a1, Operand(FIRST_SPEC_OBJECT_TYPE),
2490 if_true, if_false, fall_through); 2488 if_true, if_false, fall_through);
2491 2489
2492 context()->Plug(if_true, if_false); 2490 context()->Plug(if_true, if_false);
2493 } 2491 }
2494 2492
2495 2493
2496 void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) { 2494 void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) {
2495 ZoneList<Expression*>* args = expr->arguments();
2497 ASSERT(args->length() == 1); 2496 ASSERT(args->length() == 1);
2498 2497
2499 VisitForAccumulatorValue(args->at(0)); 2498 VisitForAccumulatorValue(args->at(0));
2500 2499
2501 Label materialize_true, materialize_false; 2500 Label materialize_true, materialize_false;
2502 Label* if_true = NULL; 2501 Label* if_true = NULL;
2503 Label* if_false = NULL; 2502 Label* if_false = NULL;
2504 Label* fall_through = NULL; 2503 Label* fall_through = NULL;
2505 context()->PrepareTest(&materialize_true, &materialize_false, 2504 context()->PrepareTest(&materialize_true, &materialize_false,
2506 &if_true, &if_false, &fall_through); 2505 &if_true, &if_false, &fall_through);
2507 2506
2508 __ JumpIfSmi(v0, if_false); 2507 __ JumpIfSmi(v0, if_false);
2509 __ lw(a1, FieldMemOperand(v0, HeapObject::kMapOffset)); 2508 __ lw(a1, FieldMemOperand(v0, HeapObject::kMapOffset));
2510 __ lbu(a1, FieldMemOperand(a1, Map::kBitFieldOffset)); 2509 __ lbu(a1, FieldMemOperand(a1, Map::kBitFieldOffset));
2511 __ And(at, a1, Operand(1 << Map::kIsUndetectable)); 2510 __ And(at, a1, Operand(1 << Map::kIsUndetectable));
2512 PrepareForBailoutBeforeSplit(true, if_true, if_false); 2511 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2513 Split(ne, at, Operand(zero_reg), if_true, if_false, fall_through); 2512 Split(ne, at, Operand(zero_reg), if_true, if_false, fall_through);
2514 2513
2515 context()->Plug(if_true, if_false); 2514 context()->Plug(if_true, if_false);
2516 } 2515 }
2517 2516
2518 2517
2519 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( 2518 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
2520 ZoneList<Expression*>* args) { 2519 CallRuntime* expr) {
2521 2520 ZoneList<Expression*>* args = expr->arguments();
2522 ASSERT(args->length() == 1); 2521 ASSERT(args->length() == 1);
2523 2522
2524 VisitForAccumulatorValue(args->at(0)); 2523 VisitForAccumulatorValue(args->at(0));
2525 2524
2526 Label materialize_true, materialize_false; 2525 Label materialize_true, materialize_false;
2527 Label* if_true = NULL; 2526 Label* if_true = NULL;
2528 Label* if_false = NULL; 2527 Label* if_false = NULL;
2529 Label* fall_through = NULL; 2528 Label* fall_through = NULL;
2530 context()->PrepareTest(&materialize_true, &materialize_false, 2529 context()->PrepareTest(&materialize_true, &materialize_false,
2531 &if_true, &if_false, &fall_through); 2530 &if_true, &if_false, &fall_through);
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
2587 __ lw(a3, ContextOperand(a3, Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX)); 2586 __ lw(a3, ContextOperand(a3, Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX));
2588 __ Branch(if_false, ne, a2, Operand(a3)); 2587 __ Branch(if_false, ne, a2, Operand(a3));
2589 2588
2590 // Set the bit in the map to indicate that it has been checked safe for 2589 // Set the bit in the map to indicate that it has been checked safe for
2591 // default valueOf and set true result. 2590 // default valueOf and set true result.
2592 __ lbu(a2, FieldMemOperand(a1, Map::kBitField2Offset)); 2591 __ lbu(a2, FieldMemOperand(a1, Map::kBitField2Offset));
2593 __ Or(a2, a2, Operand(1 << Map::kStringWrapperSafeForDefaultValueOf)); 2592 __ Or(a2, a2, Operand(1 << Map::kStringWrapperSafeForDefaultValueOf));
2594 __ sb(a2, FieldMemOperand(a1, Map::kBitField2Offset)); 2593 __ sb(a2, FieldMemOperand(a1, Map::kBitField2Offset));
2595 __ jmp(if_true); 2594 __ jmp(if_true);
2596 2595
2597 PrepareForBailoutBeforeSplit(true, if_true, if_false); 2596 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2598 context()->Plug(if_true, if_false); 2597 context()->Plug(if_true, if_false);
2599 } 2598 }
2600 2599
2601 2600
2602 void FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) { 2601 void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) {
2602 ZoneList<Expression*>* args = expr->arguments();
2603 ASSERT(args->length() == 1); 2603 ASSERT(args->length() == 1);
2604 2604
2605 VisitForAccumulatorValue(args->at(0)); 2605 VisitForAccumulatorValue(args->at(0));
2606 2606
2607 Label materialize_true, materialize_false; 2607 Label materialize_true, materialize_false;
2608 Label* if_true = NULL; 2608 Label* if_true = NULL;
2609 Label* if_false = NULL; 2609 Label* if_false = NULL;
2610 Label* fall_through = NULL; 2610 Label* fall_through = NULL;
2611 context()->PrepareTest(&materialize_true, &materialize_false, 2611 context()->PrepareTest(&materialize_true, &materialize_false,
2612 &if_true, &if_false, &fall_through); 2612 &if_true, &if_false, &fall_through);
2613 2613
2614 __ JumpIfSmi(v0, if_false); 2614 __ JumpIfSmi(v0, if_false);
2615 __ GetObjectType(v0, a1, a2); 2615 __ GetObjectType(v0, a1, a2);
2616 PrepareForBailoutBeforeSplit(true, if_true, if_false); 2616 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2617 __ Branch(if_true, eq, a2, Operand(JS_FUNCTION_TYPE)); 2617 __ Branch(if_true, eq, a2, Operand(JS_FUNCTION_TYPE));
2618 __ Branch(if_false); 2618 __ Branch(if_false);
2619 2619
2620 context()->Plug(if_true, if_false); 2620 context()->Plug(if_true, if_false);
2621 } 2621 }
2622 2622
2623 2623
2624 void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) { 2624 void FullCodeGenerator::EmitIsArray(CallRuntime* expr) {
2625 ZoneList<Expression*>* args = expr->arguments();
2625 ASSERT(args->length() == 1); 2626 ASSERT(args->length() == 1);
2626 2627
2627 VisitForAccumulatorValue(args->at(0)); 2628 VisitForAccumulatorValue(args->at(0));
2628 2629
2629 Label materialize_true, materialize_false; 2630 Label materialize_true, materialize_false;
2630 Label* if_true = NULL; 2631 Label* if_true = NULL;
2631 Label* if_false = NULL; 2632 Label* if_false = NULL;
2632 Label* fall_through = NULL; 2633 Label* fall_through = NULL;
2633 context()->PrepareTest(&materialize_true, &materialize_false, 2634 context()->PrepareTest(&materialize_true, &materialize_false,
2634 &if_true, &if_false, &fall_through); 2635 &if_true, &if_false, &fall_through);
2635 2636
2636 __ JumpIfSmi(v0, if_false); 2637 __ JumpIfSmi(v0, if_false);
2637 __ GetObjectType(v0, a1, a1); 2638 __ GetObjectType(v0, a1, a1);
2638 PrepareForBailoutBeforeSplit(true, if_true, if_false); 2639 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2639 Split(eq, a1, Operand(JS_ARRAY_TYPE), 2640 Split(eq, a1, Operand(JS_ARRAY_TYPE),
2640 if_true, if_false, fall_through); 2641 if_true, if_false, fall_through);
2641 2642
2642 context()->Plug(if_true, if_false); 2643 context()->Plug(if_true, if_false);
2643 } 2644 }
2644 2645
2645 2646
2646 void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) { 2647 void FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) {
2648 ZoneList<Expression*>* args = expr->arguments();
2647 ASSERT(args->length() == 1); 2649 ASSERT(args->length() == 1);
2648 2650
2649 VisitForAccumulatorValue(args->at(0)); 2651 VisitForAccumulatorValue(args->at(0));
2650 2652
2651 Label materialize_true, materialize_false; 2653 Label materialize_true, materialize_false;
2652 Label* if_true = NULL; 2654 Label* if_true = NULL;
2653 Label* if_false = NULL; 2655 Label* if_false = NULL;
2654 Label* fall_through = NULL; 2656 Label* fall_through = NULL;
2655 context()->PrepareTest(&materialize_true, &materialize_false, 2657 context()->PrepareTest(&materialize_true, &materialize_false,
2656 &if_true, &if_false, &fall_through); 2658 &if_true, &if_false, &fall_through);
2657 2659
2658 __ JumpIfSmi(v0, if_false); 2660 __ JumpIfSmi(v0, if_false);
2659 __ GetObjectType(v0, a1, a1); 2661 __ GetObjectType(v0, a1, a1);
2660 PrepareForBailoutBeforeSplit(true, if_true, if_false); 2662 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2661 Split(eq, a1, Operand(JS_REGEXP_TYPE), if_true, if_false, fall_through); 2663 Split(eq, a1, Operand(JS_REGEXP_TYPE), if_true, if_false, fall_through);
2662 2664
2663 context()->Plug(if_true, if_false); 2665 context()->Plug(if_true, if_false);
2664 } 2666 }
2665 2667
2666 2668
2667 void FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) { 2669 void FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) {
2668 ASSERT(args->length() == 0); 2670 ASSERT(expr->arguments()->length() == 0);
2669 2671
2670 Label materialize_true, materialize_false; 2672 Label materialize_true, materialize_false;
2671 Label* if_true = NULL; 2673 Label* if_true = NULL;
2672 Label* if_false = NULL; 2674 Label* if_false = NULL;
2673 Label* fall_through = NULL; 2675 Label* fall_through = NULL;
2674 context()->PrepareTest(&materialize_true, &materialize_false, 2676 context()->PrepareTest(&materialize_true, &materialize_false,
2675 &if_true, &if_false, &fall_through); 2677 &if_true, &if_false, &fall_through);
2676 2678
2677 // Get the frame pointer for the calling frame. 2679 // Get the frame pointer for the calling frame.
2678 __ lw(a2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); 2680 __ lw(a2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
2679 2681
2680 // Skip the arguments adaptor frame if it exists. 2682 // Skip the arguments adaptor frame if it exists.
2681 Label check_frame_marker; 2683 Label check_frame_marker;
2682 __ lw(a1, MemOperand(a2, StandardFrameConstants::kContextOffset)); 2684 __ lw(a1, MemOperand(a2, StandardFrameConstants::kContextOffset));
2683 __ Branch(&check_frame_marker, ne, 2685 __ Branch(&check_frame_marker, ne,
2684 a1, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 2686 a1, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
2685 __ lw(a2, MemOperand(a2, StandardFrameConstants::kCallerFPOffset)); 2687 __ lw(a2, MemOperand(a2, StandardFrameConstants::kCallerFPOffset));
2686 2688
2687 // Check the marker in the calling frame. 2689 // Check the marker in the calling frame.
2688 __ bind(&check_frame_marker); 2690 __ bind(&check_frame_marker);
2689 __ lw(a1, MemOperand(a2, StandardFrameConstants::kMarkerOffset)); 2691 __ lw(a1, MemOperand(a2, StandardFrameConstants::kMarkerOffset));
2690 PrepareForBailoutBeforeSplit(true, if_true, if_false); 2692 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2691 Split(eq, a1, Operand(Smi::FromInt(StackFrame::CONSTRUCT)), 2693 Split(eq, a1, Operand(Smi::FromInt(StackFrame::CONSTRUCT)),
2692 if_true, if_false, fall_through); 2694 if_true, if_false, fall_through);
2693 2695
2694 context()->Plug(if_true, if_false); 2696 context()->Plug(if_true, if_false);
2695 } 2697 }
2696 2698
2697 2699
2698 void FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) { 2700 void FullCodeGenerator::EmitObjectEquals(CallRuntime* expr) {
2701 ZoneList<Expression*>* args = expr->arguments();
2699 ASSERT(args->length() == 2); 2702 ASSERT(args->length() == 2);
2700 2703
2701 // Load the two objects into registers and perform the comparison. 2704 // Load the two objects into registers and perform the comparison.
2702 VisitForStackValue(args->at(0)); 2705 VisitForStackValue(args->at(0));
2703 VisitForAccumulatorValue(args->at(1)); 2706 VisitForAccumulatorValue(args->at(1));
2704 2707
2705 Label materialize_true, materialize_false; 2708 Label materialize_true, materialize_false;
2706 Label* if_true = NULL; 2709 Label* if_true = NULL;
2707 Label* if_false = NULL; 2710 Label* if_false = NULL;
2708 Label* fall_through = NULL; 2711 Label* fall_through = NULL;
2709 context()->PrepareTest(&materialize_true, &materialize_false, 2712 context()->PrepareTest(&materialize_true, &materialize_false,
2710 &if_true, &if_false, &fall_through); 2713 &if_true, &if_false, &fall_through);
2711 2714
2712 __ pop(a1); 2715 __ pop(a1);
2713 PrepareForBailoutBeforeSplit(true, if_true, if_false); 2716 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2714 Split(eq, v0, Operand(a1), if_true, if_false, fall_through); 2717 Split(eq, v0, Operand(a1), if_true, if_false, fall_through);
2715 2718
2716 context()->Plug(if_true, if_false); 2719 context()->Plug(if_true, if_false);
2717 } 2720 }
2718 2721
2719 2722
2720 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) { 2723 void FullCodeGenerator::EmitArguments(CallRuntime* expr) {
2724 ZoneList<Expression*>* args = expr->arguments();
2721 ASSERT(args->length() == 1); 2725 ASSERT(args->length() == 1);
2722 2726
2723 // ArgumentsAccessStub expects the key in a1 and the formal 2727 // ArgumentsAccessStub expects the key in a1 and the formal
2724 // parameter count in a0. 2728 // parameter count in a0.
2725 VisitForAccumulatorValue(args->at(0)); 2729 VisitForAccumulatorValue(args->at(0));
2726 __ mov(a1, v0); 2730 __ mov(a1, v0);
2727 __ li(a0, Operand(Smi::FromInt(info_->scope()->num_parameters()))); 2731 __ li(a0, Operand(Smi::FromInt(info_->scope()->num_parameters())));
2728 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); 2732 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
2729 __ CallStub(&stub); 2733 __ CallStub(&stub);
2730 context()->Plug(v0); 2734 context()->Plug(v0);
2731 } 2735 }
2732 2736
2733 2737
2734 void FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) { 2738 void FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) {
2735 ASSERT(args->length() == 0); 2739 ASSERT(expr->arguments()->length() == 0);
2736
2737 Label exit; 2740 Label exit;
2738 // Get the number of formal parameters. 2741 // Get the number of formal parameters.
2739 __ li(v0, Operand(Smi::FromInt(info_->scope()->num_parameters()))); 2742 __ li(v0, Operand(Smi::FromInt(info_->scope()->num_parameters())));
2740 2743
2741 // Check if the calling frame is an arguments adaptor frame. 2744 // Check if the calling frame is an arguments adaptor frame.
2742 __ lw(a2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); 2745 __ lw(a2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
2743 __ lw(a3, MemOperand(a2, StandardFrameConstants::kContextOffset)); 2746 __ lw(a3, MemOperand(a2, StandardFrameConstants::kContextOffset));
2744 __ Branch(&exit, ne, a3, 2747 __ Branch(&exit, ne, a3,
2745 Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 2748 Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
2746 2749
2747 // Arguments adaptor case: Read the arguments length from the 2750 // Arguments adaptor case: Read the arguments length from the
2748 // adaptor frame. 2751 // adaptor frame.
2749 __ lw(v0, MemOperand(a2, ArgumentsAdaptorFrameConstants::kLengthOffset)); 2752 __ lw(v0, MemOperand(a2, ArgumentsAdaptorFrameConstants::kLengthOffset));
2750 2753
2751 __ bind(&exit); 2754 __ bind(&exit);
2752 context()->Plug(v0); 2755 context()->Plug(v0);
2753 } 2756 }
2754 2757
2755 2758
2756 void FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) { 2759 void FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
2760 ZoneList<Expression*>* args = expr->arguments();
2757 ASSERT(args->length() == 1); 2761 ASSERT(args->length() == 1);
2758 Label done, null, function, non_function_constructor; 2762 Label done, null, function, non_function_constructor;
2759 2763
2760 VisitForAccumulatorValue(args->at(0)); 2764 VisitForAccumulatorValue(args->at(0));
2761 2765
2762 // If the object is a smi, we return null. 2766 // If the object is a smi, we return null.
2763 __ JumpIfSmi(v0, &null); 2767 __ JumpIfSmi(v0, &null);
2764 2768
2765 // Check that the object is a JS object but take special care of JS 2769 // Check that the object is a JS object but take special care of JS
2766 // functions to make sure they have 'Function' as their class. 2770 // functions to make sure they have 'Function' as their class.
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
2805 __ bind(&null); 2809 __ bind(&null);
2806 __ LoadRoot(v0, Heap::kNullValueRootIndex); 2810 __ LoadRoot(v0, Heap::kNullValueRootIndex);
2807 2811
2808 // All done. 2812 // All done.
2809 __ bind(&done); 2813 __ bind(&done);
2810 2814
2811 context()->Plug(v0); 2815 context()->Plug(v0);
2812 } 2816 }
2813 2817
2814 2818
2815 void FullCodeGenerator::EmitLog(ZoneList<Expression*>* args) { 2819 void FullCodeGenerator::EmitLog(CallRuntime* expr) {
2816 // Conditionally generate a log call. 2820 // Conditionally generate a log call.
2817 // Args: 2821 // Args:
2818 // 0 (literal string): The type of logging (corresponds to the flags). 2822 // 0 (literal string): The type of logging (corresponds to the flags).
2819 // This is used to determine whether or not to generate the log call. 2823 // This is used to determine whether or not to generate the log call.
2820 // 1 (string): Format string. Access the string at argument index 2 2824 // 1 (string): Format string. Access the string at argument index 2
2821 // with '%2s' (see Logger::LogRuntime for all the formats). 2825 // with '%2s' (see Logger::LogRuntime for all the formats).
2822 // 2 (array): Arguments to the format string. 2826 // 2 (array): Arguments to the format string.
2827 ZoneList<Expression*>* args = expr->arguments();
2823 ASSERT_EQ(args->length(), 3); 2828 ASSERT_EQ(args->length(), 3);
2824 if (CodeGenerator::ShouldGenerateLog(args->at(0))) { 2829 if (CodeGenerator::ShouldGenerateLog(args->at(0))) {
2825 VisitForStackValue(args->at(1)); 2830 VisitForStackValue(args->at(1));
2826 VisitForStackValue(args->at(2)); 2831 VisitForStackValue(args->at(2));
2827 __ CallRuntime(Runtime::kLog, 2); 2832 __ CallRuntime(Runtime::kLog, 2);
2828 } 2833 }
2829 2834
2830 // Finally, we're expected to leave a value on the top of the stack. 2835 // Finally, we're expected to leave a value on the top of the stack.
2831 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex); 2836 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex);
2832 context()->Plug(v0); 2837 context()->Plug(v0);
2833 } 2838 }
2834 2839
2835 2840
2836 void FullCodeGenerator::EmitRandomHeapNumber(ZoneList<Expression*>* args) { 2841 void FullCodeGenerator::EmitRandomHeapNumber(CallRuntime* expr) {
2837 ASSERT(args->length() == 0); 2842 ASSERT(expr->arguments()->length() == 0);
2838
2839 Label slow_allocate_heapnumber; 2843 Label slow_allocate_heapnumber;
2840 Label heapnumber_allocated; 2844 Label heapnumber_allocated;
2841 2845
2842 // Save the new heap number in callee-saved register s0, since 2846 // Save the new heap number in callee-saved register s0, since
2843 // we call out to external C code below. 2847 // we call out to external C code below.
2844 __ LoadRoot(t6, Heap::kHeapNumberMapRootIndex); 2848 __ LoadRoot(t6, Heap::kHeapNumberMapRootIndex);
2845 __ AllocateHeapNumber(s0, a1, a2, t6, &slow_allocate_heapnumber); 2849 __ AllocateHeapNumber(s0, a1, a2, t6, &slow_allocate_heapnumber);
2846 __ jmp(&heapnumber_allocated); 2850 __ jmp(&heapnumber_allocated);
2847 2851
2848 __ bind(&slow_allocate_heapnumber); 2852 __ bind(&slow_allocate_heapnumber);
(...skipping 30 matching lines...) Expand all
2879 __ lw(a1, ContextOperand(cp, Context::GLOBAL_INDEX)); 2883 __ lw(a1, ContextOperand(cp, Context::GLOBAL_INDEX));
2880 __ lw(a1, FieldMemOperand(a1, GlobalObject::kGlobalContextOffset)); 2884 __ lw(a1, FieldMemOperand(a1, GlobalObject::kGlobalContextOffset));
2881 __ CallCFunction( 2885 __ CallCFunction(
2882 ExternalReference::fill_heap_number_with_random_function(isolate()), 2); 2886 ExternalReference::fill_heap_number_with_random_function(isolate()), 2);
2883 } 2887 }
2884 2888
2885 context()->Plug(v0); 2889 context()->Plug(v0);
2886 } 2890 }
2887 2891
2888 2892
2889 void FullCodeGenerator::EmitSubString(ZoneList<Expression*>* args) { 2893 void FullCodeGenerator::EmitSubString(CallRuntime* expr) {
2890 // Load the arguments on the stack and call the stub. 2894 // Load the arguments on the stack and call the stub.
2891 SubStringStub stub; 2895 SubStringStub stub;
2896 ZoneList<Expression*>* args = expr->arguments();
2892 ASSERT(args->length() == 3); 2897 ASSERT(args->length() == 3);
2893 VisitForStackValue(args->at(0)); 2898 VisitForStackValue(args->at(0));
2894 VisitForStackValue(args->at(1)); 2899 VisitForStackValue(args->at(1));
2895 VisitForStackValue(args->at(2)); 2900 VisitForStackValue(args->at(2));
2896 __ CallStub(&stub); 2901 __ CallStub(&stub);
2897 context()->Plug(v0); 2902 context()->Plug(v0);
2898 } 2903 }
2899 2904
2900 2905
2901 void FullCodeGenerator::EmitRegExpExec(ZoneList<Expression*>* args) { 2906 void FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) {
2902 // Load the arguments on the stack and call the stub. 2907 // Load the arguments on the stack and call the stub.
2903 RegExpExecStub stub; 2908 RegExpExecStub stub;
2909 ZoneList<Expression*>* args = expr->arguments();
2904 ASSERT(args->length() == 4); 2910 ASSERT(args->length() == 4);
2905 VisitForStackValue(args->at(0)); 2911 VisitForStackValue(args->at(0));
2906 VisitForStackValue(args->at(1)); 2912 VisitForStackValue(args->at(1));
2907 VisitForStackValue(args->at(2)); 2913 VisitForStackValue(args->at(2));
2908 VisitForStackValue(args->at(3)); 2914 VisitForStackValue(args->at(3));
2909 __ CallStub(&stub); 2915 __ CallStub(&stub);
2910 context()->Plug(v0); 2916 context()->Plug(v0);
2911 } 2917 }
2912 2918
2913 2919
2914 void FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) { 2920 void FullCodeGenerator::EmitValueOf(CallRuntime* expr) {
2921 ZoneList<Expression*>* args = expr->arguments();
2915 ASSERT(args->length() == 1); 2922 ASSERT(args->length() == 1);
2916 2923
2917 VisitForAccumulatorValue(args->at(0)); // Load the object. 2924 VisitForAccumulatorValue(args->at(0)); // Load the object.
2918 2925
2919 Label done; 2926 Label done;
2920 // If the object is a smi return the object. 2927 // If the object is a smi return the object.
2921 __ JumpIfSmi(v0, &done); 2928 __ JumpIfSmi(v0, &done);
2922 // If the object is not a value type, return the object. 2929 // If the object is not a value type, return the object.
2923 __ GetObjectType(v0, a1, a1); 2930 __ GetObjectType(v0, a1, a1);
2924 __ Branch(&done, ne, a1, Operand(JS_VALUE_TYPE)); 2931 __ Branch(&done, ne, a1, Operand(JS_VALUE_TYPE));
2925 2932
2926 __ lw(v0, FieldMemOperand(v0, JSValue::kValueOffset)); 2933 __ lw(v0, FieldMemOperand(v0, JSValue::kValueOffset));
2927 2934
2928 __ bind(&done); 2935 __ bind(&done);
2929 context()->Plug(v0); 2936 context()->Plug(v0);
2930 } 2937 }
2931 2938
2932 2939
2933 void FullCodeGenerator::EmitMathPow(ZoneList<Expression*>* args) { 2940 void FullCodeGenerator::EmitMathPow(CallRuntime* expr) {
2934 // Load the arguments on the stack and call the runtime function. 2941 // Load the arguments on the stack and call the runtime function.
2942 ZoneList<Expression*>* args = expr->arguments();
2935 ASSERT(args->length() == 2); 2943 ASSERT(args->length() == 2);
2936 VisitForStackValue(args->at(0)); 2944 VisitForStackValue(args->at(0));
2937 VisitForStackValue(args->at(1)); 2945 VisitForStackValue(args->at(1));
2938 MathPowStub stub; 2946 MathPowStub stub;
2939 __ CallStub(&stub); 2947 __ CallStub(&stub);
2940 context()->Plug(v0); 2948 context()->Plug(v0);
2941 } 2949 }
2942 2950
2943 2951
2944 void FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) { 2952 void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) {
2953 ZoneList<Expression*>* args = expr->arguments();
2945 ASSERT(args->length() == 2); 2954 ASSERT(args->length() == 2);
2946 2955
2947 VisitForStackValue(args->at(0)); // Load the object. 2956 VisitForStackValue(args->at(0)); // Load the object.
2948 VisitForAccumulatorValue(args->at(1)); // Load the value. 2957 VisitForAccumulatorValue(args->at(1)); // Load the value.
2949 __ pop(a1); // v0 = value. a1 = object. 2958 __ pop(a1); // v0 = value. a1 = object.
2950 2959
2951 Label done; 2960 Label done;
2952 // If the object is a smi, return the value. 2961 // If the object is a smi, return the value.
2953 __ JumpIfSmi(a1, &done); 2962 __ JumpIfSmi(a1, &done);
2954 2963
2955 // If the object is not a value type, return the value. 2964 // If the object is not a value type, return the value.
2956 __ GetObjectType(a1, a2, a2); 2965 __ GetObjectType(a1, a2, a2);
2957 __ Branch(&done, ne, a2, Operand(JS_VALUE_TYPE)); 2966 __ Branch(&done, ne, a2, Operand(JS_VALUE_TYPE));
2958 2967
2959 // Store the value. 2968 // Store the value.
2960 __ sw(v0, FieldMemOperand(a1, JSValue::kValueOffset)); 2969 __ sw(v0, FieldMemOperand(a1, JSValue::kValueOffset));
2961 // Update the write barrier. Save the value as it will be 2970 // Update the write barrier. Save the value as it will be
2962 // overwritten by the write barrier code and is needed afterward. 2971 // overwritten by the write barrier code and is needed afterward.
2963 __ mov(a2, v0); 2972 __ mov(a2, v0);
2964 __ RecordWriteField( 2973 __ RecordWriteField(
2965 a1, JSValue::kValueOffset, a2, a3, kRAHasBeenSaved, kDontSaveFPRegs); 2974 a1, JSValue::kValueOffset, a2, a3, kRAHasBeenSaved, kDontSaveFPRegs);
2966 2975
2967 __ bind(&done); 2976 __ bind(&done);
2968 context()->Plug(v0); 2977 context()->Plug(v0);
2969 } 2978 }
2970 2979
2971 2980
2972 void FullCodeGenerator::EmitNumberToString(ZoneList<Expression*>* args) { 2981 void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
2982 ZoneList<Expression*>* args = expr->arguments();
2973 ASSERT_EQ(args->length(), 1); 2983 ASSERT_EQ(args->length(), 1);
2974 2984
2975 // Load the argument on the stack and call the stub. 2985 // Load the argument on the stack and call the stub.
2976 VisitForStackValue(args->at(0)); 2986 VisitForStackValue(args->at(0));
2977 2987
2978 NumberToStringStub stub; 2988 NumberToStringStub stub;
2979 __ CallStub(&stub); 2989 __ CallStub(&stub);
2980 context()->Plug(v0); 2990 context()->Plug(v0);
2981 } 2991 }
2982 2992
2983 2993
2984 void FullCodeGenerator::EmitStringCharFromCode(ZoneList<Expression*>* args) { 2994 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
2995 ZoneList<Expression*>* args = expr->arguments();
2985 ASSERT(args->length() == 1); 2996 ASSERT(args->length() == 1);
2986 2997
2987 VisitForAccumulatorValue(args->at(0)); 2998 VisitForAccumulatorValue(args->at(0));
2988 2999
2989 Label done; 3000 Label done;
2990 StringCharFromCodeGenerator generator(v0, a1); 3001 StringCharFromCodeGenerator generator(v0, a1);
2991 generator.GenerateFast(masm_); 3002 generator.GenerateFast(masm_);
2992 __ jmp(&done); 3003 __ jmp(&done);
2993 3004
2994 NopRuntimeCallHelper call_helper; 3005 NopRuntimeCallHelper call_helper;
2995 generator.GenerateSlow(masm_, call_helper); 3006 generator.GenerateSlow(masm_, call_helper);
2996 3007
2997 __ bind(&done); 3008 __ bind(&done);
2998 context()->Plug(a1); 3009 context()->Plug(a1);
2999 } 3010 }
3000 3011
3001 3012
3002 void FullCodeGenerator::EmitStringCharCodeAt(ZoneList<Expression*>* args) { 3013 void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) {
3014 ZoneList<Expression*>* args = expr->arguments();
3003 ASSERT(args->length() == 2); 3015 ASSERT(args->length() == 2);
3004 3016
3005 VisitForStackValue(args->at(0)); 3017 VisitForStackValue(args->at(0));
3006 VisitForAccumulatorValue(args->at(1)); 3018 VisitForAccumulatorValue(args->at(1));
3007 __ mov(a0, result_register()); 3019 __ mov(a0, result_register());
3008 3020
3009 Register object = a1; 3021 Register object = a1;
3010 Register index = a0; 3022 Register index = a0;
3011 Register scratch = a2; 3023 Register scratch = a2;
3012 Register result = v0; 3024 Register result = v0;
(...skipping 27 matching lines...) Expand all
3040 __ jmp(&done); 3052 __ jmp(&done);
3041 3053
3042 NopRuntimeCallHelper call_helper; 3054 NopRuntimeCallHelper call_helper;
3043 generator.GenerateSlow(masm_, call_helper); 3055 generator.GenerateSlow(masm_, call_helper);
3044 3056
3045 __ bind(&done); 3057 __ bind(&done);
3046 context()->Plug(result); 3058 context()->Plug(result);
3047 } 3059 }
3048 3060
3049 3061
3050 void FullCodeGenerator::EmitStringCharAt(ZoneList<Expression*>* args) { 3062 void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) {
3063 ZoneList<Expression*>* args = expr->arguments();
3051 ASSERT(args->length() == 2); 3064 ASSERT(args->length() == 2);
3052 3065
3053 VisitForStackValue(args->at(0)); 3066 VisitForStackValue(args->at(0));
3054 VisitForAccumulatorValue(args->at(1)); 3067 VisitForAccumulatorValue(args->at(1));
3055 __ mov(a0, result_register()); 3068 __ mov(a0, result_register());
3056 3069
3057 Register object = a1; 3070 Register object = a1;
3058 Register index = a0; 3071 Register index = a0;
3059 Register scratch1 = a2; 3072 Register scratch1 = a2;
3060 Register scratch2 = a3; 3073 Register scratch2 = a3;
(...skipping 29 matching lines...) Expand all
3090 __ jmp(&done); 3103 __ jmp(&done);
3091 3104
3092 NopRuntimeCallHelper call_helper; 3105 NopRuntimeCallHelper call_helper;
3093 generator.GenerateSlow(masm_, call_helper); 3106 generator.GenerateSlow(masm_, call_helper);
3094 3107
3095 __ bind(&done); 3108 __ bind(&done);
3096 context()->Plug(result); 3109 context()->Plug(result);
3097 } 3110 }
3098 3111
3099 3112
3100 void FullCodeGenerator::EmitStringAdd(ZoneList<Expression*>* args) { 3113 void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) {
3114 ZoneList<Expression*>* args = expr->arguments();
3101 ASSERT_EQ(2, args->length()); 3115 ASSERT_EQ(2, args->length());
3102
3103 VisitForStackValue(args->at(0)); 3116 VisitForStackValue(args->at(0));
3104 VisitForStackValue(args->at(1)); 3117 VisitForStackValue(args->at(1));
3105 3118
3106 StringAddStub stub(NO_STRING_ADD_FLAGS); 3119 StringAddStub stub(NO_STRING_ADD_FLAGS);
3107 __ CallStub(&stub); 3120 __ CallStub(&stub);
3108 context()->Plug(v0); 3121 context()->Plug(v0);
3109 } 3122 }
3110 3123
3111 3124
3112 void FullCodeGenerator::EmitStringCompare(ZoneList<Expression*>* args) { 3125 void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) {
3126 ZoneList<Expression*>* args = expr->arguments();
3113 ASSERT_EQ(2, args->length()); 3127 ASSERT_EQ(2, args->length());
3114 3128
3115 VisitForStackValue(args->at(0)); 3129 VisitForStackValue(args->at(0));
3116 VisitForStackValue(args->at(1)); 3130 VisitForStackValue(args->at(1));
3117 3131
3118 StringCompareStub stub; 3132 StringCompareStub stub;
3119 __ CallStub(&stub); 3133 __ CallStub(&stub);
3120 context()->Plug(v0); 3134 context()->Plug(v0);
3121 } 3135 }
3122 3136
3123 3137
3124 void FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) { 3138 void FullCodeGenerator::EmitMathSin(CallRuntime* expr) {
3125 // Load the argument on the stack and call the stub. 3139 // Load the argument on the stack and call the stub.
3126 TranscendentalCacheStub stub(TranscendentalCache::SIN, 3140 TranscendentalCacheStub stub(TranscendentalCache::SIN,
3127 TranscendentalCacheStub::TAGGED); 3141 TranscendentalCacheStub::TAGGED);
3142 ZoneList<Expression*>* args = expr->arguments();
3128 ASSERT(args->length() == 1); 3143 ASSERT(args->length() == 1);
3129 VisitForStackValue(args->at(0)); 3144 VisitForStackValue(args->at(0));
3130 __ mov(a0, result_register()); // Stub requires parameter in a0 and on tos. 3145 __ mov(a0, result_register()); // Stub requires parameter in a0 and on tos.
3131 __ CallStub(&stub); 3146 __ CallStub(&stub);
3132 context()->Plug(v0); 3147 context()->Plug(v0);
3133 } 3148 }
3134 3149
3135 3150
3136 void FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) { 3151 void FullCodeGenerator::EmitMathCos(CallRuntime* expr) {
3137 // Load the argument on the stack and call the stub. 3152 // Load the argument on the stack and call the stub.
3138 TranscendentalCacheStub stub(TranscendentalCache::COS, 3153 TranscendentalCacheStub stub(TranscendentalCache::COS,
3139 TranscendentalCacheStub::TAGGED); 3154 TranscendentalCacheStub::TAGGED);
3155 ZoneList<Expression*>* args = expr->arguments();
3140 ASSERT(args->length() == 1); 3156 ASSERT(args->length() == 1);
3141 VisitForStackValue(args->at(0)); 3157 VisitForStackValue(args->at(0));
3142 __ mov(a0, result_register()); // Stub requires parameter in a0 and on tos. 3158 __ mov(a0, result_register()); // Stub requires parameter in a0 and on tos.
3143 __ CallStub(&stub); 3159 __ CallStub(&stub);
3144 context()->Plug(v0); 3160 context()->Plug(v0);
3145 } 3161 }
3146 3162
3147 3163
3148 void FullCodeGenerator::EmitMathLog(ZoneList<Expression*>* args) { 3164 void FullCodeGenerator::EmitMathLog(CallRuntime* expr) {
3149 // Load the argument on the stack and call the stub. 3165 // Load the argument on the stack and call the stub.
3150 TranscendentalCacheStub stub(TranscendentalCache::LOG, 3166 TranscendentalCacheStub stub(TranscendentalCache::LOG,
3151 TranscendentalCacheStub::TAGGED); 3167 TranscendentalCacheStub::TAGGED);
3168 ZoneList<Expression*>* args = expr->arguments();
3152 ASSERT(args->length() == 1); 3169 ASSERT(args->length() == 1);
3153 VisitForStackValue(args->at(0)); 3170 VisitForStackValue(args->at(0));
3154 __ mov(a0, result_register()); // Stub requires parameter in a0 and on tos. 3171 __ mov(a0, result_register()); // Stub requires parameter in a0 and on tos.
3155 __ CallStub(&stub); 3172 __ CallStub(&stub);
3156 context()->Plug(v0); 3173 context()->Plug(v0);
3157 } 3174 }
3158 3175
3159 3176
3160 void FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) { 3177 void FullCodeGenerator::EmitMathSqrt(CallRuntime* expr) {
3161 // Load the argument on the stack and call the runtime function. 3178 // Load the argument on the stack and call the runtime function.
3179 ZoneList<Expression*>* args = expr->arguments();
3162 ASSERT(args->length() == 1); 3180 ASSERT(args->length() == 1);
3163 VisitForStackValue(args->at(0)); 3181 VisitForStackValue(args->at(0));
3164 __ CallRuntime(Runtime::kMath_sqrt, 1); 3182 __ CallRuntime(Runtime::kMath_sqrt, 1);
3165 context()->Plug(v0); 3183 context()->Plug(v0);
3166 } 3184 }
3167 3185
3168 3186
3169 void FullCodeGenerator::EmitCallFunction(ZoneList<Expression*>* args) { 3187 void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
3188 ZoneList<Expression*>* args = expr->arguments();
3170 ASSERT(args->length() >= 2); 3189 ASSERT(args->length() >= 2);
3171 3190
3172 int arg_count = args->length() - 2; // 2 ~ receiver and function. 3191 int arg_count = args->length() - 2; // 2 ~ receiver and function.
3173 for (int i = 0; i < arg_count + 1; i++) { 3192 for (int i = 0; i < arg_count + 1; i++) {
3174 VisitForStackValue(args->at(i)); 3193 VisitForStackValue(args->at(i));
3175 } 3194 }
3176 VisitForAccumulatorValue(args->last()); // Function. 3195 VisitForAccumulatorValue(args->last()); // Function.
3177 3196
3178 // InvokeFunction requires the function in a1. Move it in there. 3197 // InvokeFunction requires the function in a1. Move it in there.
3179 __ mov(a1, result_register()); 3198 __ mov(a1, result_register());
3180 ParameterCount count(arg_count); 3199 ParameterCount count(arg_count);
3181 __ InvokeFunction(a1, count, CALL_FUNCTION, 3200 __ InvokeFunction(a1, count, CALL_FUNCTION,
3182 NullCallWrapper(), CALL_AS_METHOD); 3201 NullCallWrapper(), CALL_AS_METHOD);
3183 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 3202 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
3184 context()->Plug(v0); 3203 context()->Plug(v0);
3185 } 3204 }
3186 3205
3187 3206
3188 void FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) { 3207 void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) {
3189 RegExpConstructResultStub stub; 3208 RegExpConstructResultStub stub;
3209 ZoneList<Expression*>* args = expr->arguments();
3190 ASSERT(args->length() == 3); 3210 ASSERT(args->length() == 3);
3191 VisitForStackValue(args->at(0)); 3211 VisitForStackValue(args->at(0));
3192 VisitForStackValue(args->at(1)); 3212 VisitForStackValue(args->at(1));
3193 VisitForStackValue(args->at(2)); 3213 VisitForStackValue(args->at(2));
3194 __ CallStub(&stub); 3214 __ CallStub(&stub);
3195 context()->Plug(v0); 3215 context()->Plug(v0);
3196 } 3216 }
3197 3217
3198 3218
3199 void FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) { 3219 void FullCodeGenerator::EmitSwapElements(CallRuntime* expr) {
3220 ZoneList<Expression*>* args = expr->arguments();
3200 ASSERT(args->length() == 3); 3221 ASSERT(args->length() == 3);
3201 VisitForStackValue(args->at(0)); 3222 VisitForStackValue(args->at(0));
3202 VisitForStackValue(args->at(1)); 3223 VisitForStackValue(args->at(1));
3203 VisitForStackValue(args->at(2)); 3224 VisitForStackValue(args->at(2));
3204 Label done; 3225 Label done;
3205 Label slow_case; 3226 Label slow_case;
3206 Register object = a0; 3227 Register object = a0;
3207 Register index1 = a1; 3228 Register index1 = a1;
3208 Register index2 = a2; 3229 Register index2 = a2;
3209 Register elements = a3; 3230 Register elements = a3;
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
3286 __ jmp(&done); 3307 __ jmp(&done);
3287 3308
3288 __ bind(&slow_case); 3309 __ bind(&slow_case);
3289 __ CallRuntime(Runtime::kSwapElements, 3); 3310 __ CallRuntime(Runtime::kSwapElements, 3);
3290 3311
3291 __ bind(&done); 3312 __ bind(&done);
3292 context()->Plug(v0); 3313 context()->Plug(v0);
3293 } 3314 }
3294 3315
3295 3316
3296 void FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) { 3317 void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) {
3318 ZoneList<Expression*>* args = expr->arguments();
3297 ASSERT_EQ(2, args->length()); 3319 ASSERT_EQ(2, args->length());
3298 3320
3299 ASSERT_NE(NULL, args->at(0)->AsLiteral()); 3321 ASSERT_NE(NULL, args->at(0)->AsLiteral());
3300 int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value(); 3322 int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value();
3301 3323
3302 Handle<FixedArray> jsfunction_result_caches( 3324 Handle<FixedArray> jsfunction_result_caches(
3303 isolate()->global_context()->jsfunction_result_caches()); 3325 isolate()->global_context()->jsfunction_result_caches());
3304 if (jsfunction_result_caches->length() <= cache_id) { 3326 if (jsfunction_result_caches->length() <= cache_id) {
3305 __ Abort("Attempt to use undefined cache."); 3327 __ Abort("Attempt to use undefined cache.");
3306 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex); 3328 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex);
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
3339 __ bind(&not_found); 3361 __ bind(&not_found);
3340 // Call runtime to perform the lookup. 3362 // Call runtime to perform the lookup.
3341 __ Push(cache, key); 3363 __ Push(cache, key);
3342 __ CallRuntime(Runtime::kGetFromCache, 2); 3364 __ CallRuntime(Runtime::kGetFromCache, 2);
3343 3365
3344 __ bind(&done); 3366 __ bind(&done);
3345 context()->Plug(v0); 3367 context()->Plug(v0);
3346 } 3368 }
3347 3369
3348 3370
3349 void FullCodeGenerator::EmitIsRegExpEquivalent(ZoneList<Expression*>* args) { 3371 void FullCodeGenerator::EmitIsRegExpEquivalent(CallRuntime* expr) {
3372 ZoneList<Expression*>* args = expr->arguments();
3350 ASSERT_EQ(2, args->length()); 3373 ASSERT_EQ(2, args->length());
3351 3374
3352 Register right = v0; 3375 Register right = v0;
3353 Register left = a1; 3376 Register left = a1;
3354 Register tmp = a2; 3377 Register tmp = a2;
3355 Register tmp2 = a3; 3378 Register tmp2 = a3;
3356 3379
3357 VisitForStackValue(args->at(0)); 3380 VisitForStackValue(args->at(0));
3358 VisitForAccumulatorValue(args->at(1)); // Result (right) in v0. 3381 VisitForAccumulatorValue(args->at(1)); // Result (right) in v0.
3359 __ pop(left); 3382 __ pop(left);
(...skipping 16 matching lines...) Expand all
3376 __ LoadRoot(v0, Heap::kFalseValueRootIndex); 3399 __ LoadRoot(v0, Heap::kFalseValueRootIndex);
3377 __ jmp(&done); 3400 __ jmp(&done);
3378 __ bind(&ok); 3401 __ bind(&ok);
3379 __ LoadRoot(v0, Heap::kTrueValueRootIndex); 3402 __ LoadRoot(v0, Heap::kTrueValueRootIndex);
3380 __ bind(&done); 3403 __ bind(&done);
3381 3404
3382 context()->Plug(v0); 3405 context()->Plug(v0);
3383 } 3406 }
3384 3407
3385 3408
3386 void FullCodeGenerator::EmitHasCachedArrayIndex(ZoneList<Expression*>* args) { 3409 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) {
3410 ZoneList<Expression*>* args = expr->arguments();
3387 VisitForAccumulatorValue(args->at(0)); 3411 VisitForAccumulatorValue(args->at(0));
3388 3412
3389 Label materialize_true, materialize_false; 3413 Label materialize_true, materialize_false;
3390 Label* if_true = NULL; 3414 Label* if_true = NULL;
3391 Label* if_false = NULL; 3415 Label* if_false = NULL;
3392 Label* fall_through = NULL; 3416 Label* fall_through = NULL;
3393 context()->PrepareTest(&materialize_true, &materialize_false, 3417 context()->PrepareTest(&materialize_true, &materialize_false,
3394 &if_true, &if_false, &fall_through); 3418 &if_true, &if_false, &fall_through);
3395 3419
3396 __ lw(a0, FieldMemOperand(v0, String::kHashFieldOffset)); 3420 __ lw(a0, FieldMemOperand(v0, String::kHashFieldOffset));
3397 __ And(a0, a0, Operand(String::kContainsCachedArrayIndexMask)); 3421 __ And(a0, a0, Operand(String::kContainsCachedArrayIndexMask));
3398 3422
3399 PrepareForBailoutBeforeSplit(true, if_true, if_false); 3423 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3400 Split(eq, a0, Operand(zero_reg), if_true, if_false, fall_through); 3424 Split(eq, a0, Operand(zero_reg), if_true, if_false, fall_through);
3401 3425
3402 context()->Plug(if_true, if_false); 3426 context()->Plug(if_true, if_false);
3403 } 3427 }
3404 3428
3405 3429
3406 void FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList<Expression*>* args) { 3430 void FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) {
3431 ZoneList<Expression*>* args = expr->arguments();
3407 ASSERT(args->length() == 1); 3432 ASSERT(args->length() == 1);
3408 VisitForAccumulatorValue(args->at(0)); 3433 VisitForAccumulatorValue(args->at(0));
3409 3434
3410 if (FLAG_debug_code) { 3435 if (FLAG_debug_code) {
3411 __ AbortIfNotString(v0); 3436 __ AbortIfNotString(v0);
3412 } 3437 }
3413 3438
3414 __ lw(v0, FieldMemOperand(v0, String::kHashFieldOffset)); 3439 __ lw(v0, FieldMemOperand(v0, String::kHashFieldOffset));
3415 __ IndexFromHash(v0, v0); 3440 __ IndexFromHash(v0, v0);
3416 3441
3417 context()->Plug(v0); 3442 context()->Plug(v0);
3418 } 3443 }
3419 3444
3420 3445
3421 void FullCodeGenerator::EmitFastAsciiArrayJoin(ZoneList<Expression*>* args) { 3446 void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) {
3422 Label bailout, done, one_char_separator, long_separator, 3447 Label bailout, done, one_char_separator, long_separator,
3423 non_trivial_array, not_size_one_array, loop, 3448 non_trivial_array, not_size_one_array, loop,
3424 empty_separator_loop, one_char_separator_loop, 3449 empty_separator_loop, one_char_separator_loop,
3425 one_char_separator_loop_entry, long_separator_loop; 3450 one_char_separator_loop_entry, long_separator_loop;
3426 3451 ZoneList<Expression*>* args = expr->arguments();
3427 ASSERT(args->length() == 2); 3452 ASSERT(args->length() == 2);
3428 VisitForStackValue(args->at(1)); 3453 VisitForStackValue(args->at(1));
3429 VisitForAccumulatorValue(args->at(0)); 3454 VisitForAccumulatorValue(args->at(0));
3430 3455
3431 // All aliases of the same register have disjoint lifetimes. 3456 // All aliases of the same register have disjoint lifetimes.
3432 Register array = v0; 3457 Register array = v0;
3433 Register elements = no_reg; // Will be v0. 3458 Register elements = no_reg; // Will be v0.
3434 Register result = no_reg; // Will be v0. 3459 Register result = no_reg; // Will be v0.
3435 Register separator = a1; 3460 Register separator = a1;
3436 Register array_length = a2; 3461 Register array_length = a2;
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after
3752 context()->Plug(Heap::kUndefinedValueRootIndex); 3777 context()->Plug(Heap::kUndefinedValueRootIndex);
3753 break; 3778 break;
3754 } 3779 }
3755 3780
3756 case Token::NOT: { 3781 case Token::NOT: {
3757 Comment cmnt(masm_, "[ UnaryOperation (NOT)"); 3782 Comment cmnt(masm_, "[ UnaryOperation (NOT)");
3758 if (context()->IsEffect()) { 3783 if (context()->IsEffect()) {
3759 // Unary NOT has no side effects so it's only necessary to visit the 3784 // Unary NOT has no side effects so it's only necessary to visit the
3760 // subexpression. Match the optimizing compiler by not branching. 3785 // subexpression. Match the optimizing compiler by not branching.
3761 VisitForEffect(expr->expression()); 3786 VisitForEffect(expr->expression());
3787 } else if (context()->IsTest()) {
3788 const TestContext* test = TestContext::cast(context());
3789 // The labels are swapped for the recursive call.
3790 VisitForControl(expr->expression(),
3791 test->false_label(),
3792 test->true_label(),
3793 test->fall_through());
3794 context()->Plug(test->true_label(), test->false_label());
3762 } else { 3795 } else {
3763 Label materialize_true, materialize_false; 3796 // We handle value contexts explicitly rather than simply visiting
3764 Label* if_true = NULL; 3797 // for control and plugging the control flow into the context,
3765 Label* if_false = NULL; 3798 // because we need to prepare a pair of extra administrative AST ids
3766 Label* fall_through = NULL; 3799 // for the optimizing compiler.
3767 3800 ASSERT(context()->IsAccumulatorValue() || context()->IsStackValue());
3768 // Notice that the labels are swapped. 3801 Label materialize_true, materialize_false, done;
3769 context()->PrepareTest(&materialize_true, &materialize_false, 3802 VisitForControl(expr->expression(),
3770 &if_false, &if_true, &fall_through); 3803 &materialize_false,
3771 if (context()->IsTest()) ForwardBailoutToChild(expr); 3804 &materialize_true,
3772 VisitForControl(expr->expression(), if_true, if_false, fall_through); 3805 &materialize_true);
3773 context()->Plug(if_false, if_true); // Labels swapped. 3806 __ bind(&materialize_true);
3807 PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS);
3808 __ LoadRoot(v0, Heap::kTrueValueRootIndex);
3809 if (context()->IsStackValue()) __ push(v0);
3810 __ jmp(&done);
3811 __ bind(&materialize_false);
3812 PrepareForBailoutForId(expr->MaterializeFalseId(), NO_REGISTERS);
3813 __ LoadRoot(v0, Heap::kFalseValueRootIndex);
3814 if (context()->IsStackValue()) __ push(v0);
3815 __ bind(&done);
3774 } 3816 }
3775 break; 3817 break;
3776 } 3818 }
3777 3819
3778 case Token::TYPEOF: { 3820 case Token::TYPEOF: {
3779 Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); 3821 Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
3780 { StackValueContext context(this); 3822 { StackValueContext context(this);
3781 VisitForTypeofValue(expr->expression()); 3823 VisitForTypeofValue(expr->expression());
3782 } 3824 }
3783 __ CallRuntime(Runtime::kTypeof, 1); 3825 __ CallRuntime(Runtime::kTypeof, 1);
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after
4025 __ bind(&slow); 4067 __ bind(&slow);
4026 __ li(a0, Operand(proxy->name())); 4068 __ li(a0, Operand(proxy->name()));
4027 __ Push(cp, a0); 4069 __ Push(cp, a0);
4028 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); 4070 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
4029 PrepareForBailout(expr, TOS_REG); 4071 PrepareForBailout(expr, TOS_REG);
4030 __ bind(&done); 4072 __ bind(&done);
4031 4073
4032 context()->Plug(v0); 4074 context()->Plug(v0);
4033 } else { 4075 } else {
4034 // This expression cannot throw a reference error at the top level. 4076 // This expression cannot throw a reference error at the top level.
4035 VisitInCurrentContext(expr); 4077 VisitInDuplicateContext(expr);
4036 } 4078 }
4037 } 4079 }
4038 4080
4039 void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr, 4081 void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
4082 Expression* sub_expr,
4040 Handle<String> check) { 4083 Handle<String> check) {
4041 Label materialize_true, materialize_false; 4084 Label materialize_true, materialize_false;
4042 Label* if_true = NULL; 4085 Label* if_true = NULL;
4043 Label* if_false = NULL; 4086 Label* if_false = NULL;
4044 Label* fall_through = NULL; 4087 Label* fall_through = NULL;
4045 context()->PrepareTest(&materialize_true, &materialize_false, 4088 context()->PrepareTest(&materialize_true, &materialize_false,
4046 &if_true, &if_false, &fall_through); 4089 &if_true, &if_false, &fall_through);
4047 4090
4048 { AccumulatorValueContext context(this); 4091 { AccumulatorValueContext context(this);
4049 VisitForTypeofValue(expr); 4092 VisitForTypeofValue(sub_expr);
4050 } 4093 }
4051 PrepareForBailoutBeforeSplit(true, if_true, if_false); 4094 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
4052 4095
4053 if (check->Equals(isolate()->heap()->number_symbol())) { 4096 if (check->Equals(isolate()->heap()->number_symbol())) {
4054 __ JumpIfSmi(v0, if_true); 4097 __ JumpIfSmi(v0, if_true);
4055 __ lw(v0, FieldMemOperand(v0, HeapObject::kMapOffset)); 4098 __ lw(v0, FieldMemOperand(v0, HeapObject::kMapOffset));
4056 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); 4099 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
4057 Split(eq, v0, Operand(at), if_true, if_false, fall_through); 4100 Split(eq, v0, Operand(at), if_true, if_false, fall_through);
4058 } else if (check->Equals(isolate()->heap()->string_symbol())) { 4101 } else if (check->Equals(isolate()->heap()->string_symbol())) {
4059 __ JumpIfSmi(v0, if_false); 4102 __ JumpIfSmi(v0, if_false);
4060 // Check for undetectable objects => false. 4103 // Check for undetectable objects => false.
4061 __ GetObjectType(v0, v0, a1); 4104 __ GetObjectType(v0, v0, a1);
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
4127 Label* fall_through = NULL; 4170 Label* fall_through = NULL;
4128 context()->PrepareTest(&materialize_true, &materialize_false, 4171 context()->PrepareTest(&materialize_true, &materialize_false,
4129 &if_true, &if_false, &fall_through); 4172 &if_true, &if_false, &fall_through);
4130 4173
4131 Token::Value op = expr->op(); 4174 Token::Value op = expr->op();
4132 VisitForStackValue(expr->left()); 4175 VisitForStackValue(expr->left());
4133 switch (op) { 4176 switch (op) {
4134 case Token::IN: 4177 case Token::IN:
4135 VisitForStackValue(expr->right()); 4178 VisitForStackValue(expr->right());
4136 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); 4179 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
4137 PrepareForBailoutBeforeSplit(false, NULL, NULL); 4180 PrepareForBailoutBeforeSplit(expr, false, NULL, NULL);
4138 __ LoadRoot(t0, Heap::kTrueValueRootIndex); 4181 __ LoadRoot(t0, Heap::kTrueValueRootIndex);
4139 Split(eq, v0, Operand(t0), if_true, if_false, fall_through); 4182 Split(eq, v0, Operand(t0), if_true, if_false, fall_through);
4140 break; 4183 break;
4141 4184
4142 case Token::INSTANCEOF: { 4185 case Token::INSTANCEOF: {
4143 VisitForStackValue(expr->right()); 4186 VisitForStackValue(expr->right());
4144 InstanceofStub stub(InstanceofStub::kNoFlags); 4187 InstanceofStub stub(InstanceofStub::kNoFlags);
4145 __ CallStub(&stub); 4188 __ CallStub(&stub);
4146 PrepareForBailoutBeforeSplit(true, if_true, if_false); 4189 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
4147 // The stub returns 0 for true. 4190 // The stub returns 0 for true.
4148 Split(eq, v0, Operand(zero_reg), if_true, if_false, fall_through); 4191 Split(eq, v0, Operand(zero_reg), if_true, if_false, fall_through);
4149 break; 4192 break;
4150 } 4193 }
4151 4194
4152 default: { 4195 default: {
4153 VisitForAccumulatorValue(expr->right()); 4196 VisitForAccumulatorValue(expr->right());
4154 Condition cc = eq; 4197 Condition cc = eq;
4155 switch (op) { 4198 switch (op) {
4156 case Token::EQ_STRICT: 4199 case Token::EQ_STRICT:
(...skipping 27 matching lines...) Expand all
4184 __ Or(a2, a0, Operand(a1)); 4227 __ Or(a2, a0, Operand(a1));
4185 patch_site.EmitJumpIfNotSmi(a2, &slow_case); 4228 patch_site.EmitJumpIfNotSmi(a2, &slow_case);
4186 Split(cc, a1, Operand(a0), if_true, if_false, NULL); 4229 Split(cc, a1, Operand(a0), if_true, if_false, NULL);
4187 __ bind(&slow_case); 4230 __ bind(&slow_case);
4188 } 4231 }
4189 // Record position and call the compare IC. 4232 // Record position and call the compare IC.
4190 SetSourcePosition(expr->position()); 4233 SetSourcePosition(expr->position());
4191 Handle<Code> ic = CompareIC::GetUninitialized(op); 4234 Handle<Code> ic = CompareIC::GetUninitialized(op);
4192 __ Call(ic, RelocInfo::CODE_TARGET, expr->id()); 4235 __ Call(ic, RelocInfo::CODE_TARGET, expr->id());
4193 patch_site.EmitPatchInfo(); 4236 patch_site.EmitPatchInfo();
4194 PrepareForBailoutBeforeSplit(true, if_true, if_false); 4237 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
4195 Split(cc, v0, Operand(zero_reg), if_true, if_false, fall_through); 4238 Split(cc, v0, Operand(zero_reg), if_true, if_false, fall_through);
4196 } 4239 }
4197 } 4240 }
4198 4241
4199 // Convert the result of the comparison into one expected for this 4242 // Convert the result of the comparison into one expected for this
4200 // expression's context. 4243 // expression's context.
4201 context()->Plug(if_true, if_false); 4244 context()->Plug(if_true, if_false);
4202 } 4245 }
4203 4246
4204 4247
4205 void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr, 4248 void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr,
4206 Expression* sub_expr, 4249 Expression* sub_expr,
4207 NilValue nil) { 4250 NilValue nil) {
4208 Label materialize_true, materialize_false; 4251 Label materialize_true, materialize_false;
4209 Label* if_true = NULL; 4252 Label* if_true = NULL;
4210 Label* if_false = NULL; 4253 Label* if_false = NULL;
4211 Label* fall_through = NULL; 4254 Label* fall_through = NULL;
4212 context()->PrepareTest(&materialize_true, &materialize_false, 4255 context()->PrepareTest(&materialize_true, &materialize_false,
4213 &if_true, &if_false, &fall_through); 4256 &if_true, &if_false, &fall_through);
4214 4257
4215 VisitForAccumulatorValue(sub_expr); 4258 VisitForAccumulatorValue(sub_expr);
4216 PrepareForBailoutBeforeSplit(true, if_true, if_false); 4259 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
4217 Heap::RootListIndex nil_value = nil == kNullValue ? 4260 Heap::RootListIndex nil_value = nil == kNullValue ?
4218 Heap::kNullValueRootIndex : 4261 Heap::kNullValueRootIndex :
4219 Heap::kUndefinedValueRootIndex; 4262 Heap::kUndefinedValueRootIndex;
4220 __ mov(a0, result_register()); 4263 __ mov(a0, result_register());
4221 __ LoadRoot(a1, nil_value); 4264 __ LoadRoot(a1, nil_value);
4222 if (expr->op() == Token::EQ_STRICT) { 4265 if (expr->op() == Token::EQ_STRICT) {
4223 Split(eq, a0, Operand(a1), if_true, if_false, fall_through); 4266 Split(eq, a0, Operand(a1), if_true, if_false, fall_through);
4224 } else { 4267 } else {
4225 Heap::RootListIndex other_nil_value = nil == kNullValue ? 4268 Heap::RootListIndex other_nil_value = nil == kNullValue ?
4226 Heap::kUndefinedValueRootIndex : 4269 Heap::kUndefinedValueRootIndex :
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
4343 *context_length = 0; 4386 *context_length = 0;
4344 return previous_; 4387 return previous_;
4345 } 4388 }
4346 4389
4347 4390
4348 #undef __ 4391 #undef __
4349 4392
4350 } } // namespace v8::internal 4393 } } // namespace v8::internal
4351 4394
4352 #endif // V8_TARGET_ARCH_MIPS 4395 #endif // V8_TARGET_ARCH_MIPS
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698