OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
3313 __ bind(¬_found); | 3327 __ bind(¬_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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |