Chromium Code Reviews| 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 |