| 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 1328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1339 | 1339 |
| 1340 | 1340 |
| 1341 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { | 1341 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { |
| 1342 ASSERT(ToRegister(instr->context()).is(esi)); | 1342 ASSERT(ToRegister(instr->context()).is(esi)); |
| 1343 ASSERT(ToRegister(instr->left()).is(edx)); | 1343 ASSERT(ToRegister(instr->left()).is(edx)); |
| 1344 ASSERT(ToRegister(instr->right()).is(eax)); | 1344 ASSERT(ToRegister(instr->right()).is(eax)); |
| 1345 ASSERT(ToRegister(instr->result()).is(eax)); | 1345 ASSERT(ToRegister(instr->result()).is(eax)); |
| 1346 | 1346 |
| 1347 BinaryOpStub stub(instr->op(), NO_OVERWRITE); | 1347 BinaryOpStub stub(instr->op(), NO_OVERWRITE); |
| 1348 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 1348 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 1349 __ nop(); // Signals no inlined code. |
| 1349 } | 1350 } |
| 1350 | 1351 |
| 1351 | 1352 |
| 1352 int LCodeGen::GetNextEmittedBlock(int block) { | 1353 int LCodeGen::GetNextEmittedBlock(int block) { |
| 1353 for (int i = block + 1; i < graph()->blocks()->length(); ++i) { | 1354 for (int i = block + 1; i < graph()->blocks()->length(); ++i) { |
| 1354 LLabel* label = chunk_->GetLabel(i); | 1355 LLabel* label = chunk_->GetLabel(i); |
| 1355 if (!label->HasReplacement()) return i; | 1356 if (!label->HasReplacement()) return i; |
| 1356 } | 1357 } |
| 1357 return -1; | 1358 return -1; |
| 1358 } | 1359 } |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1386 __ test(reg, Operand(reg)); | 1387 __ test(reg, Operand(reg)); |
| 1387 EmitBranch(true_block, false_block, not_zero); | 1388 EmitBranch(true_block, false_block, not_zero); |
| 1388 } else if (r.IsDouble()) { | 1389 } else if (r.IsDouble()) { |
| 1389 XMMRegister reg = ToDoubleRegister(instr->InputAt(0)); | 1390 XMMRegister reg = ToDoubleRegister(instr->InputAt(0)); |
| 1390 __ xorps(xmm0, xmm0); | 1391 __ xorps(xmm0, xmm0); |
| 1391 __ ucomisd(reg, xmm0); | 1392 __ ucomisd(reg, xmm0); |
| 1392 EmitBranch(true_block, false_block, not_equal); | 1393 EmitBranch(true_block, false_block, not_equal); |
| 1393 } else { | 1394 } else { |
| 1394 ASSERT(r.IsTagged()); | 1395 ASSERT(r.IsTagged()); |
| 1395 Register reg = ToRegister(instr->InputAt(0)); | 1396 Register reg = ToRegister(instr->InputAt(0)); |
| 1396 if (instr->hydrogen()->value()->type().IsBoolean()) { | 1397 HType type = instr->hydrogen()->value()->type(); |
| 1398 if (type.IsBoolean()) { |
| 1397 __ cmp(reg, factory()->true_value()); | 1399 __ cmp(reg, factory()->true_value()); |
| 1398 EmitBranch(true_block, false_block, equal); | 1400 EmitBranch(true_block, false_block, equal); |
| 1401 } else if (type.IsSmi()) { |
| 1402 __ test(reg, Operand(reg)); |
| 1403 EmitBranch(true_block, false_block, not_equal); |
| 1399 } else { | 1404 } else { |
| 1400 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 1405 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
| 1401 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1406 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
| 1402 | 1407 |
| 1403 __ cmp(reg, factory()->undefined_value()); | 1408 ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types(); |
| 1404 __ j(equal, false_label); | 1409 // Avoid deopts in the case where we've never executed this path before. |
| 1405 __ cmp(reg, factory()->true_value()); | 1410 if (expected.IsEmpty()) expected = ToBooleanStub::all_types(); |
| 1406 __ j(equal, true_label); | |
| 1407 __ cmp(reg, factory()->false_value()); | |
| 1408 __ j(equal, false_label); | |
| 1409 __ test(reg, Operand(reg)); | |
| 1410 __ j(equal, false_label); | |
| 1411 __ JumpIfSmi(reg, true_label); | |
| 1412 | 1411 |
| 1413 // Test for double values. Zero is false. | 1412 if (expected.Contains(ToBooleanStub::UNDEFINED)) { |
| 1414 Label call_stub; | 1413 // undefined -> false. |
| 1415 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | 1414 __ cmp(reg, factory()->undefined_value()); |
| 1416 factory()->heap_number_map()); | 1415 __ j(equal, false_label); |
| 1417 __ j(not_equal, &call_stub, Label::kNear); | 1416 } else if (expected.Contains(ToBooleanStub::INTERNAL_OBJECT)) { |
| 1418 __ fldz(); | 1417 // We've seen undefined for the first time -> deopt. |
| 1419 __ fld_d(FieldOperand(reg, HeapNumber::kValueOffset)); | 1418 __ cmp(reg, factory()->undefined_value()); |
| 1420 __ FCmp(); | 1419 DeoptimizeIf(equal, instr->environment()); |
| 1421 __ j(zero, false_label); | 1420 } |
| 1422 __ jmp(true_label); | |
| 1423 | 1421 |
| 1424 // The conversion stub doesn't cause garbage collections so it's | 1422 if (expected.Contains(ToBooleanStub::BOOLEAN)) { |
| 1425 // safe to not record a safepoint after the call. | 1423 // true -> true. |
| 1426 __ bind(&call_stub); | 1424 __ cmp(reg, factory()->true_value()); |
| 1427 ToBooleanStub stub(eax); | 1425 __ j(equal, true_label); |
| 1428 __ pushad(); | 1426 } else if (expected.Contains(ToBooleanStub::INTERNAL_OBJECT)) { |
| 1429 __ push(reg); | 1427 // We've seen a boolean for the first time -> deopt. |
| 1430 __ CallStub(&stub); | 1428 __ cmp(reg, factory()->true_value()); |
| 1431 __ test(eax, Operand(eax)); | 1429 DeoptimizeIf(equal, instr->environment()); |
| 1432 __ popad(); | 1430 } |
| 1433 EmitBranch(true_block, false_block, not_zero); | 1431 |
| 1432 if (expected.Contains(ToBooleanStub::BOOLEAN)) { |
| 1433 // false -> false. |
| 1434 __ cmp(reg, factory()->false_value()); |
| 1435 __ 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 } |
| 1441 |
| 1442 if (expected.Contains(ToBooleanStub::NULL_TYPE)) { |
| 1443 // 'null' -> false. |
| 1444 __ cmp(reg, factory()->null_value()); |
| 1445 __ 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 } |
| 1451 |
| 1452 if (expected.Contains(ToBooleanStub::SMI)) { |
| 1453 // Smis: 0 -> false, all other -> true. |
| 1454 __ test(reg, Operand(reg)); |
| 1455 __ j(equal, false_label); |
| 1456 __ JumpIfSmi(reg, true_label); |
| 1457 } else if (expected.NeedsMap()) { |
| 1458 // If we need a map later and have a Smi -> deopt. |
| 1459 __ test(reg, Immediate(kSmiTagMask)); |
| 1460 DeoptimizeIf(zero, instr->environment()); |
| 1461 } |
| 1462 |
| 1463 Register map; |
| 1464 if (expected.NeedsMap()) { |
| 1465 map = ToRegister(instr->TempAt(0)); |
| 1466 ASSERT(!map.is(reg)); |
| 1467 __ mov(map, FieldOperand(reg, HeapObject::kMapOffset)); |
| 1468 // Everything with a map could be undetectable, so check this now. |
| 1469 __ test_b(FieldOperand(map, Map::kBitFieldOffset), |
| 1470 1 << Map::kIsUndetectable); |
| 1471 // Undetectable -> false. |
| 1472 __ j(not_zero, false_label); |
| 1473 } |
| 1474 |
| 1475 if (expected.Contains(ToBooleanStub::SPEC_OBJECT)) { |
| 1476 // spec object -> true. |
| 1477 __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE); |
| 1478 __ 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 } |
| 1484 |
| 1485 if (expected.Contains(ToBooleanStub::STRING)) { |
| 1486 // String value -> false iff empty. |
| 1487 Label not_string; |
| 1488 __ CmpInstanceType(map, FIRST_NONSTRING_TYPE); |
| 1489 __ j(above_equal, ¬_string, Label::kNear); |
| 1490 __ cmp(FieldOperand(reg, String::kLengthOffset), Immediate(0)); |
| 1491 __ j(not_zero, true_label); |
| 1492 __ jmp(false_label); |
| 1493 __ 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 } |
| 1499 |
| 1500 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) { |
| 1501 // heap number -> false iff +0, -0, or NaN. |
| 1502 Label not_heap_number; |
| 1503 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), |
| 1504 factory()->heap_number_map()); |
| 1505 __ j(not_equal, ¬_heap_number, Label::kNear); |
| 1506 __ fldz(); |
| 1507 __ fld_d(FieldOperand(reg, HeapNumber::kValueOffset)); |
| 1508 __ FCmp(); |
| 1509 __ j(zero, false_label); |
| 1510 __ jmp(true_label); |
| 1511 __ 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 } |
| 1518 |
| 1519 if (expected.Contains(ToBooleanStub::INTERNAL_OBJECT)) { |
| 1520 // internal objects -> true |
| 1521 __ jmp(true_label); |
| 1522 } else { |
| 1523 // We've seen something for the first time -> deopt. |
| 1524 DeoptimizeIf(no_condition, instr->environment()); |
| 1525 } |
| 1434 } | 1526 } |
| 1435 } | 1527 } |
| 1436 } | 1528 } |
| 1437 | 1529 |
| 1438 | 1530 |
| 1439 void LCodeGen::EmitGoto(int block) { | 1531 void LCodeGen::EmitGoto(int block) { |
| 1440 block = chunk_->LookupDestination(block); | 1532 block = chunk_->LookupDestination(block); |
| 1441 int next_block = GetNextEmittedBlock(current_block_); | 1533 int next_block = GetNextEmittedBlock(current_block_); |
| 1442 if (block != next_block) { | 1534 if (block != next_block) { |
| 1443 __ jmp(chunk_->GetAssemblyLabel(block)); | 1535 __ jmp(chunk_->GetAssemblyLabel(block)); |
| (...skipping 793 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2237 FixedArray::kHeaderSize)); | 2329 FixedArray::kHeaderSize)); |
| 2238 | 2330 |
| 2239 // Check for the hole value. | 2331 // Check for the hole value. |
| 2240 if (instr->hydrogen()->RequiresHoleCheck()) { | 2332 if (instr->hydrogen()->RequiresHoleCheck()) { |
| 2241 __ cmp(result, factory()->the_hole_value()); | 2333 __ cmp(result, factory()->the_hole_value()); |
| 2242 DeoptimizeIf(equal, instr->environment()); | 2334 DeoptimizeIf(equal, instr->environment()); |
| 2243 } | 2335 } |
| 2244 } | 2336 } |
| 2245 | 2337 |
| 2246 | 2338 |
| 2247 Operand LCodeGen::BuildExternalArrayOperand( | 2339 void LCodeGen::DoLoadKeyedFastDoubleElement( |
| 2340 LLoadKeyedFastDoubleElement* instr) { |
| 2341 XMMRegister result = ToDoubleRegister(instr->result()); |
| 2342 |
| 2343 if (instr->hydrogen()->RequiresHoleCheck()) { |
| 2344 int offset = FixedDoubleArray::kHeaderSize - kHeapObjectTag + |
| 2345 sizeof(kHoleNanLower32); |
| 2346 Operand hole_check_operand = BuildFastArrayOperand( |
| 2347 instr->elements(), instr->key(), |
| 2348 JSObject::FAST_DOUBLE_ELEMENTS, |
| 2349 offset); |
| 2350 __ cmp(hole_check_operand, Immediate(kHoleNanUpper32)); |
| 2351 DeoptimizeIf(equal, instr->environment()); |
| 2352 } |
| 2353 |
| 2354 Operand double_load_operand = BuildFastArrayOperand( |
| 2355 instr->elements(), instr->key(), JSObject::FAST_DOUBLE_ELEMENTS, |
| 2356 FixedDoubleArray::kHeaderSize - kHeapObjectTag); |
| 2357 __ movdbl(result, double_load_operand); |
| 2358 } |
| 2359 |
| 2360 |
| 2361 Operand LCodeGen::BuildFastArrayOperand( |
| 2248 LOperand* external_pointer, | 2362 LOperand* external_pointer, |
| 2249 LOperand* key, | 2363 LOperand* key, |
| 2250 JSObject::ElementsKind elements_kind) { | 2364 JSObject::ElementsKind elements_kind, |
| 2365 uint32_t offset) { |
| 2251 Register external_pointer_reg = ToRegister(external_pointer); | 2366 Register external_pointer_reg = ToRegister(external_pointer); |
| 2252 int shift_size = ElementsKindToShiftSize(elements_kind); | 2367 int shift_size = ElementsKindToShiftSize(elements_kind); |
| 2253 if (key->IsConstantOperand()) { | 2368 if (key->IsConstantOperand()) { |
| 2254 int constant_value = ToInteger32(LConstantOperand::cast(key)); | 2369 int constant_value = ToInteger32(LConstantOperand::cast(key)); |
| 2255 if (constant_value & 0xF0000000) { | 2370 if (constant_value & 0xF0000000) { |
| 2256 Abort("array index constant value too big"); | 2371 Abort("array index constant value too big"); |
| 2257 } | 2372 } |
| 2258 return Operand(external_pointer_reg, constant_value * (1 << shift_size)); | 2373 return Operand(external_pointer_reg, |
| 2374 constant_value * (1 << shift_size) + offset); |
| 2259 } else { | 2375 } else { |
| 2260 ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size); | 2376 ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size); |
| 2261 return Operand(external_pointer_reg, ToRegister(key), scale_factor, 0); | 2377 return Operand(external_pointer_reg, ToRegister(key), scale_factor, offset); |
| 2262 } | 2378 } |
| 2263 } | 2379 } |
| 2264 | 2380 |
| 2265 | 2381 |
| 2266 void LCodeGen::DoLoadKeyedSpecializedArrayElement( | 2382 void LCodeGen::DoLoadKeyedSpecializedArrayElement( |
| 2267 LLoadKeyedSpecializedArrayElement* instr) { | 2383 LLoadKeyedSpecializedArrayElement* instr) { |
| 2268 JSObject::ElementsKind elements_kind = instr->elements_kind(); | 2384 JSObject::ElementsKind elements_kind = instr->elements_kind(); |
| 2269 Operand operand(BuildExternalArrayOperand(instr->external_pointer(), | 2385 Operand operand(BuildFastArrayOperand(instr->external_pointer(), |
| 2270 instr->key(), elements_kind)); | 2386 instr->key(), elements_kind, 0)); |
| 2271 if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) { | 2387 if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) { |
| 2272 XMMRegister result(ToDoubleRegister(instr->result())); | 2388 XMMRegister result(ToDoubleRegister(instr->result())); |
| 2273 __ movss(result, operand); | 2389 __ movss(result, operand); |
| 2274 __ cvtss2sd(result, result); | 2390 __ cvtss2sd(result, result); |
| 2275 } else if (elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS) { | 2391 } else if (elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS) { |
| 2276 __ movdbl(ToDoubleRegister(instr->result()), operand); | 2392 __ movdbl(ToDoubleRegister(instr->result()), operand); |
| 2277 } else { | 2393 } else { |
| 2278 Register result(ToRegister(instr->result())); | 2394 Register result(ToRegister(instr->result())); |
| 2279 switch (elements_kind) { | 2395 switch (elements_kind) { |
| 2280 case JSObject::EXTERNAL_BYTE_ELEMENTS: | 2396 case JSObject::EXTERNAL_BYTE_ELEMENTS: |
| (...skipping 516 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2797 | 2913 |
| 2798 | 2914 |
| 2799 void LCodeGen::DoMathLog(LUnaryMathOperation* instr) { | 2915 void LCodeGen::DoMathLog(LUnaryMathOperation* instr) { |
| 2800 ASSERT(instr->value()->Equals(instr->result())); | 2916 ASSERT(instr->value()->Equals(instr->result())); |
| 2801 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 2917 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
| 2802 Label positive, done, zero; | 2918 Label positive, done, zero; |
| 2803 __ xorps(xmm0, xmm0); | 2919 __ xorps(xmm0, xmm0); |
| 2804 __ ucomisd(input_reg, xmm0); | 2920 __ ucomisd(input_reg, xmm0); |
| 2805 __ j(above, &positive, Label::kNear); | 2921 __ j(above, &positive, Label::kNear); |
| 2806 __ j(equal, &zero, Label::kNear); | 2922 __ j(equal, &zero, Label::kNear); |
| 2807 ExternalReference nan = ExternalReference::address_of_nan(); | 2923 ExternalReference nan = |
| 2924 ExternalReference::address_of_canonical_non_hole_nan(); |
| 2808 __ movdbl(input_reg, Operand::StaticVariable(nan)); | 2925 __ movdbl(input_reg, Operand::StaticVariable(nan)); |
| 2809 __ jmp(&done, Label::kNear); | 2926 __ jmp(&done, Label::kNear); |
| 2810 __ bind(&zero); | 2927 __ bind(&zero); |
| 2811 __ push(Immediate(0xFFF00000)); | 2928 __ push(Immediate(0xFFF00000)); |
| 2812 __ push(Immediate(0)); | 2929 __ push(Immediate(0)); |
| 2813 __ movdbl(input_reg, Operand(esp, 0)); | 2930 __ movdbl(input_reg, Operand(esp, 0)); |
| 2814 __ add(Operand(esp), Immediate(kDoubleSize)); | 2931 __ add(Operand(esp), Immediate(kDoubleSize)); |
| 2815 __ jmp(&done, Label::kNear); | 2932 __ jmp(&done, Label::kNear); |
| 2816 __ bind(&positive); | 2933 __ bind(&positive); |
| 2817 __ fldln2(); | 2934 __ fldln2(); |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3007 | 3124 |
| 3008 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { | 3125 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { |
| 3009 __ cmp(ToRegister(instr->index()), ToOperand(instr->length())); | 3126 __ cmp(ToRegister(instr->index()), ToOperand(instr->length())); |
| 3010 DeoptimizeIf(above_equal, instr->environment()); | 3127 DeoptimizeIf(above_equal, instr->environment()); |
| 3011 } | 3128 } |
| 3012 | 3129 |
| 3013 | 3130 |
| 3014 void LCodeGen::DoStoreKeyedSpecializedArrayElement( | 3131 void LCodeGen::DoStoreKeyedSpecializedArrayElement( |
| 3015 LStoreKeyedSpecializedArrayElement* instr) { | 3132 LStoreKeyedSpecializedArrayElement* instr) { |
| 3016 JSObject::ElementsKind elements_kind = instr->elements_kind(); | 3133 JSObject::ElementsKind elements_kind = instr->elements_kind(); |
| 3017 Operand operand(BuildExternalArrayOperand(instr->external_pointer(), | 3134 Operand operand(BuildFastArrayOperand(instr->external_pointer(), |
| 3018 instr->key(), elements_kind)); | 3135 instr->key(), elements_kind, 0)); |
| 3019 if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) { | 3136 if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) { |
| 3020 __ cvtsd2ss(xmm0, ToDoubleRegister(instr->value())); | 3137 __ cvtsd2ss(xmm0, ToDoubleRegister(instr->value())); |
| 3021 __ movss(operand, xmm0); | 3138 __ movss(operand, xmm0); |
| 3022 } else if (elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS) { | 3139 } else if (elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS) { |
| 3023 __ movdbl(operand, ToDoubleRegister(instr->value())); | 3140 __ movdbl(operand, ToDoubleRegister(instr->value())); |
| 3024 } else { | 3141 } else { |
| 3025 Register value = ToRegister(instr->value()); | 3142 Register value = ToRegister(instr->value()); |
| 3026 switch (elements_kind) { | 3143 switch (elements_kind) { |
| 3027 case JSObject::EXTERNAL_PIXEL_ELEMENTS: | 3144 case JSObject::EXTERNAL_PIXEL_ELEMENTS: |
| 3028 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 3145 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3075 __ lea(key, | 3192 __ lea(key, |
| 3076 FieldOperand(elements, | 3193 FieldOperand(elements, |
| 3077 key, | 3194 key, |
| 3078 times_pointer_size, | 3195 times_pointer_size, |
| 3079 FixedArray::kHeaderSize)); | 3196 FixedArray::kHeaderSize)); |
| 3080 __ RecordWrite(elements, key, value, kSaveFPRegs); | 3197 __ RecordWrite(elements, key, value, kSaveFPRegs); |
| 3081 } | 3198 } |
| 3082 } | 3199 } |
| 3083 | 3200 |
| 3084 | 3201 |
| 3202 void LCodeGen::DoStoreKeyedFastDoubleElement( |
| 3203 LStoreKeyedFastDoubleElement* instr) { |
| 3204 XMMRegister value = ToDoubleRegister(instr->value()); |
| 3205 Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg; |
| 3206 Label have_value; |
| 3207 |
| 3208 __ ucomisd(value, value); |
| 3209 __ j(parity_odd, &have_value); // NaN. |
| 3210 |
| 3211 ExternalReference canonical_nan_reference = |
| 3212 ExternalReference::address_of_canonical_non_hole_nan(); |
| 3213 __ movdbl(value, Operand::StaticVariable(canonical_nan_reference)); |
| 3214 __ bind(&have_value); |
| 3215 |
| 3216 Operand double_store_operand = BuildFastArrayOperand( |
| 3217 instr->elements(), instr->key(), JSObject::FAST_DOUBLE_ELEMENTS, |
| 3218 FixedDoubleArray::kHeaderSize - kHeapObjectTag); |
| 3219 __ movdbl(double_store_operand, value); |
| 3220 } |
| 3221 |
| 3222 |
| 3085 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { | 3223 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { |
| 3086 ASSERT(ToRegister(instr->context()).is(esi)); | 3224 ASSERT(ToRegister(instr->context()).is(esi)); |
| 3087 ASSERT(ToRegister(instr->object()).is(edx)); | 3225 ASSERT(ToRegister(instr->object()).is(edx)); |
| 3088 ASSERT(ToRegister(instr->key()).is(ecx)); | 3226 ASSERT(ToRegister(instr->key()).is(ecx)); |
| 3089 ASSERT(ToRegister(instr->value()).is(eax)); | 3227 ASSERT(ToRegister(instr->value()).is(eax)); |
| 3090 | 3228 |
| 3091 Handle<Code> ic = instr->strict_mode() | 3229 Handle<Code> ic = instr->strict_mode() |
| 3092 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 3230 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() |
| 3093 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 3231 : isolate()->builtins()->KeyedStoreIC_Initialize(); |
| 3094 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 3232 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| (...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3458 if (deoptimize_on_undefined) { | 3596 if (deoptimize_on_undefined) { |
| 3459 DeoptimizeIf(not_equal, env); | 3597 DeoptimizeIf(not_equal, env); |
| 3460 } else { | 3598 } else { |
| 3461 Label heap_number; | 3599 Label heap_number; |
| 3462 __ j(equal, &heap_number, Label::kNear); | 3600 __ j(equal, &heap_number, Label::kNear); |
| 3463 | 3601 |
| 3464 __ cmp(input_reg, factory()->undefined_value()); | 3602 __ cmp(input_reg, factory()->undefined_value()); |
| 3465 DeoptimizeIf(not_equal, env); | 3603 DeoptimizeIf(not_equal, env); |
| 3466 | 3604 |
| 3467 // Convert undefined to NaN. | 3605 // Convert undefined to NaN. |
| 3468 ExternalReference nan = ExternalReference::address_of_nan(); | 3606 ExternalReference nan = |
| 3607 ExternalReference::address_of_canonical_non_hole_nan(); |
| 3469 __ movdbl(result_reg, Operand::StaticVariable(nan)); | 3608 __ movdbl(result_reg, Operand::StaticVariable(nan)); |
| 3470 __ jmp(&done, Label::kNear); | 3609 __ jmp(&done, Label::kNear); |
| 3471 | 3610 |
| 3472 __ bind(&heap_number); | 3611 __ bind(&heap_number); |
| 3473 } | 3612 } |
| 3474 // Heap number to XMM conversion. | 3613 // Heap number to XMM conversion. |
| 3475 __ movdbl(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset)); | 3614 __ movdbl(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
| 3476 __ jmp(&done, Label::kNear); | 3615 __ jmp(&done, Label::kNear); |
| 3477 | 3616 |
| 3478 // Smi to XMM conversion | 3617 // Smi to XMM conversion |
| (...skipping 796 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4275 env->deoptimization_index()); | 4414 env->deoptimization_index()); |
| 4276 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator); | 4415 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator); |
| 4277 } | 4416 } |
| 4278 | 4417 |
| 4279 | 4418 |
| 4280 #undef __ | 4419 #undef __ |
| 4281 | 4420 |
| 4282 } } // namespace v8::internal | 4421 } } // namespace v8::internal |
| 4283 | 4422 |
| 4284 #endif // V8_TARGET_ARCH_IA32 | 4423 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |