| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 308 LPointerMap* pointers = instr->pointer_map(); | 308 LPointerMap* pointers = instr->pointer_map(); |
| 309 RecordPosition(pointers->position()); | 309 RecordPosition(pointers->position()); |
| 310 __ call(code, mode); | 310 __ call(code, mode); |
| 311 RegisterLazyDeoptimization(instr); | 311 RegisterLazyDeoptimization(instr); |
| 312 } else { | 312 } else { |
| 313 LPointerMap no_pointers(0); | 313 LPointerMap no_pointers(0); |
| 314 RecordPosition(no_pointers.position()); | 314 RecordPosition(no_pointers.position()); |
| 315 __ call(code, mode); | 315 __ call(code, mode); |
| 316 RecordSafepoint(&no_pointers, Safepoint::kNoDeoptimizationIndex); | 316 RecordSafepoint(&no_pointers, Safepoint::kNoDeoptimizationIndex); |
| 317 } | 317 } |
| 318 |
| 319 // Signal that we don't inline smi code before these stubs in the |
| 320 // optimizing code generator. |
| 321 if (code->kind() == Code::TYPE_RECORDING_BINARY_OP_IC || |
| 322 code->kind() == Code::COMPARE_IC) { |
| 323 __ nop(); |
| 324 } |
| 318 } | 325 } |
| 319 | 326 |
| 320 | 327 |
| 321 void LCodeGen::CallRuntime(const Runtime::Function* function, | 328 void LCodeGen::CallRuntime(const Runtime::Function* function, |
| 322 int num_arguments, | 329 int num_arguments, |
| 323 LInstruction* instr) { | 330 LInstruction* instr) { |
| 324 ASSERT(instr != NULL); | 331 ASSERT(instr != NULL); |
| 325 LPointerMap* pointers = instr->pointer_map(); | 332 LPointerMap* pointers = instr->pointer_map(); |
| 326 ASSERT(pointers != NULL); | 333 ASSERT(pointers != NULL); |
| 327 RecordPosition(pointers->position()); | 334 RecordPosition(pointers->position()); |
| (...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 672 StringAddStub stub(NO_STRING_ADD_FLAGS); | 679 StringAddStub stub(NO_STRING_ADD_FLAGS); |
| 673 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 680 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 674 break; | 681 break; |
| 675 } | 682 } |
| 676 case CodeStub::StringCompare: { | 683 case CodeStub::StringCompare: { |
| 677 StringCompareStub stub; | 684 StringCompareStub stub; |
| 678 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 685 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 679 break; | 686 break; |
| 680 } | 687 } |
| 681 case CodeStub::TranscendentalCache: { | 688 case CodeStub::TranscendentalCache: { |
| 682 TranscendentalCacheStub stub(instr->transcendental_type()); | 689 TranscendentalCacheStub stub(instr->transcendental_type(), |
| 690 TranscendentalCacheStub::TAGGED); |
| 683 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 691 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 684 break; | 692 break; |
| 685 } | 693 } |
| 686 default: | 694 default: |
| 687 UNREACHABLE(); | 695 UNREACHABLE(); |
| 688 } | 696 } |
| 689 } | 697 } |
| 690 | 698 |
| 691 | 699 |
| 692 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { | 700 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { |
| (...skipping 703 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1396 // the map. The object has already been smi checked. | 1404 // the map. The object has already been smi checked. |
| 1397 Register scratch = ToRegister(instr->temp()); | 1405 Register scratch = ToRegister(instr->temp()); |
| 1398 __ mov(scratch, FieldOperand(reg, HeapObject::kMapOffset)); | 1406 __ mov(scratch, FieldOperand(reg, HeapObject::kMapOffset)); |
| 1399 __ movzx_b(scratch, FieldOperand(scratch, Map::kBitFieldOffset)); | 1407 __ movzx_b(scratch, FieldOperand(scratch, Map::kBitFieldOffset)); |
| 1400 __ test(scratch, Immediate(1 << Map::kIsUndetectable)); | 1408 __ test(scratch, Immediate(1 << Map::kIsUndetectable)); |
| 1401 EmitBranch(true_block, false_block, not_zero); | 1409 EmitBranch(true_block, false_block, not_zero); |
| 1402 } | 1410 } |
| 1403 } | 1411 } |
| 1404 | 1412 |
| 1405 | 1413 |
| 1414 Condition LCodeGen::EmitIsObject(Register input, |
| 1415 Register temp1, |
| 1416 Register temp2, |
| 1417 Label* is_not_object, |
| 1418 Label* is_object) { |
| 1419 ASSERT(!input.is(temp1)); |
| 1420 ASSERT(!input.is(temp2)); |
| 1421 ASSERT(!temp1.is(temp2)); |
| 1422 |
| 1423 __ test(input, Immediate(kSmiTagMask)); |
| 1424 __ j(equal, is_not_object); |
| 1425 |
| 1426 __ cmp(input, FACTORY->null_value()); |
| 1427 __ j(equal, is_object); |
| 1428 |
| 1429 __ mov(temp1, FieldOperand(input, HeapObject::kMapOffset)); |
| 1430 // Undetectable objects behave like undefined. |
| 1431 __ movzx_b(temp2, FieldOperand(temp1, Map::kBitFieldOffset)); |
| 1432 __ test(temp2, Immediate(1 << Map::kIsUndetectable)); |
| 1433 __ j(not_zero, is_not_object); |
| 1434 |
| 1435 __ movzx_b(temp2, FieldOperand(temp1, Map::kInstanceTypeOffset)); |
| 1436 __ cmp(temp2, FIRST_JS_OBJECT_TYPE); |
| 1437 __ j(below, is_not_object); |
| 1438 __ cmp(temp2, LAST_JS_OBJECT_TYPE); |
| 1439 return below_equal; |
| 1440 } |
| 1441 |
| 1442 |
| 1443 void LCodeGen::DoIsObject(LIsObject* instr) { |
| 1444 Register reg = ToRegister(instr->input()); |
| 1445 Register result = ToRegister(instr->result()); |
| 1446 Register temp = ToRegister(instr->temp()); |
| 1447 Label is_false, is_true, done; |
| 1448 |
| 1449 Condition true_cond = EmitIsObject(reg, result, temp, &is_false, &is_true); |
| 1450 __ j(true_cond, &is_true); |
| 1451 |
| 1452 __ bind(&is_false); |
| 1453 __ mov(result, Handle<Object>(HEAP->false_value())); |
| 1454 __ jmp(&done); |
| 1455 |
| 1456 __ bind(&is_true); |
| 1457 __ mov(result, Handle<Object>(HEAP->true_value())); |
| 1458 |
| 1459 __ bind(&done); |
| 1460 } |
| 1461 |
| 1462 |
| 1463 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { |
| 1464 Register reg = ToRegister(instr->input()); |
| 1465 Register temp = ToRegister(instr->temp()); |
| 1466 Register temp2 = ToRegister(instr->temp2()); |
| 1467 |
| 1468 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1469 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1470 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
| 1471 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
| 1472 |
| 1473 Condition true_cond = EmitIsObject(reg, temp, temp2, false_label, true_label); |
| 1474 |
| 1475 EmitBranch(true_block, false_block, true_cond); |
| 1476 } |
| 1477 |
| 1478 |
| 1406 void LCodeGen::DoIsSmi(LIsSmi* instr) { | 1479 void LCodeGen::DoIsSmi(LIsSmi* instr) { |
| 1407 Operand input = ToOperand(instr->input()); | 1480 Operand input = ToOperand(instr->input()); |
| 1408 Register result = ToRegister(instr->result()); | 1481 Register result = ToRegister(instr->result()); |
| 1409 | 1482 |
| 1410 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); | 1483 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); |
| 1411 __ test(input, Immediate(kSmiTagMask)); | 1484 __ test(input, Immediate(kSmiTagMask)); |
| 1412 __ mov(result, Handle<Object>(HEAP->true_value())); | 1485 __ mov(result, Handle<Object>(HEAP->true_value())); |
| 1413 NearLabel done; | 1486 NearLabel done; |
| 1414 __ j(zero, &done); | 1487 __ j(zero, &done); |
| 1415 __ mov(result, Handle<Object>(HEAP->false_value())); | 1488 __ mov(result, Handle<Object>(HEAP->false_value())); |
| (...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1620 Register reg = ToRegister(instr->input()); | 1693 Register reg = ToRegister(instr->input()); |
| 1621 int true_block = instr->true_block_id(); | 1694 int true_block = instr->true_block_id(); |
| 1622 int false_block = instr->false_block_id(); | 1695 int false_block = instr->false_block_id(); |
| 1623 | 1696 |
| 1624 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map()); | 1697 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map()); |
| 1625 EmitBranch(true_block, false_block, equal); | 1698 EmitBranch(true_block, false_block, equal); |
| 1626 } | 1699 } |
| 1627 | 1700 |
| 1628 | 1701 |
| 1629 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { | 1702 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { |
| 1630 InstanceofStub stub; | 1703 // Object and function are in fixed registers eax and edx. |
| 1631 __ push(ToOperand(instr->left())); | 1704 InstanceofStub stub(InstanceofStub::kArgsInRegisters); |
| 1632 __ push(ToOperand(instr->right())); | |
| 1633 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 1705 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 1634 | 1706 |
| 1635 NearLabel true_value, done; | 1707 NearLabel true_value, done; |
| 1636 __ test(eax, Operand(eax)); | 1708 __ test(eax, Operand(eax)); |
| 1637 __ j(zero, &true_value); | 1709 __ j(zero, &true_value); |
| 1638 __ mov(ToRegister(instr->result()), FACTORY->false_value()); | 1710 __ mov(ToRegister(instr->result()), FACTORY->false_value()); |
| 1639 __ jmp(&done); | 1711 __ jmp(&done); |
| 1640 __ bind(&true_value); | 1712 __ bind(&true_value); |
| 1641 __ mov(ToRegister(instr->result()), FACTORY->true_value()); | 1713 __ mov(ToRegister(instr->result()), FACTORY->true_value()); |
| 1642 __ bind(&done); | 1714 __ bind(&done); |
| 1643 } | 1715 } |
| 1644 | 1716 |
| 1645 | 1717 |
| 1646 void LCodeGen::DoInstanceOfAndBranch(LInstanceOfAndBranch* instr) { | 1718 void LCodeGen::DoInstanceOfAndBranch(LInstanceOfAndBranch* instr) { |
| 1647 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1719 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1648 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1720 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1649 | 1721 |
| 1650 InstanceofStub stub; | 1722 InstanceofStub stub(InstanceofStub::kArgsInRegisters); |
| 1651 __ push(ToOperand(instr->left())); | |
| 1652 __ push(ToOperand(instr->right())); | |
| 1653 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 1723 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 1654 __ test(eax, Operand(eax)); | 1724 __ test(eax, Operand(eax)); |
| 1655 EmitBranch(true_block, false_block, zero); | 1725 EmitBranch(true_block, false_block, zero); |
| 1656 } | 1726 } |
| 1657 | 1727 |
| 1658 | 1728 |
| 1659 static Condition ComputeCompareCondition(Token::Value op) { | 1729 static Condition ComputeCompareCondition(Token::Value op) { |
| 1660 switch (op) { | 1730 switch (op) { |
| 1661 case Token::EQ_STRICT: | 1731 case Token::EQ_STRICT: |
| 1662 case Token::EQ: | 1732 case Token::EQ: |
| (...skipping 506 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2169 } | 2239 } |
| 2170 | 2240 |
| 2171 | 2241 |
| 2172 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { | 2242 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { |
| 2173 XMMRegister input_reg = ToDoubleRegister(instr->input()); | 2243 XMMRegister input_reg = ToDoubleRegister(instr->input()); |
| 2174 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); | 2244 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); |
| 2175 __ sqrtsd(input_reg, input_reg); | 2245 __ sqrtsd(input_reg, input_reg); |
| 2176 } | 2246 } |
| 2177 | 2247 |
| 2178 | 2248 |
| 2249 void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) { |
| 2250 XMMRegister xmm_scratch = xmm0; |
| 2251 XMMRegister input_reg = ToDoubleRegister(instr->input()); |
| 2252 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); |
| 2253 ExternalReference negative_infinity = |
| 2254 ExternalReference::address_of_negative_infinity(); |
| 2255 __ movdbl(xmm_scratch, Operand::StaticVariable(negative_infinity)); |
| 2256 __ ucomisd(xmm_scratch, input_reg); |
| 2257 DeoptimizeIf(equal, instr->environment()); |
| 2258 __ sqrtsd(input_reg, input_reg); |
| 2259 } |
| 2260 |
| 2261 |
| 2262 void LCodeGen::DoPower(LPower* instr) { |
| 2263 LOperand* left = instr->left(); |
| 2264 LOperand* right = instr->right(); |
| 2265 DoubleRegister result_reg = ToDoubleRegister(instr->result()); |
| 2266 Representation exponent_type = instr->hydrogen()->right()->representation(); |
| 2267 if (exponent_type.IsDouble()) { |
| 2268 // It is safe to use ebx directly since the instruction is marked |
| 2269 // as a call. |
| 2270 __ PrepareCallCFunction(4, ebx); |
| 2271 __ movdbl(Operand(esp, 0 * kDoubleSize), ToDoubleRegister(left)); |
| 2272 __ movdbl(Operand(esp, 1 * kDoubleSize), ToDoubleRegister(right)); |
| 2273 __ CallCFunction(ExternalReference::power_double_double_function(), 4); |
| 2274 } else if (exponent_type.IsInteger32()) { |
| 2275 // It is safe to use ebx directly since the instruction is marked |
| 2276 // as a call. |
| 2277 ASSERT(!ToRegister(right).is(ebx)); |
| 2278 __ PrepareCallCFunction(4, ebx); |
| 2279 __ movdbl(Operand(esp, 0 * kDoubleSize), ToDoubleRegister(left)); |
| 2280 __ mov(Operand(esp, 1 * kDoubleSize), ToRegister(right)); |
| 2281 __ CallCFunction(ExternalReference::power_double_int_function(), 4); |
| 2282 } else { |
| 2283 ASSERT(exponent_type.IsTagged()); |
| 2284 CpuFeatures::Scope scope(SSE2); |
| 2285 Register right_reg = ToRegister(right); |
| 2286 |
| 2287 Label non_smi, call; |
| 2288 __ test(right_reg, Immediate(kSmiTagMask)); |
| 2289 __ j(not_zero, &non_smi); |
| 2290 __ SmiUntag(right_reg); |
| 2291 __ cvtsi2sd(result_reg, Operand(right_reg)); |
| 2292 __ jmp(&call); |
| 2293 |
| 2294 __ bind(&non_smi); |
| 2295 // It is safe to use ebx directly since the instruction is marked |
| 2296 // as a call. |
| 2297 ASSERT(!right_reg.is(ebx)); |
| 2298 __ CmpObjectType(right_reg, HEAP_NUMBER_TYPE , ebx); |
| 2299 DeoptimizeIf(not_equal, instr->environment()); |
| 2300 __ movdbl(result_reg, FieldOperand(right_reg, HeapNumber::kValueOffset)); |
| 2301 |
| 2302 __ bind(&call); |
| 2303 __ PrepareCallCFunction(4, ebx); |
| 2304 __ movdbl(Operand(esp, 0 * kDoubleSize), ToDoubleRegister(left)); |
| 2305 __ movdbl(Operand(esp, 1 * kDoubleSize), result_reg); |
| 2306 __ CallCFunction(ExternalReference::power_double_double_function(), 4); |
| 2307 } |
| 2308 |
| 2309 // Return value is in st(0) on ia32. |
| 2310 // Store it into the (fixed) result register. |
| 2311 __ sub(Operand(esp), Immediate(kDoubleSize)); |
| 2312 __ fstp_d(Operand(esp, 0)); |
| 2313 __ movdbl(result_reg, Operand(esp, 0)); |
| 2314 __ add(Operand(esp), Immediate(kDoubleSize)); |
| 2315 } |
| 2316 |
| 2317 |
| 2318 void LCodeGen::DoMathLog(LUnaryMathOperation* instr) { |
| 2319 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); |
| 2320 TranscendentalCacheStub stub(TranscendentalCache::LOG, |
| 2321 TranscendentalCacheStub::UNTAGGED); |
| 2322 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 2323 } |
| 2324 |
| 2325 |
| 2326 void LCodeGen::DoMathCos(LUnaryMathOperation* instr) { |
| 2327 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); |
| 2328 TranscendentalCacheStub stub(TranscendentalCache::COS, |
| 2329 TranscendentalCacheStub::UNTAGGED); |
| 2330 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 2331 } |
| 2332 |
| 2333 |
| 2334 void LCodeGen::DoMathSin(LUnaryMathOperation* instr) { |
| 2335 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); |
| 2336 TranscendentalCacheStub stub(TranscendentalCache::SIN, |
| 2337 TranscendentalCacheStub::UNTAGGED); |
| 2338 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 2339 } |
| 2340 |
| 2341 |
| 2179 void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) { | 2342 void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) { |
| 2180 switch (instr->op()) { | 2343 switch (instr->op()) { |
| 2181 case kMathAbs: | 2344 case kMathAbs: |
| 2182 DoMathAbs(instr); | 2345 DoMathAbs(instr); |
| 2183 break; | 2346 break; |
| 2184 case kMathFloor: | 2347 case kMathFloor: |
| 2185 DoMathFloor(instr); | 2348 DoMathFloor(instr); |
| 2186 break; | 2349 break; |
| 2187 case kMathRound: | 2350 case kMathRound: |
| 2188 DoMathRound(instr); | 2351 DoMathRound(instr); |
| 2189 break; | 2352 break; |
| 2190 case kMathSqrt: | 2353 case kMathSqrt: |
| 2191 DoMathSqrt(instr); | 2354 DoMathSqrt(instr); |
| 2192 break; | 2355 break; |
| 2356 case kMathPowHalf: |
| 2357 DoMathPowHalf(instr); |
| 2358 break; |
| 2359 case kMathCos: |
| 2360 DoMathCos(instr); |
| 2361 break; |
| 2362 case kMathSin: |
| 2363 DoMathSin(instr); |
| 2364 break; |
| 2365 case kMathLog: |
| 2366 DoMathLog(instr); |
| 2367 break; |
| 2368 |
| 2193 default: | 2369 default: |
| 2194 UNREACHABLE(); | 2370 UNREACHABLE(); |
| 2195 } | 2371 } |
| 2196 } | 2372 } |
| 2197 | 2373 |
| 2198 | 2374 |
| 2199 void LCodeGen::DoCallKeyed(LCallKeyed* instr) { | 2375 void LCodeGen::DoCallKeyed(LCallKeyed* instr) { |
| 2200 ASSERT(ToRegister(instr->result()).is(eax)); | 2376 ASSERT(ToRegister(instr->result()).is(eax)); |
| 2201 | 2377 |
| 2202 int arity = instr->arity(); | 2378 int arity = instr->arity(); |
| (...skipping 896 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3099 ASSERT(!environment->HasBeenRegistered()); | 3275 ASSERT(!environment->HasBeenRegistered()); |
| 3100 RegisterEnvironmentForDeoptimization(environment); | 3276 RegisterEnvironmentForDeoptimization(environment); |
| 3101 ASSERT(osr_pc_offset_ == -1); | 3277 ASSERT(osr_pc_offset_ == -1); |
| 3102 osr_pc_offset_ = masm()->pc_offset(); | 3278 osr_pc_offset_ = masm()->pc_offset(); |
| 3103 } | 3279 } |
| 3104 | 3280 |
| 3105 | 3281 |
| 3106 #undef __ | 3282 #undef __ |
| 3107 | 3283 |
| 3108 } } // namespace v8::internal | 3284 } } // namespace v8::internal |
| OLD | NEW |