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 1362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1373 Abort("DoHasCachedArrayIndex unimplemented."); | 1373 Abort("DoHasCachedArrayIndex unimplemented."); |
1374 } | 1374 } |
1375 | 1375 |
1376 | 1376 |
1377 void LCodeGen::DoHasCachedArrayIndexAndBranch( | 1377 void LCodeGen::DoHasCachedArrayIndexAndBranch( |
1378 LHasCachedArrayIndexAndBranch* instr) { | 1378 LHasCachedArrayIndexAndBranch* instr) { |
1379 Abort("DoHasCachedArrayIndexAndBranch unimplemented."); | 1379 Abort("DoHasCachedArrayIndexAndBranch unimplemented."); |
1380 } | 1380 } |
1381 | 1381 |
1382 | 1382 |
1383 // Branches to a label or falls through with the answer in the z flag. Trashes | 1383 // Branches to a label or falls through with the answer in the z flag. Trashes |
1384 // the temp registers, but not the input. Only input and temp2 may alias. | 1384 // the temp registers, but not the input. Only input and temp2 may alias. |
Søren Thygesen Gjesse
2011/01/10 09:56:08
input is trashed if temp2 aliases it.
Alexandre
2011/01/10 10:48:27
Indeed. Changed the code to have input and temp2 a
| |
1385 void LCodeGen::EmitClassOfTest(Label* is_true, | 1385 void LCodeGen::EmitClassOfTest(Label* is_true, |
1386 Label* is_false, | 1386 Label* is_false, |
1387 Handle<String>class_name, | 1387 Handle<String>class_name, |
1388 Register input, | 1388 Register input, |
1389 Register temp, | 1389 Register temp, |
1390 Register temp2) { | 1390 Register temp2) { |
1391 Abort("EmitClassOfTest unimplemented."); | 1391 ASSERT(!input.is(temp)); |
1392 ASSERT(!temp.is(temp2)); // But input and temp2 may be the same register. | |
1393 | |
1394 __ BranchOnSmi(input, is_false); | |
1395 | |
1396 __ CompareObjectType(input, temp, temp2, FIRST_JS_OBJECT_TYPE); | |
1397 __ b(lt, is_false); | |
1398 | |
Søren Thygesen Gjesse
2011/01/10 09:56:08
How about just
// temp: map of input
// temp2: o
Alexandre
2011/01/10 10:48:27
Done.
| |
1399 // After CompareObjectType: | |
1400 // - Input's map is in temp. | |
1401 // - Input's type is in temp2. | |
1402 | |
1403 // Functions have class 'Function'. | |
1404 __ cmp(temp2, Operand(JS_FUNCTION_TYPE)); | |
1405 if (class_name->IsEqualTo(CStrVector("Function"))) { | |
1406 __ b(eq, is_true); | |
1407 } else { | |
1408 __ b(eq, is_false); | |
1409 } | |
1410 | |
1411 // Check if the constructor in the map is a function. | |
1412 __ ldr(temp, FieldMemOperand(temp, Map::kConstructorOffset)); | |
Søren Thygesen Gjesse
2011/01/10 09:56:08
After this
// temp: constructor
Alexandre
2011/01/10 10:48:27
Done.
| |
1413 | |
1414 // As long as JS_FUNCTION_TYPE is the last instance type and it is | |
1415 // right after LAST_JS_OBJECT_TYPE, we can avoid checking for | |
1416 // LAST_JS_OBJECT_TYPE. | |
1417 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); | |
1418 ASSERT(JS_FUNCTION_TYPE == LAST_JS_OBJECT_TYPE + 1); | |
1419 | |
1420 // Objects with a non-function constructor have class 'Object'. | |
1421 __ CompareObjectType(temp, temp2, temp2, JS_FUNCTION_TYPE); | |
1422 if (class_name->IsEqualTo(CStrVector("Object"))) { | |
1423 __ b(ne, is_true); | |
1424 } else { | |
1425 __ b(ne, is_false); | |
1426 } | |
1427 | |
Søren Thygesen Gjesse
2011/01/10 09:56:08
Change comment to
// Get the instance class name
Alexandre
2011/01/10 10:48:27
Done.
| |
1428 // temp now contains the constructor function. Grab the | |
1429 // instance class name from there. | |
1430 __ ldr(temp, FieldMemOperand(temp, JSFunction::kSharedFunctionInfoOffset)); | |
1431 __ ldr(temp, FieldMemOperand(temp, | |
1432 SharedFunctionInfo::kInstanceClassNameOffset)); | |
1433 // The class name we are testing against is a symbol because it's a literal. | |
1434 // The name in the constructor is a symbol because of the way the context is | |
1435 // booted. This routine isn't expected to work for random API-created | |
1436 // classes and it doesn't have to because you can't access it with natives | |
1437 // syntax. Since both sides are symbols it is sufficient to use an identity | |
1438 // comparison. | |
1439 __ cmp(temp, Operand(class_name)); | |
1440 // End with the answer in the z flag. | |
1392 } | 1441 } |
1393 | 1442 |
1394 | 1443 |
1395 void LCodeGen::DoClassOfTest(LClassOfTest* instr) { | 1444 void LCodeGen::DoClassOfTest(LClassOfTest* instr) { |
Søren Thygesen Gjesse
2011/01/10 09:56:08
Maybe implement this now you have done EmitClassOf
Alexandre
2011/01/10 10:48:27
Implemented.
On 2011/01/10 09:56:08, Søren Gjesse
| |
1396 Abort("DoClassOfTest unimplemented."); | 1445 Abort("DoClassOfTest unimplemented."); |
1397 } | 1446 } |
1398 | 1447 |
1399 | 1448 |
1400 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { | 1449 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { |
1401 Abort("DoClassOfTestAndBranch unimplemented."); | 1450 Register input = ToRegister(instr->input()); |
1451 Register temp = ToRegister(instr->temporary()); | |
1452 Register temp2 = ToRegister(instr->temporary2()); | |
1453 if (input.is(temp)) { | |
1454 // Swap. | |
Søren Thygesen Gjesse
2011/01/10 09:56:08
There is a Swap instruction in the macro assembler
Alexandre
2011/01/10 10:48:27
Removed. Not needed anymore, as all these register
| |
1455 Register swapper = temp; | |
1456 temp = temp2; | |
1457 temp2 = swapper; | |
1458 } | |
1459 Handle<String> class_name = instr->hydrogen()->class_name(); | |
1460 | |
1461 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
1462 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
1463 | |
1464 Label* true_label = chunk_->GetAssemblyLabel(true_block); | |
1465 Label* false_label = chunk_->GetAssemblyLabel(false_block); | |
1466 | |
1467 EmitClassOfTest(true_label, false_label, class_name, input, temp, temp2); | |
1468 | |
1469 EmitBranch(true_block, false_block, eq); | |
1402 } | 1470 } |
1403 | 1471 |
1404 | 1472 |
1405 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { | 1473 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { |
1406 Register reg = ToRegister(instr->input()); | 1474 Register reg = ToRegister(instr->input()); |
1407 Register temp = ToRegister(instr->temp()); | 1475 Register temp = ToRegister(instr->temp()); |
1408 int true_block = instr->true_block_id(); | 1476 int true_block = instr->true_block_id(); |
1409 int false_block = instr->false_block_id(); | 1477 int false_block = instr->false_block_id(); |
1410 | 1478 |
1411 __ ldr(temp, FieldMemOperand(reg, HeapObject::kMapOffset)); | 1479 __ ldr(temp, FieldMemOperand(reg, HeapObject::kMapOffset)); |
(...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1777 Abort("DoDeferredMathAbsTaggedHeapNumber unimplemented."); | 1845 Abort("DoDeferredMathAbsTaggedHeapNumber unimplemented."); |
1778 } | 1846 } |
1779 | 1847 |
1780 | 1848 |
1781 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { | 1849 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { |
1782 Abort("DoMathAbs unimplemented."); | 1850 Abort("DoMathAbs unimplemented."); |
1783 } | 1851 } |
1784 | 1852 |
1785 | 1853 |
1786 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { | 1854 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { |
1787 Abort("DoMathFloor unimplemented."); | 1855 DoubleRegister input_reg = ToDoubleRegister(instr->input()); |
Søren Thygesen Gjesse
2011/01/10 09:56:08
input_reg -> input?
| |
1856 SwVfpRegister single_precision_scratch = s0; | |
Søren Thygesen Gjesse
2011/01/10 09:56:08
Please add double_scratch0() and single_scratch0()
| |
1857 Register result = ToRegister(instr->result()); | |
1858 Register scratch = scratch0(); | |
1859 | |
1860 // Set custom FPCSR: | |
1861 // - Set rounding mode to "Round towards Minus Infinity" | |
Søren Thygesen Gjesse
2011/01/10 09:56:08
No need to refer to specific bit numbers in the co
| |
1862 // (ie bits [23:22] = 0b10). | |
1863 // - Clear vfp cumulative exception flags (bits [3:0]). | |
1864 // - Make sure Flush-to-zero mode control bit is unset (bit 22). | |
1865 __ vmrs(scratch); | |
Søren Thygesen Gjesse
2011/01/10 09:56:08
Don't we need to backup and restore FPSCR here? Th
| |
1866 __ bic(scratch, scratch, | |
1867 Operand(kVFPExceptionMask | kVFPRoundingModeMask | kVFPFlushToZeroMask)); | |
1868 __ orr(scratch, scratch, Operand(kVFPRoundToMinusInfinityBits)); | |
1869 __ vmsr(scratch); | |
1870 | |
1871 // Convert the argument to an integer. | |
1872 __ vcvt_s32_f64(single_precision_scratch, | |
1873 input_reg, | |
1874 Assembler::FPSCRRounding, | |
1875 al); | |
1876 | |
1877 // Retrieve FPSCR and check for vfp exceptions. | |
1878 __ vmrs(scratch); | |
1879 __ tst(scratch, Operand(kVFPExceptionMask)); | |
1880 DeoptimizeIf(ne, instr->environment()); | |
1881 | |
1882 // Move the result back to general purpose register r0. | |
1883 __ vmov(result, single_precision_scratch); | |
1788 } | 1884 } |
1789 | 1885 |
1790 | 1886 |
1791 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { | 1887 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { |
1792 Abort("DoMathSqrt unimplemented."); | 1888 DoubleRegister input_reg = ToDoubleRegister(instr->input()); |
Søren Thygesen Gjesse
2011/01/10 09:56:08
input_reg -> input?
Alexandre
2011/01/10 10:48:27
Done.
| |
1889 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); | |
1890 __ vsqrt(input_reg, input_reg); | |
1793 } | 1891 } |
1794 | 1892 |
1795 | 1893 |
1796 void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) { | 1894 void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) { |
1797 switch (instr->op()) { | 1895 switch (instr->op()) { |
1798 case kMathAbs: | 1896 case kMathAbs: |
1799 DoMathAbs(instr); | 1897 DoMathAbs(instr); |
1800 break; | 1898 break; |
1801 case kMathFloor: | 1899 case kMathFloor: |
1802 DoMathFloor(instr); | 1900 DoMathFloor(instr); |
(...skipping 820 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2623 | 2721 |
2624 | 2722 |
2625 void LCodeGen::DoOsrEntry(LOsrEntry* instr) { | 2723 void LCodeGen::DoOsrEntry(LOsrEntry* instr) { |
2626 Abort("DoOsrEntry unimplemented."); | 2724 Abort("DoOsrEntry unimplemented."); |
2627 } | 2725 } |
2628 | 2726 |
2629 | 2727 |
2630 #undef __ | 2728 #undef __ |
2631 | 2729 |
2632 } } // namespace v8::internal | 2730 } } // namespace v8::internal |
OLD | NEW |