| 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 1194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1205 } | 1205 } |
| 1206 | 1206 |
| 1207 | 1207 |
| 1208 void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) { | 1208 void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) { |
| 1209 Register result = ToRegister(instr->result()); | 1209 Register result = ToRegister(instr->result()); |
| 1210 Register array = ToRegister(instr->InputAt(0)); | 1210 Register array = ToRegister(instr->InputAt(0)); |
| 1211 __ mov(result, FieldOperand(array, JSArray::kLengthOffset)); | 1211 __ mov(result, FieldOperand(array, JSArray::kLengthOffset)); |
| 1212 } | 1212 } |
| 1213 | 1213 |
| 1214 | 1214 |
| 1215 void LCodeGen::DoFixedArrayLength(LFixedArrayLength* instr) { | 1215 void LCodeGen::DoFixedArrayBaseLength( |
| 1216 LFixedArrayBaseLength* instr) { |
| 1216 Register result = ToRegister(instr->result()); | 1217 Register result = ToRegister(instr->result()); |
| 1217 Register array = ToRegister(instr->InputAt(0)); | 1218 Register array = ToRegister(instr->InputAt(0)); |
| 1218 __ mov(result, FieldOperand(array, FixedArray::kLengthOffset)); | 1219 __ mov(result, FieldOperand(array, FixedArrayBase::kLengthOffset)); |
| 1219 } | |
| 1220 | |
| 1221 | |
| 1222 void LCodeGen::DoExternalArrayLength(LExternalArrayLength* instr) { | |
| 1223 Register result = ToRegister(instr->result()); | |
| 1224 Register array = ToRegister(instr->InputAt(0)); | |
| 1225 __ mov(result, FieldOperand(array, ExternalArray::kLengthOffset)); | |
| 1226 } | 1220 } |
| 1227 | 1221 |
| 1228 | 1222 |
| 1229 void LCodeGen::DoElementsKind(LElementsKind* instr) { | 1223 void LCodeGen::DoElementsKind(LElementsKind* instr) { |
| 1230 Register result = ToRegister(instr->result()); | 1224 Register result = ToRegister(instr->result()); |
| 1231 Register input = ToRegister(instr->InputAt(0)); | 1225 Register input = ToRegister(instr->InputAt(0)); |
| 1232 | 1226 |
| 1233 // Load map into |result|. | 1227 // Load map into |result|. |
| 1234 __ mov(result, FieldOperand(input, HeapObject::kMapOffset)); | 1228 __ mov(result, FieldOperand(input, HeapObject::kMapOffset)); |
| 1235 // Load the map's "bit field 2" into |result|. We only need the first byte, | 1229 // Load the map's "bit field 2" into |result|. We only need the first byte, |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1406 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1400 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
| 1407 | 1401 |
| 1408 ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types(); | 1402 ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types(); |
| 1409 // Avoid deopts in the case where we've never executed this path before. | 1403 // Avoid deopts in the case where we've never executed this path before. |
| 1410 if (expected.IsEmpty()) expected = ToBooleanStub::all_types(); | 1404 if (expected.IsEmpty()) expected = ToBooleanStub::all_types(); |
| 1411 | 1405 |
| 1412 if (expected.Contains(ToBooleanStub::UNDEFINED)) { | 1406 if (expected.Contains(ToBooleanStub::UNDEFINED)) { |
| 1413 // undefined -> false. | 1407 // undefined -> false. |
| 1414 __ cmp(reg, factory()->undefined_value()); | 1408 __ cmp(reg, factory()->undefined_value()); |
| 1415 __ j(equal, false_label); | 1409 __ j(equal, false_label); |
| 1416 } else if (expected.Contains(ToBooleanStub::INTERNAL_OBJECT)) { | |
| 1417 // We've seen undefined for the first time -> deopt. | |
| 1418 __ cmp(reg, factory()->undefined_value()); | |
| 1419 DeoptimizeIf(equal, instr->environment()); | |
| 1420 } | 1410 } |
| 1421 | |
| 1422 if (expected.Contains(ToBooleanStub::BOOLEAN)) { | 1411 if (expected.Contains(ToBooleanStub::BOOLEAN)) { |
| 1423 // true -> true. | 1412 // true -> true. |
| 1424 __ cmp(reg, factory()->true_value()); | 1413 __ cmp(reg, factory()->true_value()); |
| 1425 __ j(equal, true_label); | 1414 __ j(equal, true_label); |
| 1426 } else if (expected.Contains(ToBooleanStub::INTERNAL_OBJECT)) { | |
| 1427 // We've seen a boolean for the first time -> deopt. | |
| 1428 __ cmp(reg, factory()->true_value()); | |
| 1429 DeoptimizeIf(equal, instr->environment()); | |
| 1430 } | |
| 1431 | |
| 1432 if (expected.Contains(ToBooleanStub::BOOLEAN)) { | |
| 1433 // false -> false. | 1415 // false -> false. |
| 1434 __ cmp(reg, factory()->false_value()); | 1416 __ cmp(reg, factory()->false_value()); |
| 1435 __ j(equal, false_label); | 1417 __ j(equal, false_label); |
| 1436 } else if (expected.Contains(ToBooleanStub::INTERNAL_OBJECT)) { | |
| 1437 // We've seen a boolean for the first time -> deopt. | |
| 1438 __ cmp(reg, factory()->false_value()); | |
| 1439 DeoptimizeIf(equal, instr->environment()); | |
| 1440 } | 1418 } |
| 1441 | |
| 1442 if (expected.Contains(ToBooleanStub::NULL_TYPE)) { | 1419 if (expected.Contains(ToBooleanStub::NULL_TYPE)) { |
| 1443 // 'null' -> false. | 1420 // 'null' -> false. |
| 1444 __ cmp(reg, factory()->null_value()); | 1421 __ cmp(reg, factory()->null_value()); |
| 1445 __ j(equal, false_label); | 1422 __ j(equal, false_label); |
| 1446 } else if (expected.Contains(ToBooleanStub::INTERNAL_OBJECT)) { | |
| 1447 // We've seen null for the first time -> deopt. | |
| 1448 __ cmp(reg, factory()->null_value()); | |
| 1449 DeoptimizeIf(equal, instr->environment()); | |
| 1450 } | 1423 } |
| 1451 | 1424 |
| 1452 if (expected.Contains(ToBooleanStub::SMI)) { | 1425 if (expected.Contains(ToBooleanStub::SMI)) { |
| 1453 // Smis: 0 -> false, all other -> true. | 1426 // Smis: 0 -> false, all other -> true. |
| 1454 __ test(reg, Operand(reg)); | 1427 __ test(reg, Operand(reg)); |
| 1455 __ j(equal, false_label); | 1428 __ j(equal, false_label); |
| 1456 __ JumpIfSmi(reg, true_label); | 1429 __ JumpIfSmi(reg, true_label); |
| 1457 } else if (expected.NeedsMap()) { | 1430 } else if (expected.NeedsMap()) { |
| 1458 // If we need a map later and have a Smi -> deopt. | 1431 // If we need a map later and have a Smi -> deopt. |
| 1459 __ test(reg, Immediate(kSmiTagMask)); | 1432 __ test(reg, Immediate(kSmiTagMask)); |
| 1460 DeoptimizeIf(zero, instr->environment()); | 1433 DeoptimizeIf(zero, instr->environment()); |
| 1461 } | 1434 } |
| 1462 | 1435 |
| 1463 Register map = no_reg; | 1436 Register map = no_reg; // Keep the compiler happy. |
| 1464 if (expected.NeedsMap()) { | 1437 if (expected.NeedsMap()) { |
| 1465 map = ToRegister(instr->TempAt(0)); | 1438 map = ToRegister(instr->TempAt(0)); |
| 1466 ASSERT(!map.is(reg)); | 1439 ASSERT(!map.is(reg)); |
| 1467 __ mov(map, FieldOperand(reg, HeapObject::kMapOffset)); | 1440 __ mov(map, FieldOperand(reg, HeapObject::kMapOffset)); |
| 1468 // Everything with a map could be undetectable, so check this now. | 1441 |
| 1469 __ test_b(FieldOperand(map, Map::kBitFieldOffset), | 1442 if (expected.CanBeUndetectable()) { |
| 1470 1 << Map::kIsUndetectable); | 1443 // Undetectable -> false. |
| 1471 // Undetectable -> false. | 1444 __ test_b(FieldOperand(map, Map::kBitFieldOffset), |
| 1472 __ j(not_zero, false_label); | 1445 1 << Map::kIsUndetectable); |
| 1446 __ j(not_zero, false_label); |
| 1447 } |
| 1473 } | 1448 } |
| 1474 | 1449 |
| 1475 if (expected.Contains(ToBooleanStub::SPEC_OBJECT)) { | 1450 if (expected.Contains(ToBooleanStub::SPEC_OBJECT)) { |
| 1476 // spec object -> true. | 1451 // spec object -> true. |
| 1477 __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE); | 1452 __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE); |
| 1478 __ j(above_equal, true_label); | 1453 __ j(above_equal, true_label); |
| 1479 } else if (expected.Contains(ToBooleanStub::INTERNAL_OBJECT)) { | |
| 1480 // We've seen a spec object for the first time -> deopt. | |
| 1481 __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE); | |
| 1482 DeoptimizeIf(above_equal, instr->environment()); | |
| 1483 } | 1454 } |
| 1484 | 1455 |
| 1485 if (expected.Contains(ToBooleanStub::STRING)) { | 1456 if (expected.Contains(ToBooleanStub::STRING)) { |
| 1486 // String value -> false iff empty. | 1457 // String value -> false iff empty. |
| 1487 Label not_string; | 1458 Label not_string; |
| 1488 __ CmpInstanceType(map, FIRST_NONSTRING_TYPE); | 1459 __ CmpInstanceType(map, FIRST_NONSTRING_TYPE); |
| 1489 __ j(above_equal, ¬_string, Label::kNear); | 1460 __ j(above_equal, ¬_string, Label::kNear); |
| 1490 __ cmp(FieldOperand(reg, String::kLengthOffset), Immediate(0)); | 1461 __ cmp(FieldOperand(reg, String::kLengthOffset), Immediate(0)); |
| 1491 __ j(not_zero, true_label); | 1462 __ j(not_zero, true_label); |
| 1492 __ jmp(false_label); | 1463 __ jmp(false_label); |
| 1493 __ bind(¬_string); | 1464 __ bind(¬_string); |
| 1494 } else if (expected.Contains(ToBooleanStub::INTERNAL_OBJECT)) { | |
| 1495 // We've seen a string for the first time -> deopt | |
| 1496 __ CmpInstanceType(map, FIRST_NONSTRING_TYPE); | |
| 1497 DeoptimizeIf(below, instr->environment()); | |
| 1498 } | 1465 } |
| 1499 | 1466 |
| 1500 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) { | 1467 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) { |
| 1501 // heap number -> false iff +0, -0, or NaN. | 1468 // heap number -> false iff +0, -0, or NaN. |
| 1502 Label not_heap_number; | 1469 Label not_heap_number; |
| 1503 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | 1470 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), |
| 1504 factory()->heap_number_map()); | 1471 factory()->heap_number_map()); |
| 1505 __ j(not_equal, ¬_heap_number, Label::kNear); | 1472 __ j(not_equal, ¬_heap_number, Label::kNear); |
| 1506 __ fldz(); | 1473 __ fldz(); |
| 1507 __ fld_d(FieldOperand(reg, HeapNumber::kValueOffset)); | 1474 __ fld_d(FieldOperand(reg, HeapNumber::kValueOffset)); |
| 1508 __ FCmp(); | 1475 __ FCmp(); |
| 1509 __ j(zero, false_label); | 1476 __ j(zero, false_label); |
| 1510 __ jmp(true_label); | 1477 __ jmp(true_label); |
| 1511 __ bind(¬_heap_number); | 1478 __ bind(¬_heap_number); |
| 1512 } else if (expected.Contains(ToBooleanStub::INTERNAL_OBJECT)) { | |
| 1513 // We've seen a heap number for the first time -> deopt. | |
| 1514 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | |
| 1515 factory()->heap_number_map()); | |
| 1516 DeoptimizeIf(equal, instr->environment()); | |
| 1517 } | 1479 } |
| 1518 | 1480 |
| 1519 if (expected.Contains(ToBooleanStub::INTERNAL_OBJECT)) { | 1481 // We've seen something for the first time -> deopt. |
| 1520 // internal objects -> true | 1482 DeoptimizeIf(no_condition, instr->environment()); |
| 1521 __ jmp(true_label); | |
| 1522 } else { | |
| 1523 // We've seen something for the first time -> deopt. | |
| 1524 DeoptimizeIf(no_condition, instr->environment()); | |
| 1525 } | |
| 1526 } | 1483 } |
| 1527 } | 1484 } |
| 1528 } | 1485 } |
| 1529 | 1486 |
| 1530 | 1487 |
| 1531 void LCodeGen::EmitGoto(int block) { | 1488 void LCodeGen::EmitGoto(int block) { |
| 1532 block = chunk_->LookupDestination(block); | 1489 block = chunk_->LookupDestination(block); |
| 1533 int next_block = GetNextEmittedBlock(current_block_); | 1490 int next_block = GetNextEmittedBlock(current_block_); |
| 1534 if (block != next_block) { | 1491 if (block != next_block) { |
| 1535 __ jmp(chunk_->GetAssemblyLabel(block)); | 1492 __ jmp(chunk_->GetAssemblyLabel(block)); |
| (...skipping 774 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2310 __ sub(length, index); | 2267 __ sub(length, index); |
| 2311 DeoptimizeIf(below_equal, instr->environment()); | 2268 DeoptimizeIf(below_equal, instr->environment()); |
| 2312 | 2269 |
| 2313 // There are two words between the frame pointer and the last argument. | 2270 // There are two words between the frame pointer and the last argument. |
| 2314 // Subtracting from length accounts for one of them add one more. | 2271 // Subtracting from length accounts for one of them add one more. |
| 2315 __ mov(result, Operand(arguments, length, times_4, kPointerSize)); | 2272 __ mov(result, Operand(arguments, length, times_4, kPointerSize)); |
| 2316 } | 2273 } |
| 2317 | 2274 |
| 2318 | 2275 |
| 2319 void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) { | 2276 void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) { |
| 2320 Register elements = ToRegister(instr->elements()); | |
| 2321 Register key = ToRegister(instr->key()); | |
| 2322 Register result = ToRegister(instr->result()); | 2277 Register result = ToRegister(instr->result()); |
| 2323 ASSERT(result.is(elements)); | |
| 2324 | 2278 |
| 2325 // Load the result. | 2279 // Load the result. |
| 2326 __ mov(result, FieldOperand(elements, | 2280 __ mov(result, |
| 2327 key, | 2281 BuildFastArrayOperand(instr->elements(), instr->key(), |
| 2328 times_pointer_size, | 2282 JSObject::FAST_ELEMENTS, |
| 2329 FixedArray::kHeaderSize)); | 2283 FixedArray::kHeaderSize - kHeapObjectTag)); |
| 2330 | 2284 |
| 2331 // Check for the hole value. | 2285 // Check for the hole value. |
| 2332 if (instr->hydrogen()->RequiresHoleCheck()) { | 2286 if (instr->hydrogen()->RequiresHoleCheck()) { |
| 2333 __ cmp(result, factory()->the_hole_value()); | 2287 __ cmp(result, factory()->the_hole_value()); |
| 2334 DeoptimizeIf(equal, instr->environment()); | 2288 DeoptimizeIf(equal, instr->environment()); |
| 2335 } | 2289 } |
| 2336 } | 2290 } |
| 2337 | 2291 |
| 2338 | 2292 |
| 2339 void LCodeGen::DoLoadKeyedFastDoubleElement( | 2293 void LCodeGen::DoLoadKeyedFastDoubleElement( |
| (...skipping 12 matching lines...) Expand all Loading... |
| 2352 } | 2306 } |
| 2353 | 2307 |
| 2354 Operand double_load_operand = BuildFastArrayOperand( | 2308 Operand double_load_operand = BuildFastArrayOperand( |
| 2355 instr->elements(), instr->key(), JSObject::FAST_DOUBLE_ELEMENTS, | 2309 instr->elements(), instr->key(), JSObject::FAST_DOUBLE_ELEMENTS, |
| 2356 FixedDoubleArray::kHeaderSize - kHeapObjectTag); | 2310 FixedDoubleArray::kHeaderSize - kHeapObjectTag); |
| 2357 __ movdbl(result, double_load_operand); | 2311 __ movdbl(result, double_load_operand); |
| 2358 } | 2312 } |
| 2359 | 2313 |
| 2360 | 2314 |
| 2361 Operand LCodeGen::BuildFastArrayOperand( | 2315 Operand LCodeGen::BuildFastArrayOperand( |
| 2362 LOperand* external_pointer, | 2316 LOperand* elements_pointer, |
| 2363 LOperand* key, | 2317 LOperand* key, |
| 2364 JSObject::ElementsKind elements_kind, | 2318 JSObject::ElementsKind elements_kind, |
| 2365 uint32_t offset) { | 2319 uint32_t offset) { |
| 2366 Register external_pointer_reg = ToRegister(external_pointer); | 2320 Register elements_pointer_reg = ToRegister(elements_pointer); |
| 2367 int shift_size = ElementsKindToShiftSize(elements_kind); | 2321 int shift_size = ElementsKindToShiftSize(elements_kind); |
| 2368 if (key->IsConstantOperand()) { | 2322 if (key->IsConstantOperand()) { |
| 2369 int constant_value = ToInteger32(LConstantOperand::cast(key)); | 2323 int constant_value = ToInteger32(LConstantOperand::cast(key)); |
| 2370 if (constant_value & 0xF0000000) { | 2324 if (constant_value & 0xF0000000) { |
| 2371 Abort("array index constant value too big"); | 2325 Abort("array index constant value too big"); |
| 2372 } | 2326 } |
| 2373 return Operand(external_pointer_reg, | 2327 return Operand(elements_pointer_reg, |
| 2374 constant_value * (1 << shift_size) + offset); | 2328 constant_value * (1 << shift_size) + offset); |
| 2375 } else { | 2329 } else { |
| 2376 ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size); | 2330 ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size); |
| 2377 return Operand(external_pointer_reg, ToRegister(key), scale_factor, offset); | 2331 return Operand(elements_pointer_reg, ToRegister(key), scale_factor, offset); |
| 2378 } | 2332 } |
| 2379 } | 2333 } |
| 2380 | 2334 |
| 2381 | 2335 |
| 2382 void LCodeGen::DoLoadKeyedSpecializedArrayElement( | 2336 void LCodeGen::DoLoadKeyedSpecializedArrayElement( |
| 2383 LLoadKeyedSpecializedArrayElement* instr) { | 2337 LLoadKeyedSpecializedArrayElement* instr) { |
| 2384 JSObject::ElementsKind elements_kind = instr->elements_kind(); | 2338 JSObject::ElementsKind elements_kind = instr->elements_kind(); |
| 2385 Operand operand(BuildFastArrayOperand(instr->external_pointer(), | 2339 Operand operand(BuildFastArrayOperand(instr->external_pointer(), |
| 2386 instr->key(), elements_kind, 0)); | 2340 instr->key(), elements_kind, 0)); |
| 2387 if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) { | 2341 if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) { |
| (...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2764 EmitIntegerMathAbs(instr); | 2718 EmitIntegerMathAbs(instr); |
| 2765 __ bind(deferred->exit()); | 2719 __ bind(deferred->exit()); |
| 2766 } | 2720 } |
| 2767 } | 2721 } |
| 2768 | 2722 |
| 2769 | 2723 |
| 2770 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { | 2724 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { |
| 2771 XMMRegister xmm_scratch = xmm0; | 2725 XMMRegister xmm_scratch = xmm0; |
| 2772 Register output_reg = ToRegister(instr->result()); | 2726 Register output_reg = ToRegister(instr->result()); |
| 2773 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 2727 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
| 2774 __ xorps(xmm_scratch, xmm_scratch); // Zero the register. | |
| 2775 __ ucomisd(input_reg, xmm_scratch); | |
| 2776 | 2728 |
| 2777 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 2729 if (CpuFeatures::IsSupported(SSE4_1)) { |
| 2778 DeoptimizeIf(below_equal, instr->environment()); | 2730 CpuFeatures::Scope scope(SSE4_1); |
| 2731 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 2732 // Deoptimize on negative zero. |
| 2733 Label non_zero; |
| 2734 __ xorps(xmm_scratch, xmm_scratch); // Zero the register. |
| 2735 __ ucomisd(input_reg, xmm_scratch); |
| 2736 __ j(not_equal, &non_zero, Label::kNear); |
| 2737 __ movmskpd(output_reg, input_reg); |
| 2738 __ test(output_reg, Immediate(1)); |
| 2739 DeoptimizeIf(not_zero, instr->environment()); |
| 2740 __ bind(&non_zero); |
| 2741 } |
| 2742 __ roundsd(xmm_scratch, input_reg, Assembler::kRoundDown); |
| 2743 __ cvttsd2si(output_reg, Operand(xmm_scratch)); |
| 2744 // Overflow is signalled with minint. |
| 2745 __ cmp(output_reg, 0x80000000u); |
| 2746 DeoptimizeIf(equal, instr->environment()); |
| 2779 } else { | 2747 } else { |
| 2748 Label done; |
| 2749 // Deoptimize on negative numbers. |
| 2750 __ xorps(xmm_scratch, xmm_scratch); // Zero the register. |
| 2751 __ ucomisd(input_reg, xmm_scratch); |
| 2780 DeoptimizeIf(below, instr->environment()); | 2752 DeoptimizeIf(below, instr->environment()); |
| 2753 |
| 2754 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 2755 // Check for negative zero. |
| 2756 Label positive_sign; |
| 2757 __ j(above, &positive_sign, Label::kNear); |
| 2758 __ movmskpd(output_reg, input_reg); |
| 2759 __ test(output_reg, Immediate(1)); |
| 2760 DeoptimizeIf(not_zero, instr->environment()); |
| 2761 __ Set(output_reg, Immediate(0)); |
| 2762 __ jmp(&done, Label::kNear); |
| 2763 __ bind(&positive_sign); |
| 2764 } |
| 2765 |
| 2766 // Use truncating instruction (OK because input is positive). |
| 2767 __ cvttsd2si(output_reg, Operand(input_reg)); |
| 2768 |
| 2769 // Overflow is signalled with minint. |
| 2770 __ cmp(output_reg, 0x80000000u); |
| 2771 DeoptimizeIf(equal, instr->environment()); |
| 2772 __ bind(&done); |
| 2781 } | 2773 } |
| 2782 | |
| 2783 // Use truncating instruction (OK because input is positive). | |
| 2784 __ cvttsd2si(output_reg, Operand(input_reg)); | |
| 2785 | |
| 2786 // Overflow is signalled with minint. | |
| 2787 __ cmp(output_reg, 0x80000000u); | |
| 2788 DeoptimizeIf(equal, instr->environment()); | |
| 2789 } | 2774 } |
| 2790 | 2775 |
| 2791 | |
| 2792 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { | 2776 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { |
| 2793 XMMRegister xmm_scratch = xmm0; | 2777 XMMRegister xmm_scratch = xmm0; |
| 2794 Register output_reg = ToRegister(instr->result()); | 2778 Register output_reg = ToRegister(instr->result()); |
| 2795 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 2779 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
| 2796 | 2780 |
| 2797 Label below_half, done; | 2781 Label below_half, done; |
| 2798 // xmm_scratch = 0.5 | 2782 // xmm_scratch = 0.5 |
| 2799 ExternalReference one_half = ExternalReference::address_of_one_half(); | 2783 ExternalReference one_half = ExternalReference::address_of_one_half(); |
| 2800 __ movdbl(xmm_scratch, Operand::StaticVariable(one_half)); | 2784 __ movdbl(xmm_scratch, Operand::StaticVariable(one_half)); |
| 2801 | |
| 2802 __ ucomisd(xmm_scratch, input_reg); | 2785 __ ucomisd(xmm_scratch, input_reg); |
| 2803 __ j(above, &below_half); | 2786 __ j(above, &below_half); |
| 2804 // input = input + 0.5 | 2787 // input = input + 0.5 |
| 2805 __ addsd(input_reg, xmm_scratch); | 2788 __ addsd(input_reg, xmm_scratch); |
| 2806 | 2789 |
| 2807 | |
| 2808 // Compute Math.floor(value + 0.5). | 2790 // Compute Math.floor(value + 0.5). |
| 2809 // Use truncating instruction (OK because input is positive). | 2791 // Use truncating instruction (OK because input is positive). |
| 2810 __ cvttsd2si(output_reg, Operand(input_reg)); | 2792 __ cvttsd2si(output_reg, Operand(input_reg)); |
| 2811 | 2793 |
| 2812 // Overflow is signalled with minint. | 2794 // Overflow is signalled with minint. |
| 2813 __ cmp(output_reg, 0x80000000u); | 2795 __ cmp(output_reg, 0x80000000u); |
| 2814 DeoptimizeIf(equal, instr->environment()); | 2796 DeoptimizeIf(equal, instr->environment()); |
| 2815 __ jmp(&done); | 2797 __ jmp(&done); |
| 2816 | 2798 |
| 2817 __ bind(&below_half); | 2799 __ bind(&below_half); |
| (...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3116 | 3098 |
| 3117 __ mov(ecx, instr->name()); | 3099 __ mov(ecx, instr->name()); |
| 3118 Handle<Code> ic = instr->strict_mode() | 3100 Handle<Code> ic = instr->strict_mode() |
| 3119 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 3101 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
| 3120 : isolate()->builtins()->StoreIC_Initialize(); | 3102 : isolate()->builtins()->StoreIC_Initialize(); |
| 3121 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 3103 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 3122 } | 3104 } |
| 3123 | 3105 |
| 3124 | 3106 |
| 3125 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { | 3107 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { |
| 3126 __ cmp(ToRegister(instr->index()), ToOperand(instr->length())); | 3108 if (instr->index()->IsConstantOperand()) { |
| 3127 DeoptimizeIf(above_equal, instr->environment()); | 3109 __ cmp(ToOperand(instr->length()), |
| 3110 ToImmediate(LConstantOperand::cast(instr->index()))); |
| 3111 DeoptimizeIf(below_equal, instr->environment()); |
| 3112 } else { |
| 3113 __ cmp(ToRegister(instr->index()), ToOperand(instr->length())); |
| 3114 DeoptimizeIf(above_equal, instr->environment()); |
| 3115 } |
| 3128 } | 3116 } |
| 3129 | 3117 |
| 3130 | 3118 |
| 3131 void LCodeGen::DoStoreKeyedSpecializedArrayElement( | 3119 void LCodeGen::DoStoreKeyedSpecializedArrayElement( |
| 3132 LStoreKeyedSpecializedArrayElement* instr) { | 3120 LStoreKeyedSpecializedArrayElement* instr) { |
| 3133 JSObject::ElementsKind elements_kind = instr->elements_kind(); | 3121 JSObject::ElementsKind elements_kind = instr->elements_kind(); |
| 3134 Operand operand(BuildFastArrayOperand(instr->external_pointer(), | 3122 Operand operand(BuildFastArrayOperand(instr->external_pointer(), |
| 3135 instr->key(), elements_kind, 0)); | 3123 instr->key(), elements_kind, 0)); |
| 3136 if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) { | 3124 if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) { |
| 3137 __ cvtsd2ss(xmm0, ToDoubleRegister(instr->value())); | 3125 __ cvtsd2ss(xmm0, ToDoubleRegister(instr->value())); |
| (...skipping 1070 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4208 __ test_b(FieldOperand(input, Map::kBitFieldOffset), | 4196 __ test_b(FieldOperand(input, Map::kBitFieldOffset), |
| 4209 1 << Map::kIsUndetectable); | 4197 1 << Map::kIsUndetectable); |
| 4210 final_branch_condition = zero; | 4198 final_branch_condition = zero; |
| 4211 | 4199 |
| 4212 } else if (type_name->Equals(heap()->boolean_symbol())) { | 4200 } else if (type_name->Equals(heap()->boolean_symbol())) { |
| 4213 __ cmp(input, factory()->true_value()); | 4201 __ cmp(input, factory()->true_value()); |
| 4214 __ j(equal, true_label); | 4202 __ j(equal, true_label); |
| 4215 __ cmp(input, factory()->false_value()); | 4203 __ cmp(input, factory()->false_value()); |
| 4216 final_branch_condition = equal; | 4204 final_branch_condition = equal; |
| 4217 | 4205 |
| 4206 } else if (FLAG_harmony_typeof && type_name->Equals(heap()->null_symbol())) { |
| 4207 __ cmp(input, factory()->null_value()); |
| 4208 final_branch_condition = equal; |
| 4209 |
| 4218 } else if (type_name->Equals(heap()->undefined_symbol())) { | 4210 } else if (type_name->Equals(heap()->undefined_symbol())) { |
| 4219 __ cmp(input, factory()->undefined_value()); | 4211 __ cmp(input, factory()->undefined_value()); |
| 4220 __ j(equal, true_label); | 4212 __ j(equal, true_label); |
| 4221 __ JumpIfSmi(input, false_label); | 4213 __ JumpIfSmi(input, false_label); |
| 4222 // Check for undetectable objects => true. | 4214 // Check for undetectable objects => true. |
| 4223 __ mov(input, FieldOperand(input, HeapObject::kMapOffset)); | 4215 __ mov(input, FieldOperand(input, HeapObject::kMapOffset)); |
| 4224 __ test_b(FieldOperand(input, Map::kBitFieldOffset), | 4216 __ test_b(FieldOperand(input, Map::kBitFieldOffset), |
| 4225 1 << Map::kIsUndetectable); | 4217 1 << Map::kIsUndetectable); |
| 4226 final_branch_condition = not_zero; | 4218 final_branch_condition = not_zero; |
| 4227 | 4219 |
| 4228 } else if (type_name->Equals(heap()->function_symbol())) { | 4220 } else if (type_name->Equals(heap()->function_symbol())) { |
| 4229 STATIC_ASSERT(LAST_TYPE == LAST_CALLABLE_SPEC_OBJECT_TYPE); | 4221 STATIC_ASSERT(LAST_TYPE == LAST_CALLABLE_SPEC_OBJECT_TYPE); |
| 4230 __ JumpIfSmi(input, false_label); | 4222 __ JumpIfSmi(input, false_label); |
| 4231 __ CmpObjectType(input, FIRST_CALLABLE_SPEC_OBJECT_TYPE, input); | 4223 __ CmpObjectType(input, FIRST_CALLABLE_SPEC_OBJECT_TYPE, input); |
| 4232 final_branch_condition = above_equal; | 4224 final_branch_condition = above_equal; |
| 4233 | 4225 |
| 4234 } else if (type_name->Equals(heap()->object_symbol())) { | 4226 } else if (type_name->Equals(heap()->object_symbol())) { |
| 4235 __ JumpIfSmi(input, false_label); | 4227 __ JumpIfSmi(input, false_label); |
| 4236 __ cmp(input, factory()->null_value()); | 4228 if (!FLAG_harmony_typeof) { |
| 4237 __ j(equal, true_label); | 4229 __ cmp(input, factory()->null_value()); |
| 4230 __ j(equal, true_label); |
| 4231 } |
| 4238 __ CmpObjectType(input, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, input); | 4232 __ CmpObjectType(input, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, input); |
| 4239 __ j(below, false_label); | 4233 __ j(below, false_label); |
| 4240 __ CmpInstanceType(input, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); | 4234 __ CmpInstanceType(input, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); |
| 4241 __ j(above, false_label); | 4235 __ j(above, false_label); |
| 4242 // Check for undetectable objects => false. | 4236 // Check for undetectable objects => false. |
| 4243 __ test_b(FieldOperand(input, Map::kBitFieldOffset), | 4237 __ test_b(FieldOperand(input, Map::kBitFieldOffset), |
| 4244 1 << Map::kIsUndetectable); | 4238 1 << Map::kIsUndetectable); |
| 4245 final_branch_condition = zero; | 4239 final_branch_condition = zero; |
| 4246 | 4240 |
| 4247 } else { | 4241 } else { |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4414 env->deoptimization_index()); | 4408 env->deoptimization_index()); |
| 4415 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator); | 4409 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator); |
| 4416 } | 4410 } |
| 4417 | 4411 |
| 4418 | 4412 |
| 4419 #undef __ | 4413 #undef __ |
| 4420 | 4414 |
| 4421 } } // namespace v8::internal | 4415 } } // namespace v8::internal |
| 4422 | 4416 |
| 4423 #endif // V8_TARGET_ARCH_IA32 | 4417 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |