| 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 1195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1206 } | 1206 } |
| 1207 | 1207 |
| 1208 | 1208 |
| 1209 void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) { | 1209 void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) { |
| 1210 Register result = ToRegister(instr->result()); | 1210 Register result = ToRegister(instr->result()); |
| 1211 Register array = ToRegister(instr->InputAt(0)); | 1211 Register array = ToRegister(instr->InputAt(0)); |
| 1212 __ movq(result, FieldOperand(array, JSArray::kLengthOffset)); | 1212 __ movq(result, FieldOperand(array, JSArray::kLengthOffset)); |
| 1213 } | 1213 } |
| 1214 | 1214 |
| 1215 | 1215 |
| 1216 void LCodeGen::DoFixedArrayLength(LFixedArrayLength* instr) { | 1216 void LCodeGen::DoFixedArrayBaseLength(LFixedArrayBaseLength* instr) { |
| 1217 Register result = ToRegister(instr->result()); | 1217 Register result = ToRegister(instr->result()); |
| 1218 Register array = ToRegister(instr->InputAt(0)); | 1218 Register array = ToRegister(instr->InputAt(0)); |
| 1219 __ movq(result, FieldOperand(array, FixedArray::kLengthOffset)); | 1219 __ movq(result, FieldOperand(array, FixedArrayBase::kLengthOffset)); |
| 1220 } | |
| 1221 | |
| 1222 | |
| 1223 void LCodeGen::DoExternalArrayLength(LExternalArrayLength* instr) { | |
| 1224 Register result = ToRegister(instr->result()); | |
| 1225 Register array = ToRegister(instr->InputAt(0)); | |
| 1226 __ movl(result, FieldOperand(array, ExternalPixelArray::kLengthOffset)); | |
| 1227 } | 1220 } |
| 1228 | 1221 |
| 1229 | 1222 |
| 1230 void LCodeGen::DoElementsKind(LElementsKind* instr) { | 1223 void LCodeGen::DoElementsKind(LElementsKind* instr) { |
| 1231 Register result = ToRegister(instr->result()); | 1224 Register result = ToRegister(instr->result()); |
| 1232 Register input = ToRegister(instr->InputAt(0)); | 1225 Register input = ToRegister(instr->InputAt(0)); |
| 1233 | 1226 |
| 1234 // Load map into |result|. | 1227 // Load map into |result|. |
| 1235 __ movq(result, FieldOperand(input, HeapObject::kMapOffset)); | 1228 __ movq(result, FieldOperand(input, HeapObject::kMapOffset)); |
| 1236 // 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 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1400 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1393 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
| 1401 | 1394 |
| 1402 ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types(); | 1395 ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types(); |
| 1403 // Avoid deopts in the case where we've never executed this path before. | 1396 // Avoid deopts in the case where we've never executed this path before. |
| 1404 if (expected.IsEmpty()) expected = ToBooleanStub::all_types(); | 1397 if (expected.IsEmpty()) expected = ToBooleanStub::all_types(); |
| 1405 | 1398 |
| 1406 if (expected.Contains(ToBooleanStub::UNDEFINED)) { | 1399 if (expected.Contains(ToBooleanStub::UNDEFINED)) { |
| 1407 // undefined -> false. | 1400 // undefined -> false. |
| 1408 __ CompareRoot(reg, Heap::kUndefinedValueRootIndex); | 1401 __ CompareRoot(reg, Heap::kUndefinedValueRootIndex); |
| 1409 __ j(equal, false_label); | 1402 __ j(equal, false_label); |
| 1410 } else if (expected.Contains(ToBooleanStub::INTERNAL_OBJECT)) { | |
| 1411 // We've seen undefined for the first time -> deopt. | |
| 1412 __ CompareRoot(reg, Heap::kUndefinedValueRootIndex); | |
| 1413 DeoptimizeIf(equal, instr->environment()); | |
| 1414 } | 1403 } |
| 1415 | |
| 1416 if (expected.Contains(ToBooleanStub::BOOLEAN)) { | 1404 if (expected.Contains(ToBooleanStub::BOOLEAN)) { |
| 1417 // true -> true. | 1405 // true -> true. |
| 1418 __ CompareRoot(reg, Heap::kTrueValueRootIndex); | 1406 __ CompareRoot(reg, Heap::kTrueValueRootIndex); |
| 1419 __ j(equal, true_label); | 1407 __ j(equal, true_label); |
| 1420 } else if (expected.Contains(ToBooleanStub::INTERNAL_OBJECT)) { | |
| 1421 // We've seen a boolean for the first time -> deopt. | |
| 1422 __ CompareRoot(reg, Heap::kTrueValueRootIndex); | |
| 1423 DeoptimizeIf(equal, instr->environment()); | |
| 1424 } | |
| 1425 | |
| 1426 if (expected.Contains(ToBooleanStub::BOOLEAN)) { | |
| 1427 // false -> false. | 1408 // false -> false. |
| 1428 __ CompareRoot(reg, Heap::kFalseValueRootIndex); | 1409 __ CompareRoot(reg, Heap::kFalseValueRootIndex); |
| 1429 __ j(equal, false_label); | 1410 __ j(equal, false_label); |
| 1430 } else if (expected.Contains(ToBooleanStub::INTERNAL_OBJECT)) { | |
| 1431 // We've seen a boolean for the first time -> deopt. | |
| 1432 __ CompareRoot(reg, Heap::kFalseValueRootIndex); | |
| 1433 DeoptimizeIf(equal, instr->environment()); | |
| 1434 } | 1411 } |
| 1435 | |
| 1436 if (expected.Contains(ToBooleanStub::NULL_TYPE)) { | 1412 if (expected.Contains(ToBooleanStub::NULL_TYPE)) { |
| 1437 // 'null' -> false. | 1413 // 'null' -> false. |
| 1438 __ CompareRoot(reg, Heap::kNullValueRootIndex); | 1414 __ CompareRoot(reg, Heap::kNullValueRootIndex); |
| 1439 __ j(equal, false_label); | 1415 __ j(equal, false_label); |
| 1440 } else if (expected.Contains(ToBooleanStub::INTERNAL_OBJECT)) { | |
| 1441 // We've seen null for the first time -> deopt. | |
| 1442 __ CompareRoot(reg, Heap::kNullValueRootIndex); | |
| 1443 DeoptimizeIf(equal, instr->environment()); | |
| 1444 } | 1416 } |
| 1445 | 1417 |
| 1446 if (expected.Contains(ToBooleanStub::SMI)) { | 1418 if (expected.Contains(ToBooleanStub::SMI)) { |
| 1447 // Smis: 0 -> false, all other -> true. | 1419 // Smis: 0 -> false, all other -> true. |
| 1448 __ Cmp(reg, Smi::FromInt(0)); | 1420 __ Cmp(reg, Smi::FromInt(0)); |
| 1449 __ j(equal, false_label); | 1421 __ j(equal, false_label); |
| 1450 __ JumpIfSmi(reg, true_label); | 1422 __ JumpIfSmi(reg, true_label); |
| 1451 } else if (expected.NeedsMap()) { | 1423 } else if (expected.NeedsMap()) { |
| 1452 // If we need a map later and have a Smi -> deopt. | 1424 // If we need a map later and have a Smi -> deopt. |
| 1453 __ testb(reg, Immediate(kSmiTagMask)); | 1425 __ testb(reg, Immediate(kSmiTagMask)); |
| 1454 DeoptimizeIf(zero, instr->environment()); | 1426 DeoptimizeIf(zero, instr->environment()); |
| 1455 } | 1427 } |
| 1456 | 1428 |
| 1457 const Register map = kScratchRegister; | 1429 const Register map = kScratchRegister; |
| 1458 if (expected.NeedsMap()) { | 1430 if (expected.NeedsMap()) { |
| 1459 __ movq(map, FieldOperand(reg, HeapObject::kMapOffset)); | 1431 __ movq(map, FieldOperand(reg, HeapObject::kMapOffset)); |
| 1460 // Everything with a map could be undetectable, so check this now. | 1432 |
| 1461 __ testb(FieldOperand(map, Map::kBitFieldOffset), | 1433 if (expected.CanBeUndetectable()) { |
| 1462 Immediate(1 << Map::kIsUndetectable)); | 1434 // Undetectable -> false. |
| 1463 // Undetectable -> false. | 1435 __ testb(FieldOperand(map, Map::kBitFieldOffset), |
| 1464 __ j(not_zero, false_label); | 1436 Immediate(1 << Map::kIsUndetectable)); |
| 1437 __ j(not_zero, false_label); |
| 1438 } |
| 1465 } | 1439 } |
| 1466 | 1440 |
| 1467 if (expected.Contains(ToBooleanStub::SPEC_OBJECT)) { | 1441 if (expected.Contains(ToBooleanStub::SPEC_OBJECT)) { |
| 1468 // spec object -> true. | 1442 // spec object -> true. |
| 1469 __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE); | 1443 __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE); |
| 1470 __ j(above_equal, true_label); | 1444 __ j(above_equal, true_label); |
| 1471 } else if (expected.Contains(ToBooleanStub::INTERNAL_OBJECT)) { | |
| 1472 // We've seen a spec object for the first time -> deopt. | |
| 1473 __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE); | |
| 1474 DeoptimizeIf(above_equal, instr->environment()); | |
| 1475 } | 1445 } |
| 1476 | 1446 |
| 1477 if (expected.Contains(ToBooleanStub::STRING)) { | 1447 if (expected.Contains(ToBooleanStub::STRING)) { |
| 1478 // String value -> false iff empty. | 1448 // String value -> false iff empty. |
| 1479 Label not_string; | 1449 Label not_string; |
| 1480 __ CmpInstanceType(map, FIRST_NONSTRING_TYPE); | 1450 __ CmpInstanceType(map, FIRST_NONSTRING_TYPE); |
| 1481 __ j(above_equal, ¬_string, Label::kNear); | 1451 __ j(above_equal, ¬_string, Label::kNear); |
| 1482 __ cmpq(FieldOperand(reg, String::kLengthOffset), Immediate(0)); | 1452 __ cmpq(FieldOperand(reg, String::kLengthOffset), Immediate(0)); |
| 1483 __ j(not_zero, true_label); | 1453 __ j(not_zero, true_label); |
| 1484 __ jmp(false_label); | 1454 __ jmp(false_label); |
| 1485 __ bind(¬_string); | 1455 __ bind(¬_string); |
| 1486 } else if (expected.Contains(ToBooleanStub::INTERNAL_OBJECT)) { | |
| 1487 // We've seen a string for the first time -> deopt | |
| 1488 __ CmpInstanceType(map, FIRST_NONSTRING_TYPE); | |
| 1489 DeoptimizeIf(below, instr->environment()); | |
| 1490 } | 1456 } |
| 1491 | 1457 |
| 1492 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) { | 1458 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) { |
| 1493 // heap number -> false iff +0, -0, or NaN. | 1459 // heap number -> false iff +0, -0, or NaN. |
| 1494 Label not_heap_number; | 1460 Label not_heap_number; |
| 1495 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex); | 1461 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex); |
| 1496 __ j(not_equal, ¬_heap_number, Label::kNear); | 1462 __ j(not_equal, ¬_heap_number, Label::kNear); |
| 1497 __ xorps(xmm0, xmm0); | 1463 __ xorps(xmm0, xmm0); |
| 1498 __ ucomisd(xmm0, FieldOperand(reg, HeapNumber::kValueOffset)); | 1464 __ ucomisd(xmm0, FieldOperand(reg, HeapNumber::kValueOffset)); |
| 1499 __ j(zero, false_label); | 1465 __ j(zero, false_label); |
| 1500 __ jmp(true_label); | 1466 __ jmp(true_label); |
| 1501 __ bind(¬_heap_number); | 1467 __ bind(¬_heap_number); |
| 1502 } else if (expected.Contains(ToBooleanStub::INTERNAL_OBJECT)) { | |
| 1503 // We've seen a heap number for the first time -> deopt. | |
| 1504 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex); | |
| 1505 DeoptimizeIf(equal, instr->environment()); | |
| 1506 } | 1468 } |
| 1507 | 1469 |
| 1508 if (expected.Contains(ToBooleanStub::INTERNAL_OBJECT)) { | 1470 // We've seen something for the first time -> deopt. |
| 1509 // internal objects -> true | 1471 DeoptimizeIf(no_condition, instr->environment()); |
| 1510 __ jmp(true_label); | |
| 1511 } else { | |
| 1512 // We've seen something for the first time -> deopt. | |
| 1513 DeoptimizeIf(no_condition, instr->environment()); | |
| 1514 } | |
| 1515 } | 1472 } |
| 1516 } | 1473 } |
| 1517 } | 1474 } |
| 1518 | 1475 |
| 1519 | 1476 |
| 1520 void LCodeGen::EmitGoto(int block) { | 1477 void LCodeGen::EmitGoto(int block) { |
| 1521 block = chunk_->LookupDestination(block); | 1478 block = chunk_->LookupDestination(block); |
| 1522 int next_block = GetNextEmittedBlock(current_block_); | 1479 int next_block = GetNextEmittedBlock(current_block_); |
| 1523 if (block != next_block) { | 1480 if (block != next_block) { |
| 1524 __ jmp(chunk_->GetAssemblyLabel(block)); | 1481 __ jmp(chunk_->GetAssemblyLabel(block)); |
| (...skipping 784 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2309 } | 2266 } |
| 2310 DeoptimizeIf(below_equal, instr->environment()); | 2267 DeoptimizeIf(below_equal, instr->environment()); |
| 2311 | 2268 |
| 2312 // There are two words between the frame pointer and the last argument. | 2269 // There are two words between the frame pointer and the last argument. |
| 2313 // Subtracting from length accounts for one of them add one more. | 2270 // Subtracting from length accounts for one of them add one more. |
| 2314 __ movq(result, Operand(arguments, length, times_pointer_size, kPointerSize)); | 2271 __ movq(result, Operand(arguments, length, times_pointer_size, kPointerSize)); |
| 2315 } | 2272 } |
| 2316 | 2273 |
| 2317 | 2274 |
| 2318 void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) { | 2275 void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) { |
| 2319 Register elements = ToRegister(instr->elements()); | |
| 2320 Register key = ToRegister(instr->key()); | |
| 2321 Register result = ToRegister(instr->result()); | 2276 Register result = ToRegister(instr->result()); |
| 2322 ASSERT(result.is(elements)); | |
| 2323 | 2277 |
| 2324 // Load the result. | 2278 // Load the result. |
| 2325 __ movq(result, FieldOperand(elements, | 2279 __ movq(result, |
| 2326 key, | 2280 BuildFastArrayOperand(instr->elements(), instr->key(), |
| 2327 times_pointer_size, | 2281 JSObject::FAST_ELEMENTS, |
| 2328 FixedArray::kHeaderSize)); | 2282 FixedArray::kHeaderSize - kHeapObjectTag)); |
| 2329 | 2283 |
| 2330 // Check for the hole value. | 2284 // Check for the hole value. |
| 2331 if (instr->hydrogen()->RequiresHoleCheck()) { | 2285 if (instr->hydrogen()->RequiresHoleCheck()) { |
| 2332 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); | 2286 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); |
| 2333 DeoptimizeIf(equal, instr->environment()); | 2287 DeoptimizeIf(equal, instr->environment()); |
| 2334 } | 2288 } |
| 2335 } | 2289 } |
| 2336 | 2290 |
| 2337 | 2291 |
| 2338 void LCodeGen::DoLoadKeyedFastDoubleElement( | 2292 void LCodeGen::DoLoadKeyedFastDoubleElement( |
| (...skipping 13 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 __ movsd(result, double_load_operand); | 2311 __ movsd(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), | 2331 return Operand(elements_pointer_reg, ToRegister(key), |
| 2378 scale_factor, offset); | 2332 scale_factor, offset); |
| 2379 } | 2333 } |
| 2380 } | 2334 } |
| 2381 | 2335 |
| 2382 | 2336 |
| 2383 void LCodeGen::DoLoadKeyedSpecializedArrayElement( | 2337 void LCodeGen::DoLoadKeyedSpecializedArrayElement( |
| 2384 LLoadKeyedSpecializedArrayElement* instr) { | 2338 LLoadKeyedSpecializedArrayElement* instr) { |
| 2385 JSObject::ElementsKind elements_kind = instr->elements_kind(); | 2339 JSObject::ElementsKind elements_kind = instr->elements_kind(); |
| 2386 Operand operand(BuildFastArrayOperand(instr->external_pointer(), | 2340 Operand operand(BuildFastArrayOperand(instr->external_pointer(), |
| 2387 instr->key(), elements_kind, 0)); | 2341 instr->key(), elements_kind, 0)); |
| (...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2763 __ Integer32ToSmi(input_reg, input_reg); | 2717 __ Integer32ToSmi(input_reg, input_reg); |
| 2764 __ bind(deferred->exit()); | 2718 __ bind(deferred->exit()); |
| 2765 } | 2719 } |
| 2766 } | 2720 } |
| 2767 | 2721 |
| 2768 | 2722 |
| 2769 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { | 2723 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { |
| 2770 XMMRegister xmm_scratch = xmm0; | 2724 XMMRegister xmm_scratch = xmm0; |
| 2771 Register output_reg = ToRegister(instr->result()); | 2725 Register output_reg = ToRegister(instr->result()); |
| 2772 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); | 2726 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); |
| 2727 Label done; |
| 2773 | 2728 |
| 2774 if (CpuFeatures::IsSupported(SSE4_1)) { | 2729 if (CpuFeatures::IsSupported(SSE4_1)) { |
| 2775 CpuFeatures::Scope scope(SSE4_1); | 2730 CpuFeatures::Scope scope(SSE4_1); |
| 2776 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 2731 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 2777 // Deoptimize if minus zero. | 2732 // Deoptimize if minus zero. |
| 2778 __ movq(output_reg, input_reg); | 2733 __ movq(output_reg, input_reg); |
| 2779 __ subq(output_reg, Immediate(1)); | 2734 __ subq(output_reg, Immediate(1)); |
| 2780 DeoptimizeIf(overflow, instr->environment()); | 2735 DeoptimizeIf(overflow, instr->environment()); |
| 2781 } | 2736 } |
| 2782 __ roundsd(xmm_scratch, input_reg, Assembler::kRoundDown); | 2737 __ roundsd(xmm_scratch, input_reg, Assembler::kRoundDown); |
| 2783 __ cvttsd2si(output_reg, xmm_scratch); | 2738 __ cvttsd2si(output_reg, xmm_scratch); |
| 2784 __ cmpl(output_reg, Immediate(0x80000000)); | 2739 __ cmpl(output_reg, Immediate(0x80000000)); |
| 2785 DeoptimizeIf(equal, instr->environment()); | 2740 DeoptimizeIf(equal, instr->environment()); |
| 2786 } else { | 2741 } else { |
| 2742 // Deoptimize on negative inputs. |
| 2787 __ xorps(xmm_scratch, xmm_scratch); // Zero the register. | 2743 __ xorps(xmm_scratch, xmm_scratch); // Zero the register. |
| 2788 __ ucomisd(input_reg, xmm_scratch); | 2744 __ ucomisd(input_reg, xmm_scratch); |
| 2789 | 2745 DeoptimizeIf(below, instr->environment()); |
| 2790 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 2746 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 2791 DeoptimizeIf(below_equal, instr->environment()); | 2747 // Check for negative zero. |
| 2792 } else { | 2748 Label positive_sign; |
| 2793 DeoptimizeIf(below, instr->environment()); | 2749 __ j(above, &positive_sign, Label::kNear); |
| 2750 __ movmskpd(output_reg, input_reg); |
| 2751 __ testq(output_reg, Immediate(1)); |
| 2752 DeoptimizeIf(not_zero, instr->environment()); |
| 2753 __ Set(output_reg, 0); |
| 2754 __ jmp(&done); |
| 2755 __ bind(&positive_sign); |
| 2794 } | 2756 } |
| 2795 | 2757 |
| 2796 // Use truncating instruction (OK because input is positive). | 2758 // Use truncating instruction (OK because input is positive). |
| 2797 __ cvttsd2si(output_reg, input_reg); | 2759 __ cvttsd2si(output_reg, input_reg); |
| 2798 | 2760 |
| 2799 // Overflow is signalled with minint. | 2761 // Overflow is signalled with minint. |
| 2800 __ cmpl(output_reg, Immediate(0x80000000)); | 2762 __ cmpl(output_reg, Immediate(0x80000000)); |
| 2801 DeoptimizeIf(equal, instr->environment()); | 2763 DeoptimizeIf(equal, instr->environment()); |
| 2802 } | 2764 } |
| 2765 __ bind(&done); |
| 2803 } | 2766 } |
| 2804 | 2767 |
| 2805 | 2768 |
| 2806 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { | 2769 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { |
| 2807 const XMMRegister xmm_scratch = xmm0; | 2770 const XMMRegister xmm_scratch = xmm0; |
| 2808 Register output_reg = ToRegister(instr->result()); | 2771 Register output_reg = ToRegister(instr->result()); |
| 2809 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); | 2772 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); |
| 2810 | 2773 |
| 2811 Label done; | 2774 Label done; |
| 2812 // xmm_scratch = 0.5 | 2775 // xmm_scratch = 0.5 |
| (...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3141 case JSObject::DICTIONARY_ELEMENTS: | 3104 case JSObject::DICTIONARY_ELEMENTS: |
| 3142 case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS: | 3105 case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS: |
| 3143 UNREACHABLE(); | 3106 UNREACHABLE(); |
| 3144 break; | 3107 break; |
| 3145 } | 3108 } |
| 3146 } | 3109 } |
| 3147 } | 3110 } |
| 3148 | 3111 |
| 3149 | 3112 |
| 3150 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { | 3113 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { |
| 3151 if (instr->length()->IsRegister()) { | 3114 if (instr->index()->IsConstantOperand()) { |
| 3152 __ cmpq(ToRegister(instr->index()), ToRegister(instr->length())); | 3115 if (instr->length()->IsRegister()) { |
| 3116 __ cmpq(ToRegister(instr->length()), |
| 3117 Immediate(ToInteger32(LConstantOperand::cast(instr->index())))); |
| 3118 } else { |
| 3119 __ cmpq(ToOperand(instr->length()), |
| 3120 Immediate(ToInteger32(LConstantOperand::cast(instr->index())))); |
| 3121 } |
| 3153 } else { | 3122 } else { |
| 3154 __ cmpq(ToRegister(instr->index()), ToOperand(instr->length())); | 3123 if (instr->length()->IsRegister()) { |
| 3124 __ cmpq(ToRegister(instr->length()), ToRegister(instr->index())); |
| 3125 } else { |
| 3126 __ cmpq(ToOperand(instr->length()), ToRegister(instr->index())); |
| 3127 } |
| 3155 } | 3128 } |
| 3156 DeoptimizeIf(above_equal, instr->environment()); | 3129 DeoptimizeIf(below_equal, instr->environment()); |
| 3157 } | 3130 } |
| 3158 | 3131 |
| 3159 | 3132 |
| 3160 void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) { | 3133 void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) { |
| 3161 Register value = ToRegister(instr->value()); | 3134 Register value = ToRegister(instr->value()); |
| 3162 Register elements = ToRegister(instr->object()); | 3135 Register elements = ToRegister(instr->object()); |
| 3163 Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg; | 3136 Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg; |
| 3164 | 3137 |
| 3165 // Do the store. | 3138 // Do the store. |
| 3166 if (instr->key()->IsConstantOperand()) { | 3139 if (instr->key()->IsConstantOperand()) { |
| (...skipping 845 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4012 __ testb(FieldOperand(input, Map::kBitFieldOffset), | 3985 __ testb(FieldOperand(input, Map::kBitFieldOffset), |
| 4013 Immediate(1 << Map::kIsUndetectable)); | 3986 Immediate(1 << Map::kIsUndetectable)); |
| 4014 final_branch_condition = zero; | 3987 final_branch_condition = zero; |
| 4015 | 3988 |
| 4016 } else if (type_name->Equals(heap()->boolean_symbol())) { | 3989 } else if (type_name->Equals(heap()->boolean_symbol())) { |
| 4017 __ CompareRoot(input, Heap::kTrueValueRootIndex); | 3990 __ CompareRoot(input, Heap::kTrueValueRootIndex); |
| 4018 __ j(equal, true_label); | 3991 __ j(equal, true_label); |
| 4019 __ CompareRoot(input, Heap::kFalseValueRootIndex); | 3992 __ CompareRoot(input, Heap::kFalseValueRootIndex); |
| 4020 final_branch_condition = equal; | 3993 final_branch_condition = equal; |
| 4021 | 3994 |
| 3995 } else if (FLAG_harmony_typeof && type_name->Equals(heap()->null_symbol())) { |
| 3996 __ CompareRoot(input, Heap::kNullValueRootIndex); |
| 3997 final_branch_condition = equal; |
| 3998 |
| 4022 } else if (type_name->Equals(heap()->undefined_symbol())) { | 3999 } else if (type_name->Equals(heap()->undefined_symbol())) { |
| 4023 __ CompareRoot(input, Heap::kUndefinedValueRootIndex); | 4000 __ CompareRoot(input, Heap::kUndefinedValueRootIndex); |
| 4024 __ j(equal, true_label); | 4001 __ j(equal, true_label); |
| 4025 __ JumpIfSmi(input, false_label); | 4002 __ JumpIfSmi(input, false_label); |
| 4026 // Check for undetectable objects => true. | 4003 // Check for undetectable objects => true. |
| 4027 __ movq(input, FieldOperand(input, HeapObject::kMapOffset)); | 4004 __ movq(input, FieldOperand(input, HeapObject::kMapOffset)); |
| 4028 __ testb(FieldOperand(input, Map::kBitFieldOffset), | 4005 __ testb(FieldOperand(input, Map::kBitFieldOffset), |
| 4029 Immediate(1 << Map::kIsUndetectable)); | 4006 Immediate(1 << Map::kIsUndetectable)); |
| 4030 final_branch_condition = not_zero; | 4007 final_branch_condition = not_zero; |
| 4031 | 4008 |
| 4032 } else if (type_name->Equals(heap()->function_symbol())) { | 4009 } else if (type_name->Equals(heap()->function_symbol())) { |
| 4033 __ JumpIfSmi(input, false_label); | 4010 __ JumpIfSmi(input, false_label); |
| 4034 __ CmpObjectType(input, FIRST_CALLABLE_SPEC_OBJECT_TYPE, input); | 4011 __ CmpObjectType(input, FIRST_CALLABLE_SPEC_OBJECT_TYPE, input); |
| 4035 final_branch_condition = above_equal; | 4012 final_branch_condition = above_equal; |
| 4036 | 4013 |
| 4037 } else if (type_name->Equals(heap()->object_symbol())) { | 4014 } else if (type_name->Equals(heap()->object_symbol())) { |
| 4038 __ JumpIfSmi(input, false_label); | 4015 __ JumpIfSmi(input, false_label); |
| 4039 __ CompareRoot(input, Heap::kNullValueRootIndex); | 4016 if (!FLAG_harmony_typeof) { |
| 4040 __ j(equal, true_label); | 4017 __ CompareRoot(input, Heap::kNullValueRootIndex); |
| 4018 __ j(equal, true_label); |
| 4019 } |
| 4041 __ CmpObjectType(input, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, input); | 4020 __ CmpObjectType(input, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, input); |
| 4042 __ j(below, false_label); | 4021 __ j(below, false_label); |
| 4043 __ CmpInstanceType(input, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); | 4022 __ CmpInstanceType(input, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); |
| 4044 __ j(above, false_label); | 4023 __ j(above, false_label); |
| 4045 // Check for undetectable objects => false. | 4024 // Check for undetectable objects => false. |
| 4046 __ testb(FieldOperand(input, Map::kBitFieldOffset), | 4025 __ testb(FieldOperand(input, Map::kBitFieldOffset), |
| 4047 Immediate(1 << Map::kIsUndetectable)); | 4026 Immediate(1 << Map::kIsUndetectable)); |
| 4048 final_branch_condition = zero; | 4027 final_branch_condition = zero; |
| 4049 | 4028 |
| 4050 } else { | 4029 } else { |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4195 RegisterEnvironmentForDeoptimization(environment); | 4174 RegisterEnvironmentForDeoptimization(environment); |
| 4196 ASSERT(osr_pc_offset_ == -1); | 4175 ASSERT(osr_pc_offset_ == -1); |
| 4197 osr_pc_offset_ = masm()->pc_offset(); | 4176 osr_pc_offset_ = masm()->pc_offset(); |
| 4198 } | 4177 } |
| 4199 | 4178 |
| 4200 #undef __ | 4179 #undef __ |
| 4201 | 4180 |
| 4202 } } // namespace v8::internal | 4181 } } // namespace v8::internal |
| 4203 | 4182 |
| 4204 #endif // V8_TARGET_ARCH_X64 | 4183 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |