| 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 538 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 549 if (true_label_ != fall_through_) __ b(true_label_); | 549 if (true_label_ != fall_through_) __ b(true_label_); |
| 550 } else { | 550 } else { |
| 551 if (false_label_ != fall_through_) __ b(false_label_); | 551 if (false_label_ != fall_through_) __ b(false_label_); |
| 552 } | 552 } |
| 553 } | 553 } |
| 554 | 554 |
| 555 | 555 |
| 556 void FullCodeGenerator::DoTest(Label* if_true, | 556 void FullCodeGenerator::DoTest(Label* if_true, |
| 557 Label* if_false, | 557 Label* if_false, |
| 558 Label* fall_through) { | 558 Label* fall_through) { |
| 559 if (CpuFeatures::IsSupported(VFP3)) { | 559 if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) { |
| 560 CpuFeatures::Scope scope(VFP3); | 560 CpuFeatures::Scope scope(VFP3); |
| 561 // Emit the inlined tests assumed by the stub. | 561 // Emit the inlined tests assumed by the stub. |
| 562 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 562 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
| 563 __ cmp(result_register(), ip); | 563 __ cmp(result_register(), ip); |
| 564 __ b(eq, if_false); | 564 __ b(eq, if_false); |
| 565 __ LoadRoot(ip, Heap::kTrueValueRootIndex); | 565 __ LoadRoot(ip, Heap::kTrueValueRootIndex); |
| 566 __ cmp(result_register(), ip); | 566 __ cmp(result_register(), ip); |
| 567 __ b(eq, if_true); | 567 __ b(eq, if_true); |
| 568 __ LoadRoot(ip, Heap::kFalseValueRootIndex); | 568 __ LoadRoot(ip, Heap::kFalseValueRootIndex); |
| 569 __ cmp(result_register(), ip); | 569 __ cmp(result_register(), ip); |
| (...skipping 944 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1514 VisitForAccumulatorValue(property->key()); | 1514 VisitForAccumulatorValue(property->key()); |
| 1515 __ ldr(r1, MemOperand(sp, 0)); | 1515 __ ldr(r1, MemOperand(sp, 0)); |
| 1516 __ push(r0); | 1516 __ push(r0); |
| 1517 } else { | 1517 } else { |
| 1518 VisitForStackValue(property->obj()); | 1518 VisitForStackValue(property->obj()); |
| 1519 VisitForStackValue(property->key()); | 1519 VisitForStackValue(property->key()); |
| 1520 } | 1520 } |
| 1521 break; | 1521 break; |
| 1522 } | 1522 } |
| 1523 | 1523 |
| 1524 // For compound assignments we need another deoptimization point after the | |
| 1525 // variable/property load. | |
| 1526 if (expr->is_compound()) { | 1524 if (expr->is_compound()) { |
| 1527 { AccumulatorValueContext context(this); | 1525 { AccumulatorValueContext context(this); |
| 1528 switch (assign_type) { | 1526 switch (assign_type) { |
| 1529 case VARIABLE: | 1527 case VARIABLE: |
| 1530 EmitVariableLoad(expr->target()->AsVariableProxy()->var()); | 1528 EmitVariableLoad(expr->target()->AsVariableProxy()->var()); |
| 1531 PrepareForBailout(expr->target(), TOS_REG); | |
| 1532 break; | 1529 break; |
| 1533 case NAMED_PROPERTY: | 1530 case NAMED_PROPERTY: |
| 1534 EmitNamedPropertyLoad(property); | 1531 EmitNamedPropertyLoad(property); |
| 1535 PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG); | |
| 1536 break; | 1532 break; |
| 1537 case KEYED_PROPERTY: | 1533 case KEYED_PROPERTY: |
| 1538 EmitKeyedPropertyLoad(property); | 1534 EmitKeyedPropertyLoad(property); |
| 1539 PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG); | |
| 1540 break; | 1535 break; |
| 1541 } | 1536 } |
| 1542 } | 1537 } |
| 1543 | 1538 |
| 1539 // For property compound assignments we need another deoptimization |
| 1540 // point after the property load. |
| 1541 if (property != NULL) { |
| 1542 PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG); |
| 1543 } |
| 1544 |
| 1544 Token::Value op = expr->binary_op(); | 1545 Token::Value op = expr->binary_op(); |
| 1545 __ push(r0); // Left operand goes on the stack. | 1546 __ push(r0); // Left operand goes on the stack. |
| 1546 VisitForAccumulatorValue(expr->value()); | 1547 VisitForAccumulatorValue(expr->value()); |
| 1547 | 1548 |
| 1548 OverwriteMode mode = expr->value()->ResultOverwriteAllowed() | 1549 OverwriteMode mode = expr->value()->ResultOverwriteAllowed() |
| 1549 ? OVERWRITE_RIGHT | 1550 ? OVERWRITE_RIGHT |
| 1550 : NO_OVERWRITE; | 1551 : NO_OVERWRITE; |
| 1551 SetSourcePosition(expr->position() + 1); | 1552 SetSourcePosition(expr->position() + 1); |
| 1552 AccumulatorValueContext context(this); | 1553 AccumulatorValueContext context(this); |
| 1553 if (ShouldInlineSmiCase(op)) { | 1554 if (ShouldInlineSmiCase(op)) { |
| (...skipping 651 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2205 } | 2206 } |
| 2206 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); | 2207 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); |
| 2207 } else { | 2208 } else { |
| 2208 // Call to a keyed property. | 2209 // Call to a keyed property. |
| 2209 { PreservePositionScope scope(masm()->positions_recorder()); | 2210 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2210 VisitForStackValue(prop->obj()); | 2211 VisitForStackValue(prop->obj()); |
| 2211 } | 2212 } |
| 2212 EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET); | 2213 EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET); |
| 2213 } | 2214 } |
| 2214 } else { | 2215 } else { |
| 2216 // Call to some other expression. If the expression is an anonymous |
| 2217 // function literal not called in a loop, mark it as one that should |
| 2218 // also use the fast code generator. |
| 2219 FunctionLiteral* lit = fun->AsFunctionLiteral(); |
| 2220 if (lit != NULL && |
| 2221 lit->name()->Equals(isolate()->heap()->empty_string()) && |
| 2222 loop_depth() == 0) { |
| 2223 lit->set_try_full_codegen(true); |
| 2224 } |
| 2225 |
| 2215 { PreservePositionScope scope(masm()->positions_recorder()); | 2226 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2216 VisitForStackValue(fun); | 2227 VisitForStackValue(fun); |
| 2217 } | 2228 } |
| 2218 // Load global receiver object. | 2229 // Load global receiver object. |
| 2219 __ ldr(r1, GlobalObjectOperand()); | 2230 __ ldr(r1, GlobalObjectOperand()); |
| 2220 __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); | 2231 __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); |
| 2221 __ push(r1); | 2232 __ push(r1); |
| 2222 // Emit function call. | 2233 // Emit function call. |
| 2223 EmitCallWithStub(expr); | 2234 EmitCallWithStub(expr); |
| 2224 } | 2235 } |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2386 | 2397 |
| 2387 VisitForAccumulatorValue(args->at(0)); | 2398 VisitForAccumulatorValue(args->at(0)); |
| 2388 | 2399 |
| 2389 Label materialize_true, materialize_false; | 2400 Label materialize_true, materialize_false; |
| 2390 Label* if_true = NULL; | 2401 Label* if_true = NULL; |
| 2391 Label* if_false = NULL; | 2402 Label* if_false = NULL; |
| 2392 Label* fall_through = NULL; | 2403 Label* fall_through = NULL; |
| 2393 context()->PrepareTest(&materialize_true, &materialize_false, | 2404 context()->PrepareTest(&materialize_true, &materialize_false, |
| 2394 &if_true, &if_false, &fall_through); | 2405 &if_true, &if_false, &fall_through); |
| 2395 | 2406 |
| 2396 if (FLAG_debug_code) __ AbortIfSmi(r0); | 2407 // Just indicate false, as %_IsStringWrapperSafeForDefaultValueOf() is only |
| 2397 | 2408 // used in a few functions in runtime.js which should not normally be hit by |
| 2398 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); | 2409 // this compiler. |
| 2399 __ ldrb(ip, FieldMemOperand(r1, Map::kBitField2Offset)); | |
| 2400 __ tst(ip, Operand(1 << Map::kStringWrapperSafeForDefaultValueOf)); | |
| 2401 __ b(ne, if_true); | |
| 2402 | |
| 2403 // Check for fast case object. Generate false result for slow case object. | |
| 2404 __ ldr(r2, FieldMemOperand(r0, JSObject::kPropertiesOffset)); | |
| 2405 __ ldr(r2, FieldMemOperand(r2, HeapObject::kMapOffset)); | |
| 2406 __ LoadRoot(ip, Heap::kHashTableMapRootIndex); | |
| 2407 __ cmp(r2, ip); | |
| 2408 __ b(eq, if_false); | |
| 2409 | |
| 2410 // Look for valueOf symbol in the descriptor array, and indicate false if | |
| 2411 // found. The type is not checked, so if it is a transition it is a false | |
| 2412 // negative. | |
| 2413 __ ldr(r4, FieldMemOperand(r1, Map::kInstanceDescriptorsOffset)); | |
| 2414 __ ldr(r3, FieldMemOperand(r4, FixedArray::kLengthOffset)); | |
| 2415 // r4: descriptor array | |
| 2416 // r3: length of descriptor array | |
| 2417 // Calculate the end of the descriptor array. | |
| 2418 STATIC_ASSERT(kSmiTag == 0); | |
| 2419 STATIC_ASSERT(kSmiTagSize == 1); | |
| 2420 STATIC_ASSERT(kPointerSize == 4); | |
| 2421 __ add(r2, r4, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); | |
| 2422 __ add(r2, r2, Operand(r3, LSL, kPointerSizeLog2 - kSmiTagSize)); | |
| 2423 | |
| 2424 // Calculate location of the first key name. | |
| 2425 __ add(r4, | |
| 2426 r4, | |
| 2427 Operand(FixedArray::kHeaderSize - kHeapObjectTag + | |
| 2428 DescriptorArray::kFirstIndex * kPointerSize)); | |
| 2429 // Loop through all the keys in the descriptor array. If one of these is the | |
| 2430 // symbol valueOf the result is false. | |
| 2431 Label entry, loop; | |
| 2432 // The use of ip to store the valueOf symbol asumes that it is not otherwise | |
| 2433 // used in the loop below. | |
| 2434 __ mov(ip, Operand(FACTORY->value_of_symbol())); | |
| 2435 __ jmp(&entry); | |
| 2436 __ bind(&loop); | |
| 2437 __ ldr(r3, MemOperand(r4, 0)); | |
| 2438 __ cmp(r3, ip); | |
| 2439 __ b(eq, if_false); | |
| 2440 __ add(r4, r4, Operand(kPointerSize)); | |
| 2441 __ bind(&entry); | |
| 2442 __ cmp(r4, Operand(r2)); | |
| 2443 __ b(ne, &loop); | |
| 2444 | |
| 2445 // If a valueOf property is not found on the object check that it's | |
| 2446 // prototype is the un-modified String prototype. If not result is false. | |
| 2447 __ ldr(r2, FieldMemOperand(r1, Map::kPrototypeOffset)); | |
| 2448 __ tst(r2, Operand(kSmiTagMask)); | |
| 2449 __ b(eq, if_false); | |
| 2450 __ ldr(r2, FieldMemOperand(r2, HeapObject::kMapOffset)); | |
| 2451 __ ldr(r3, ContextOperand(cp, Context::GLOBAL_INDEX)); | |
| 2452 __ ldr(r3, FieldMemOperand(r3, GlobalObject::kGlobalContextOffset)); | |
| 2453 __ ldr(r3, ContextOperand(r3, Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX)); | |
| 2454 __ cmp(r2, r3); | |
| 2455 __ b(ne, if_false); | |
| 2456 | |
| 2457 // Set the bit in the map to indicate that it has been checked safe for | |
| 2458 // default valueOf and set true result. | |
| 2459 __ ldrb(r2, FieldMemOperand(r4, Map::kBitField2Offset)); | |
| 2460 __ orr(r2, r2, Operand(1 << Map::kStringWrapperSafeForDefaultValueOf)); | |
| 2461 __ strb(r2, FieldMemOperand(r4, Map::kBitField2Offset)); | |
| 2462 __ jmp(if_true); | |
| 2463 | |
| 2464 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); | 2410 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); |
| 2411 __ jmp(if_false); |
| 2465 context()->Plug(if_true, if_false); | 2412 context()->Plug(if_true, if_false); |
| 2466 } | 2413 } |
| 2467 | 2414 |
| 2468 | 2415 |
| 2469 void FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) { | 2416 void FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) { |
| 2470 ASSERT(args->length() == 1); | 2417 ASSERT(args->length() == 1); |
| 2471 | 2418 |
| 2472 VisitForAccumulatorValue(args->at(0)); | 2419 VisitForAccumulatorValue(args->at(0)); |
| 2473 | 2420 |
| 2474 Label materialize_true, materialize_false; | 2421 Label materialize_true, materialize_false; |
| (...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2709 __ bind(&slow_allocate_heapnumber); | 2656 __ bind(&slow_allocate_heapnumber); |
| 2710 // Allocate a heap number. | 2657 // Allocate a heap number. |
| 2711 __ CallRuntime(Runtime::kNumberAlloc, 0); | 2658 __ CallRuntime(Runtime::kNumberAlloc, 0); |
| 2712 __ mov(r4, Operand(r0)); | 2659 __ mov(r4, Operand(r0)); |
| 2713 | 2660 |
| 2714 __ bind(&heapnumber_allocated); | 2661 __ bind(&heapnumber_allocated); |
| 2715 | 2662 |
| 2716 // Convert 32 random bits in r0 to 0.(32 random bits) in a double | 2663 // Convert 32 random bits in r0 to 0.(32 random bits) in a double |
| 2717 // by computing: | 2664 // by computing: |
| 2718 // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)). | 2665 // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)). |
| 2719 if (CpuFeatures::IsSupported(VFP3)) { | 2666 if (isolate()->cpu_features()->IsSupported(VFP3)) { |
| 2720 __ PrepareCallCFunction(1, r0); | 2667 __ PrepareCallCFunction(0, r1); |
| 2721 __ mov(r0, Operand(ExternalReference::isolate_address())); | 2668 __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 0); |
| 2722 __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1); | |
| 2723 | 2669 |
| 2724 CpuFeatures::Scope scope(VFP3); | 2670 CpuFeatures::Scope scope(VFP3); |
| 2725 // 0x41300000 is the top half of 1.0 x 2^20 as a double. | 2671 // 0x41300000 is the top half of 1.0 x 2^20 as a double. |
| 2726 // Create this constant using mov/orr to avoid PC relative load. | 2672 // Create this constant using mov/orr to avoid PC relative load. |
| 2727 __ mov(r1, Operand(0x41000000)); | 2673 __ mov(r1, Operand(0x41000000)); |
| 2728 __ orr(r1, r1, Operand(0x300000)); | 2674 __ orr(r1, r1, Operand(0x300000)); |
| 2729 // Move 0x41300000xxxxxxxx (x = random bits) to VFP. | 2675 // Move 0x41300000xxxxxxxx (x = random bits) to VFP. |
| 2730 __ vmov(d7, r0, r1); | 2676 __ vmov(d7, r0, r1); |
| 2731 // Move 0x4130000000000000 to VFP. | 2677 // Move 0x4130000000000000 to VFP. |
| 2732 __ mov(r0, Operand(0, RelocInfo::NONE)); | 2678 __ mov(r0, Operand(0, RelocInfo::NONE)); |
| 2733 __ vmov(d8, r0, r1); | 2679 __ vmov(d8, r0, r1); |
| 2734 // Subtract and store the result in the heap number. | 2680 // Subtract and store the result in the heap number. |
| 2735 __ vsub(d7, d7, d8); | 2681 __ vsub(d7, d7, d8); |
| 2736 __ sub(r0, r4, Operand(kHeapObjectTag)); | 2682 __ sub(r0, r4, Operand(kHeapObjectTag)); |
| 2737 __ vstr(d7, r0, HeapNumber::kValueOffset); | 2683 __ vstr(d7, r0, HeapNumber::kValueOffset); |
| 2738 __ mov(r0, r4); | 2684 __ mov(r0, r4); |
| 2739 } else { | 2685 } else { |
| 2740 __ PrepareCallCFunction(2, r0); | |
| 2741 __ mov(r0, Operand(r4)); | 2686 __ mov(r0, Operand(r4)); |
| 2742 __ mov(r1, Operand(ExternalReference::isolate_address())); | 2687 __ PrepareCallCFunction(1, r1); |
| 2743 __ CallCFunction( | 2688 __ CallCFunction( |
| 2744 ExternalReference::fill_heap_number_with_random_function(isolate()), 2); | 2689 ExternalReference::fill_heap_number_with_random_function(isolate()), 1); |
| 2745 } | 2690 } |
| 2746 | 2691 |
| 2747 context()->Plug(r0); | 2692 context()->Plug(r0); |
| 2748 } | 2693 } |
| 2749 | 2694 |
| 2750 | 2695 |
| 2751 void FullCodeGenerator::EmitSubString(ZoneList<Expression*>* args) { | 2696 void FullCodeGenerator::EmitSubString(ZoneList<Expression*>* args) { |
| 2752 // Load the arguments on the stack and call the stub. | 2697 // Load the arguments on the stack and call the stub. |
| 2753 SubStringStub stub; | 2698 SubStringStub stub; |
| 2754 ASSERT(args->length() == 3); | 2699 ASSERT(args->length() == 3); |
| (...skipping 968 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3723 VisitForStackValue(prop->obj()); | 3668 VisitForStackValue(prop->obj()); |
| 3724 VisitForAccumulatorValue(prop->key()); | 3669 VisitForAccumulatorValue(prop->key()); |
| 3725 __ ldr(r1, MemOperand(sp, 0)); | 3670 __ ldr(r1, MemOperand(sp, 0)); |
| 3726 __ push(r0); | 3671 __ push(r0); |
| 3727 EmitKeyedPropertyLoad(prop); | 3672 EmitKeyedPropertyLoad(prop); |
| 3728 } | 3673 } |
| 3729 } | 3674 } |
| 3730 | 3675 |
| 3731 // We need a second deoptimization point after loading the value | 3676 // We need a second deoptimization point after loading the value |
| 3732 // in case evaluating the property load my have a side effect. | 3677 // in case evaluating the property load my have a side effect. |
| 3733 if (assign_type == VARIABLE) { | 3678 PrepareForBailout(expr->increment(), TOS_REG); |
| 3734 PrepareForBailout(expr->expression(), TOS_REG); | |
| 3735 } else { | |
| 3736 PrepareForBailout(expr->increment(), TOS_REG); | |
| 3737 } | |
| 3738 | 3679 |
| 3739 // Call ToNumber only if operand is not a smi. | 3680 // Call ToNumber only if operand is not a smi. |
| 3740 Label no_conversion; | 3681 Label no_conversion; |
| 3741 __ JumpIfSmi(r0, &no_conversion); | 3682 __ JumpIfSmi(r0, &no_conversion); |
| 3742 ToNumberStub convert_stub; | 3683 ToNumberStub convert_stub; |
| 3743 __ CallStub(&convert_stub); | 3684 __ CallStub(&convert_stub); |
| 3744 __ bind(&no_conversion); | 3685 __ bind(&no_conversion); |
| 3745 | 3686 |
| 3746 // Save result for postfix expressions. | 3687 // Save result for postfix expressions. |
| 3747 if (expr->is_postfix()) { | 3688 if (expr->is_postfix()) { |
| (...skipping 465 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4213 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. | 4154 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. |
| 4214 __ add(pc, r1, Operand(masm_->CodeObject())); | 4155 __ add(pc, r1, Operand(masm_->CodeObject())); |
| 4215 } | 4156 } |
| 4216 | 4157 |
| 4217 | 4158 |
| 4218 #undef __ | 4159 #undef __ |
| 4219 | 4160 |
| 4220 } } // namespace v8::internal | 4161 } } // namespace v8::internal |
| 4221 | 4162 |
| 4222 #endif // V8_TARGET_ARCH_ARM | 4163 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |