| 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. | |
| 1462 if (expr->is_compound()) { | 1460 if (expr->is_compound()) { |
| 1463 { AccumulatorValueContext context(this); | 1461 { AccumulatorValueContext context(this); |
| 1464 switch (assign_type) { | 1462 switch (assign_type) { |
| 1465 case VARIABLE: | 1463 case VARIABLE: |
| 1466 EmitVariableLoad(expr->target()->AsVariableProxy()->var()); | 1464 EmitVariableLoad(expr->target()->AsVariableProxy()->var()); |
| 1467 PrepareForBailout(expr->target(), TOS_REG); | |
| 1468 break; | 1465 break; |
| 1469 case NAMED_PROPERTY: | 1466 case NAMED_PROPERTY: |
| 1470 EmitNamedPropertyLoad(property); | 1467 EmitNamedPropertyLoad(property); |
| 1471 PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG); | |
| 1472 break; | 1468 break; |
| 1473 case KEYED_PROPERTY: | 1469 case KEYED_PROPERTY: |
| 1474 EmitKeyedPropertyLoad(property); | 1470 EmitKeyedPropertyLoad(property); |
| 1475 PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG); | |
| 1476 break; | 1471 break; |
| 1477 } | 1472 } |
| 1478 } | 1473 } |
| 1479 | 1474 |
| 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 |
| 1480 Token::Value op = expr->binary_op(); | 1481 Token::Value op = expr->binary_op(); |
| 1481 __ push(eax); // Left operand goes on the stack. | 1482 __ push(eax); // Left operand goes on the stack. |
| 1482 VisitForAccumulatorValue(expr->value()); | 1483 VisitForAccumulatorValue(expr->value()); |
| 1483 | 1484 |
| 1484 OverwriteMode mode = expr->value()->ResultOverwriteAllowed() | 1485 OverwriteMode mode = expr->value()->ResultOverwriteAllowed() |
| 1485 ? OVERWRITE_RIGHT | 1486 ? OVERWRITE_RIGHT |
| 1486 : NO_OVERWRITE; | 1487 : NO_OVERWRITE; |
| 1487 SetSourcePosition(expr->position() + 1); | 1488 SetSourcePosition(expr->position() + 1); |
| 1488 AccumulatorValueContext context(this); | 1489 AccumulatorValueContext context(this); |
| 1489 if (ShouldInlineSmiCase(op)) { | 1490 if (ShouldInlineSmiCase(op)) { |
| (...skipping 624 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2114 } | 2115 } |
| 2115 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); | 2116 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); |
| 2116 } else { | 2117 } else { |
| 2117 // Call to a keyed property. | 2118 // Call to a keyed property. |
| 2118 { PreservePositionScope scope(masm()->positions_recorder()); | 2119 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2119 VisitForStackValue(prop->obj()); | 2120 VisitForStackValue(prop->obj()); |
| 2120 } | 2121 } |
| 2121 EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET); | 2122 EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET); |
| 2122 } | 2123 } |
| 2123 } else { | 2124 } 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 } |
| 2124 { PreservePositionScope scope(masm()->positions_recorder()); | 2134 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2125 VisitForStackValue(fun); | 2135 VisitForStackValue(fun); |
| 2126 } | 2136 } |
| 2127 // Load global receiver object. | 2137 // Load global receiver object. |
| 2128 __ mov(ebx, GlobalObjectOperand()); | 2138 __ mov(ebx, GlobalObjectOperand()); |
| 2129 __ push(FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset)); | 2139 __ push(FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset)); |
| 2130 // Emit function call. | 2140 // Emit function call. |
| 2131 EmitCallWithStub(expr); | 2141 EmitCallWithStub(expr); |
| 2132 } | 2142 } |
| 2133 | 2143 |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2295 | 2305 |
| 2296 VisitForAccumulatorValue(args->at(0)); | 2306 VisitForAccumulatorValue(args->at(0)); |
| 2297 | 2307 |
| 2298 Label materialize_true, materialize_false; | 2308 Label materialize_true, materialize_false; |
| 2299 Label* if_true = NULL; | 2309 Label* if_true = NULL; |
| 2300 Label* if_false = NULL; | 2310 Label* if_false = NULL; |
| 2301 Label* fall_through = NULL; | 2311 Label* fall_through = NULL; |
| 2302 context()->PrepareTest(&materialize_true, &materialize_false, | 2312 context()->PrepareTest(&materialize_true, &materialize_false, |
| 2303 &if_true, &if_false, &fall_through); | 2313 &if_true, &if_false, &fall_through); |
| 2304 | 2314 |
| 2305 if (FLAG_debug_code) __ AbortIfSmi(eax); | 2315 // TODO(3110205): Implement this. |
| 2306 | 2316 // Currently unimplemented. Emit false, a safe choice. |
| 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 | |
| 2371 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); | 2317 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); |
| 2318 __ jmp(if_false); |
| 2372 context()->Plug(if_true, if_false); | 2319 context()->Plug(if_true, if_false); |
| 2373 } | 2320 } |
| 2374 | 2321 |
| 2375 | 2322 |
| 2376 void FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) { | 2323 void FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) { |
| 2377 ASSERT(args->length() == 1); | 2324 ASSERT(args->length() == 1); |
| 2378 | 2325 |
| 2379 VisitForAccumulatorValue(args->at(0)); | 2326 VisitForAccumulatorValue(args->at(0)); |
| 2380 | 2327 |
| 2381 Label materialize_true, materialize_false; | 2328 Label materialize_true, materialize_false; |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2617 __ AllocateHeapNumber(edi, ebx, ecx, &slow_allocate_heapnumber); | 2564 __ AllocateHeapNumber(edi, ebx, ecx, &slow_allocate_heapnumber); |
| 2618 __ jmp(&heapnumber_allocated); | 2565 __ jmp(&heapnumber_allocated); |
| 2619 | 2566 |
| 2620 __ bind(&slow_allocate_heapnumber); | 2567 __ bind(&slow_allocate_heapnumber); |
| 2621 // Allocate a heap number. | 2568 // Allocate a heap number. |
| 2622 __ CallRuntime(Runtime::kNumberAlloc, 0); | 2569 __ CallRuntime(Runtime::kNumberAlloc, 0); |
| 2623 __ mov(edi, eax); | 2570 __ mov(edi, eax); |
| 2624 | 2571 |
| 2625 __ bind(&heapnumber_allocated); | 2572 __ bind(&heapnumber_allocated); |
| 2626 | 2573 |
| 2627 __ PrepareCallCFunction(1, ebx); | 2574 __ PrepareCallCFunction(0, ebx); |
| 2628 __ mov(Operand(esp, 0), Immediate(ExternalReference::isolate_address())); | |
| 2629 __ CallCFunction(ExternalReference::random_uint32_function(isolate()), | 2575 __ CallCFunction(ExternalReference::random_uint32_function(isolate()), |
| 2630 1); | 2576 0); |
| 2631 | 2577 |
| 2632 // Convert 32 random bits in eax to 0.(32 random bits) in a double | 2578 // Convert 32 random bits in eax to 0.(32 random bits) in a double |
| 2633 // by computing: | 2579 // by computing: |
| 2634 // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)). | 2580 // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)). |
| 2635 // This is implemented on both SSE2 and FPU. | 2581 // This is implemented on both SSE2 and FPU. |
| 2636 if (CpuFeatures::IsSupported(SSE2)) { | 2582 if (isolate()->cpu_features()->IsSupported(SSE2)) { |
| 2637 CpuFeatures::Scope fscope(SSE2); | 2583 CpuFeatures::Scope fscope(SSE2); |
| 2638 __ mov(ebx, Immediate(0x49800000)); // 1.0 x 2^20 as single. | 2584 __ mov(ebx, Immediate(0x49800000)); // 1.0 x 2^20 as single. |
| 2639 __ movd(xmm1, Operand(ebx)); | 2585 __ movd(xmm1, Operand(ebx)); |
| 2640 __ movd(xmm0, Operand(eax)); | 2586 __ movd(xmm0, Operand(eax)); |
| 2641 __ cvtss2sd(xmm1, xmm1); | 2587 __ cvtss2sd(xmm1, xmm1); |
| 2642 __ pxor(xmm0, xmm1); | 2588 __ pxor(xmm0, xmm1); |
| 2643 __ subsd(xmm0, xmm1); | 2589 __ subsd(xmm0, xmm1); |
| 2644 __ movdbl(FieldOperand(edi, HeapNumber::kValueOffset), xmm0); | 2590 __ movdbl(FieldOperand(edi, HeapNumber::kValueOffset), xmm0); |
| 2645 } else { | 2591 } else { |
| 2646 // 0x4130000000000000 is 1.0 x 2^20 as a double. | 2592 // 0x4130000000000000 is 1.0 x 2^20 as a double. |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2701 context()->Plug(eax); | 2647 context()->Plug(eax); |
| 2702 } | 2648 } |
| 2703 | 2649 |
| 2704 | 2650 |
| 2705 void FullCodeGenerator::EmitMathPow(ZoneList<Expression*>* args) { | 2651 void FullCodeGenerator::EmitMathPow(ZoneList<Expression*>* args) { |
| 2706 // Load the arguments on the stack and call the runtime function. | 2652 // Load the arguments on the stack and call the runtime function. |
| 2707 ASSERT(args->length() == 2); | 2653 ASSERT(args->length() == 2); |
| 2708 VisitForStackValue(args->at(0)); | 2654 VisitForStackValue(args->at(0)); |
| 2709 VisitForStackValue(args->at(1)); | 2655 VisitForStackValue(args->at(1)); |
| 2710 | 2656 |
| 2711 if (CpuFeatures::IsSupported(SSE2)) { | 2657 if (isolate()->cpu_features()->IsSupported(SSE2)) { |
| 2712 MathPowStub stub; | 2658 MathPowStub stub; |
| 2713 __ CallStub(&stub); | 2659 __ CallStub(&stub); |
| 2714 } else { | 2660 } else { |
| 2715 __ CallRuntime(Runtime::kMath_pow, 2); | 2661 __ CallRuntime(Runtime::kMath_pow, 2); |
| 2716 } | 2662 } |
| 2717 context()->Plug(eax); | 2663 context()->Plug(eax); |
| 2718 } | 2664 } |
| 2719 | 2665 |
| 2720 | 2666 |
| 2721 void FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) { | 2667 void FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) { |
| (...skipping 943 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3665 VisitForStackValue(prop->obj()); | 3611 VisitForStackValue(prop->obj()); |
| 3666 VisitForAccumulatorValue(prop->key()); | 3612 VisitForAccumulatorValue(prop->key()); |
| 3667 __ mov(edx, Operand(esp, 0)); | 3613 __ mov(edx, Operand(esp, 0)); |
| 3668 __ push(eax); | 3614 __ push(eax); |
| 3669 EmitKeyedPropertyLoad(prop); | 3615 EmitKeyedPropertyLoad(prop); |
| 3670 } | 3616 } |
| 3671 } | 3617 } |
| 3672 | 3618 |
| 3673 // We need a second deoptimization point after loading the value | 3619 // We need a second deoptimization point after loading the value |
| 3674 // in case evaluating the property load my have a side effect. | 3620 // in case evaluating the property load my have a side effect. |
| 3675 if (assign_type == VARIABLE) { | 3621 PrepareForBailout(expr->increment(), TOS_REG); |
| 3676 PrepareForBailout(expr->expression(), TOS_REG); | |
| 3677 } else { | |
| 3678 PrepareForBailout(expr->increment(), TOS_REG); | |
| 3679 } | |
| 3680 | 3622 |
| 3681 // Call ToNumber only if operand is not a smi. | 3623 // Call ToNumber only if operand is not a smi. |
| 3682 NearLabel no_conversion; | 3624 NearLabel no_conversion; |
| 3683 if (ShouldInlineSmiCase(expr->op())) { | 3625 if (ShouldInlineSmiCase(expr->op())) { |
| 3684 __ test(eax, Immediate(kSmiTagMask)); | 3626 __ test(eax, Immediate(kSmiTagMask)); |
| 3685 __ j(zero, &no_conversion); | 3627 __ j(zero, &no_conversion); |
| 3686 } | 3628 } |
| 3687 ToNumberStub convert_stub; | 3629 ToNumberStub convert_stub; |
| 3688 __ CallStub(&convert_stub); | 3630 __ CallStub(&convert_stub); |
| 3689 __ bind(&no_conversion); | 3631 __ bind(&no_conversion); |
| (...skipping 498 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4188 // And return. | 4130 // And return. |
| 4189 __ ret(0); | 4131 __ ret(0); |
| 4190 } | 4132 } |
| 4191 | 4133 |
| 4192 | 4134 |
| 4193 #undef __ | 4135 #undef __ |
| 4194 | 4136 |
| 4195 } } // namespace v8::internal | 4137 } } // namespace v8::internal |
| 4196 | 4138 |
| 4197 #endif // V8_TARGET_ARCH_IA32 | 4139 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |