| 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 1439 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1450 __ mov(edx, Operand(esp, 0)); | 1450 __ mov(edx, Operand(esp, 0)); |
| 1451 __ push(eax); | 1451 __ push(eax); |
| 1452 } else { | 1452 } else { |
| 1453 VisitForStackValue(property->obj()); | 1453 VisitForStackValue(property->obj()); |
| 1454 VisitForStackValue(property->key()); | 1454 VisitForStackValue(property->key()); |
| 1455 } | 1455 } |
| 1456 break; | 1456 break; |
| 1457 } | 1457 } |
| 1458 } | 1458 } |
| 1459 | 1459 |
| 1460 // For compound assignments we need another deoptimization point after the |
| 1461 // variable/property load. |
| 1460 if (expr->is_compound()) { | 1462 if (expr->is_compound()) { |
| 1461 { AccumulatorValueContext context(this); | 1463 { AccumulatorValueContext context(this); |
| 1462 switch (assign_type) { | 1464 switch (assign_type) { |
| 1463 case VARIABLE: | 1465 case VARIABLE: |
| 1464 EmitVariableLoad(expr->target()->AsVariableProxy()->var()); | 1466 EmitVariableLoad(expr->target()->AsVariableProxy()->var()); |
| 1467 PrepareForBailout(expr->target(), TOS_REG); |
| 1465 break; | 1468 break; |
| 1466 case NAMED_PROPERTY: | 1469 case NAMED_PROPERTY: |
| 1467 EmitNamedPropertyLoad(property); | 1470 EmitNamedPropertyLoad(property); |
| 1471 PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG); |
| 1468 break; | 1472 break; |
| 1469 case KEYED_PROPERTY: | 1473 case KEYED_PROPERTY: |
| 1470 EmitKeyedPropertyLoad(property); | 1474 EmitKeyedPropertyLoad(property); |
| 1475 PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG); |
| 1471 break; | 1476 break; |
| 1472 } | 1477 } |
| 1473 } | 1478 } |
| 1474 | 1479 |
| 1475 // For property compound assignments we need another deoptimization | |
| 1476 // point after the property load. | |
| 1477 if (property != NULL) { | |
| 1478 PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG); | |
| 1479 } | |
| 1480 | |
| 1481 Token::Value op = expr->binary_op(); | 1480 Token::Value op = expr->binary_op(); |
| 1482 __ push(eax); // Left operand goes on the stack. | 1481 __ push(eax); // Left operand goes on the stack. |
| 1483 VisitForAccumulatorValue(expr->value()); | 1482 VisitForAccumulatorValue(expr->value()); |
| 1484 | 1483 |
| 1485 OverwriteMode mode = expr->value()->ResultOverwriteAllowed() | 1484 OverwriteMode mode = expr->value()->ResultOverwriteAllowed() |
| 1486 ? OVERWRITE_RIGHT | 1485 ? OVERWRITE_RIGHT |
| 1487 : NO_OVERWRITE; | 1486 : NO_OVERWRITE; |
| 1488 SetSourcePosition(expr->position() + 1); | 1487 SetSourcePosition(expr->position() + 1); |
| 1489 AccumulatorValueContext context(this); | 1488 AccumulatorValueContext context(this); |
| 1490 if (ShouldInlineSmiCase(op)) { | 1489 if (ShouldInlineSmiCase(op)) { |
| (...skipping 624 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2115 } | 2114 } |
| 2116 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); | 2115 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); |
| 2117 } else { | 2116 } else { |
| 2118 // Call to a keyed property. | 2117 // Call to a keyed property. |
| 2119 { PreservePositionScope scope(masm()->positions_recorder()); | 2118 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2120 VisitForStackValue(prop->obj()); | 2119 VisitForStackValue(prop->obj()); |
| 2121 } | 2120 } |
| 2122 EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET); | 2121 EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET); |
| 2123 } | 2122 } |
| 2124 } else { | 2123 } else { |
| 2125 // Call to some other expression. If the expression is an anonymous | |
| 2126 // function literal not called in a loop, mark it as one that should | |
| 2127 // also use the full code generator. | |
| 2128 FunctionLiteral* lit = fun->AsFunctionLiteral(); | |
| 2129 if (lit != NULL && | |
| 2130 lit->name()->Equals(isolate()->heap()->empty_string()) && | |
| 2131 loop_depth() == 0) { | |
| 2132 lit->set_try_full_codegen(true); | |
| 2133 } | |
| 2134 { PreservePositionScope scope(masm()->positions_recorder()); | 2124 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2135 VisitForStackValue(fun); | 2125 VisitForStackValue(fun); |
| 2136 } | 2126 } |
| 2137 // Load global receiver object. | 2127 // Load global receiver object. |
| 2138 __ mov(ebx, GlobalObjectOperand()); | 2128 __ mov(ebx, GlobalObjectOperand()); |
| 2139 __ push(FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset)); | 2129 __ push(FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset)); |
| 2140 // Emit function call. | 2130 // Emit function call. |
| 2141 EmitCallWithStub(expr); | 2131 EmitCallWithStub(expr); |
| 2142 } | 2132 } |
| 2143 | 2133 |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2305 | 2295 |
| 2306 VisitForAccumulatorValue(args->at(0)); | 2296 VisitForAccumulatorValue(args->at(0)); |
| 2307 | 2297 |
| 2308 Label materialize_true, materialize_false; | 2298 Label materialize_true, materialize_false; |
| 2309 Label* if_true = NULL; | 2299 Label* if_true = NULL; |
| 2310 Label* if_false = NULL; | 2300 Label* if_false = NULL; |
| 2311 Label* fall_through = NULL; | 2301 Label* fall_through = NULL; |
| 2312 context()->PrepareTest(&materialize_true, &materialize_false, | 2302 context()->PrepareTest(&materialize_true, &materialize_false, |
| 2313 &if_true, &if_false, &fall_through); | 2303 &if_true, &if_false, &fall_through); |
| 2314 | 2304 |
| 2315 // TODO(3110205): Implement this. | 2305 if (FLAG_debug_code) __ AbortIfSmi(eax); |
| 2316 // Currently unimplemented. Emit false, a safe choice. | 2306 |
| 2307 // Check whether this map has already been checked to be safe for default |
| 2308 // valueOf. |
| 2309 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
| 2310 __ test_b(FieldOperand(ebx, Map::kBitField2Offset), |
| 2311 1 << Map::kStringWrapperSafeForDefaultValueOf); |
| 2312 __ j(not_zero, if_true); |
| 2313 |
| 2314 // Check for fast case object. Return false for slow case objects. |
| 2315 __ mov(ecx, FieldOperand(eax, JSObject::kPropertiesOffset)); |
| 2316 __ mov(ecx, FieldOperand(ecx, HeapObject::kMapOffset)); |
| 2317 __ cmp(ecx, FACTORY->hash_table_map()); |
| 2318 __ j(equal, if_false); |
| 2319 |
| 2320 // Look for valueOf symbol in the descriptor array, and indicate false if |
| 2321 // found. The type is not checked, so if it is a transition it is a false |
| 2322 // negative. |
| 2323 __ mov(ebx, FieldOperand(ebx, Map::kInstanceDescriptorsOffset)); |
| 2324 __ mov(ecx, FieldOperand(ebx, FixedArray::kLengthOffset)); |
| 2325 // ebx: descriptor array |
| 2326 // ecx: length of descriptor array |
| 2327 // Calculate the end of the descriptor array. |
| 2328 STATIC_ASSERT(kSmiTag == 0); |
| 2329 STATIC_ASSERT(kSmiTagSize == 1); |
| 2330 STATIC_ASSERT(kPointerSize == 4); |
| 2331 __ lea(ecx, Operand(ebx, ecx, times_2, FixedArray::kHeaderSize)); |
| 2332 // Calculate location of the first key name. |
| 2333 __ add(Operand(ebx), |
| 2334 Immediate(FixedArray::kHeaderSize + |
| 2335 DescriptorArray::kFirstIndex * kPointerSize)); |
| 2336 // Loop through all the keys in the descriptor array. If one of these is the |
| 2337 // symbol valueOf the result is false. |
| 2338 Label entry, loop; |
| 2339 __ jmp(&entry); |
| 2340 __ bind(&loop); |
| 2341 __ mov(edx, FieldOperand(ebx, 0)); |
| 2342 __ cmp(edx, FACTORY->value_of_symbol()); |
| 2343 __ j(equal, if_false); |
| 2344 __ add(Operand(ebx), Immediate(kPointerSize)); |
| 2345 __ bind(&entry); |
| 2346 __ cmp(ebx, Operand(ecx)); |
| 2347 __ j(not_equal, &loop); |
| 2348 |
| 2349 // Reload map as register ebx was used as temporary above. |
| 2350 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
| 2351 |
| 2352 // If a valueOf property is not found on the object check that it's |
| 2353 // prototype is the un-modified String prototype. If not result is false. |
| 2354 __ mov(ecx, FieldOperand(ebx, Map::kPrototypeOffset)); |
| 2355 __ test(ecx, Immediate(kSmiTagMask)); |
| 2356 __ j(zero, if_false); |
| 2357 __ mov(ecx, FieldOperand(ecx, HeapObject::kMapOffset)); |
| 2358 __ mov(edx, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX))); |
| 2359 __ mov(edx, |
| 2360 FieldOperand(edx, GlobalObject::kGlobalContextOffset)); |
| 2361 __ cmp(ecx, |
| 2362 ContextOperand(edx, |
| 2363 Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX)); |
| 2364 __ j(not_equal, if_false); |
| 2365 // Set the bit in the map to indicate that it has been checked safe for |
| 2366 // default valueOf and set true result. |
| 2367 __ or_(FieldOperand(ebx, Map::kBitField2Offset), |
| 2368 Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf)); |
| 2369 __ jmp(if_true); |
| 2370 |
| 2317 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); | 2371 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); |
| 2318 __ jmp(if_false); | |
| 2319 context()->Plug(if_true, if_false); | 2372 context()->Plug(if_true, if_false); |
| 2320 } | 2373 } |
| 2321 | 2374 |
| 2322 | 2375 |
| 2323 void FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) { | 2376 void FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) { |
| 2324 ASSERT(args->length() == 1); | 2377 ASSERT(args->length() == 1); |
| 2325 | 2378 |
| 2326 VisitForAccumulatorValue(args->at(0)); | 2379 VisitForAccumulatorValue(args->at(0)); |
| 2327 | 2380 |
| 2328 Label materialize_true, materialize_false; | 2381 Label materialize_true, materialize_false; |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2564 __ AllocateHeapNumber(edi, ebx, ecx, &slow_allocate_heapnumber); | 2617 __ AllocateHeapNumber(edi, ebx, ecx, &slow_allocate_heapnumber); |
| 2565 __ jmp(&heapnumber_allocated); | 2618 __ jmp(&heapnumber_allocated); |
| 2566 | 2619 |
| 2567 __ bind(&slow_allocate_heapnumber); | 2620 __ bind(&slow_allocate_heapnumber); |
| 2568 // Allocate a heap number. | 2621 // Allocate a heap number. |
| 2569 __ CallRuntime(Runtime::kNumberAlloc, 0); | 2622 __ CallRuntime(Runtime::kNumberAlloc, 0); |
| 2570 __ mov(edi, eax); | 2623 __ mov(edi, eax); |
| 2571 | 2624 |
| 2572 __ bind(&heapnumber_allocated); | 2625 __ bind(&heapnumber_allocated); |
| 2573 | 2626 |
| 2574 __ PrepareCallCFunction(0, ebx); | 2627 __ PrepareCallCFunction(1, ebx); |
| 2628 __ mov(Operand(esp, 0), Immediate(ExternalReference::isolate_address())); |
| 2575 __ CallCFunction(ExternalReference::random_uint32_function(isolate()), | 2629 __ CallCFunction(ExternalReference::random_uint32_function(isolate()), |
| 2576 0); | 2630 1); |
| 2577 | 2631 |
| 2578 // Convert 32 random bits in eax to 0.(32 random bits) in a double | 2632 // Convert 32 random bits in eax to 0.(32 random bits) in a double |
| 2579 // by computing: | 2633 // by computing: |
| 2580 // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)). | 2634 // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)). |
| 2581 // This is implemented on both SSE2 and FPU. | 2635 // This is implemented on both SSE2 and FPU. |
| 2582 if (isolate()->cpu_features()->IsSupported(SSE2)) { | 2636 if (CpuFeatures::IsSupported(SSE2)) { |
| 2583 CpuFeatures::Scope fscope(SSE2); | 2637 CpuFeatures::Scope fscope(SSE2); |
| 2584 __ mov(ebx, Immediate(0x49800000)); // 1.0 x 2^20 as single. | 2638 __ mov(ebx, Immediate(0x49800000)); // 1.0 x 2^20 as single. |
| 2585 __ movd(xmm1, Operand(ebx)); | 2639 __ movd(xmm1, Operand(ebx)); |
| 2586 __ movd(xmm0, Operand(eax)); | 2640 __ movd(xmm0, Operand(eax)); |
| 2587 __ cvtss2sd(xmm1, xmm1); | 2641 __ cvtss2sd(xmm1, xmm1); |
| 2588 __ pxor(xmm0, xmm1); | 2642 __ pxor(xmm0, xmm1); |
| 2589 __ subsd(xmm0, xmm1); | 2643 __ subsd(xmm0, xmm1); |
| 2590 __ movdbl(FieldOperand(edi, HeapNumber::kValueOffset), xmm0); | 2644 __ movdbl(FieldOperand(edi, HeapNumber::kValueOffset), xmm0); |
| 2591 } else { | 2645 } else { |
| 2592 // 0x4130000000000000 is 1.0 x 2^20 as a double. | 2646 // 0x4130000000000000 is 1.0 x 2^20 as a double. |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2647 context()->Plug(eax); | 2701 context()->Plug(eax); |
| 2648 } | 2702 } |
| 2649 | 2703 |
| 2650 | 2704 |
| 2651 void FullCodeGenerator::EmitMathPow(ZoneList<Expression*>* args) { | 2705 void FullCodeGenerator::EmitMathPow(ZoneList<Expression*>* args) { |
| 2652 // Load the arguments on the stack and call the runtime function. | 2706 // Load the arguments on the stack and call the runtime function. |
| 2653 ASSERT(args->length() == 2); | 2707 ASSERT(args->length() == 2); |
| 2654 VisitForStackValue(args->at(0)); | 2708 VisitForStackValue(args->at(0)); |
| 2655 VisitForStackValue(args->at(1)); | 2709 VisitForStackValue(args->at(1)); |
| 2656 | 2710 |
| 2657 if (isolate()->cpu_features()->IsSupported(SSE2)) { | 2711 if (CpuFeatures::IsSupported(SSE2)) { |
| 2658 MathPowStub stub; | 2712 MathPowStub stub; |
| 2659 __ CallStub(&stub); | 2713 __ CallStub(&stub); |
| 2660 } else { | 2714 } else { |
| 2661 __ CallRuntime(Runtime::kMath_pow, 2); | 2715 __ CallRuntime(Runtime::kMath_pow, 2); |
| 2662 } | 2716 } |
| 2663 context()->Plug(eax); | 2717 context()->Plug(eax); |
| 2664 } | 2718 } |
| 2665 | 2719 |
| 2666 | 2720 |
| 2667 void FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) { | 2721 void FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) { |
| (...skipping 943 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3611 VisitForStackValue(prop->obj()); | 3665 VisitForStackValue(prop->obj()); |
| 3612 VisitForAccumulatorValue(prop->key()); | 3666 VisitForAccumulatorValue(prop->key()); |
| 3613 __ mov(edx, Operand(esp, 0)); | 3667 __ mov(edx, Operand(esp, 0)); |
| 3614 __ push(eax); | 3668 __ push(eax); |
| 3615 EmitKeyedPropertyLoad(prop); | 3669 EmitKeyedPropertyLoad(prop); |
| 3616 } | 3670 } |
| 3617 } | 3671 } |
| 3618 | 3672 |
| 3619 // We need a second deoptimization point after loading the value | 3673 // We need a second deoptimization point after loading the value |
| 3620 // in case evaluating the property load my have a side effect. | 3674 // in case evaluating the property load my have a side effect. |
| 3621 PrepareForBailout(expr->increment(), TOS_REG); | 3675 if (assign_type == VARIABLE) { |
| 3676 PrepareForBailout(expr->expression(), TOS_REG); |
| 3677 } else { |
| 3678 PrepareForBailout(expr->increment(), TOS_REG); |
| 3679 } |
| 3622 | 3680 |
| 3623 // Call ToNumber only if operand is not a smi. | 3681 // Call ToNumber only if operand is not a smi. |
| 3624 NearLabel no_conversion; | 3682 NearLabel no_conversion; |
| 3625 if (ShouldInlineSmiCase(expr->op())) { | 3683 if (ShouldInlineSmiCase(expr->op())) { |
| 3626 __ test(eax, Immediate(kSmiTagMask)); | 3684 __ test(eax, Immediate(kSmiTagMask)); |
| 3627 __ j(zero, &no_conversion); | 3685 __ j(zero, &no_conversion); |
| 3628 } | 3686 } |
| 3629 ToNumberStub convert_stub; | 3687 ToNumberStub convert_stub; |
| 3630 __ CallStub(&convert_stub); | 3688 __ CallStub(&convert_stub); |
| 3631 __ bind(&no_conversion); | 3689 __ bind(&no_conversion); |
| (...skipping 498 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4130 // And return. | 4188 // And return. |
| 4131 __ ret(0); | 4189 __ ret(0); |
| 4132 } | 4190 } |
| 4133 | 4191 |
| 4134 | 4192 |
| 4135 #undef __ | 4193 #undef __ |
| 4136 | 4194 |
| 4137 } } // namespace v8::internal | 4195 } } // namespace v8::internal |
| 4138 | 4196 |
| 4139 #endif // V8_TARGET_ARCH_IA32 | 4197 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |