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 940 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
951 Register result = ToRegister(instr->result()); | 951 Register result = ToRegister(instr->result()); |
952 Register array = ToRegister(instr->input()); | 952 Register array = ToRegister(instr->input()); |
953 __ ldr(result, FieldMemOperand(array, JSArray::kLengthOffset)); | 953 __ ldr(result, FieldMemOperand(array, JSArray::kLengthOffset)); |
954 } | 954 } |
955 | 955 |
956 | 956 |
957 void LCodeGen::DoFixedArrayLength(LFixedArrayLength* instr) { | 957 void LCodeGen::DoFixedArrayLength(LFixedArrayLength* instr) { |
958 Register result = ToRegister(instr->result()); | 958 Register result = ToRegister(instr->result()); |
959 Register array = ToRegister(instr->input()); | 959 Register array = ToRegister(instr->input()); |
960 __ ldr(result, FieldMemOperand(array, FixedArray::kLengthOffset)); | 960 __ ldr(result, FieldMemOperand(array, FixedArray::kLengthOffset)); |
961 Abort("DoFixedArrayLength untested."); | |
962 } | 961 } |
963 | 962 |
964 | 963 |
965 void LCodeGen::DoValueOf(LValueOf* instr) { | 964 void LCodeGen::DoValueOf(LValueOf* instr) { |
966 Abort("DoValueOf unimplemented."); | 965 Register input = ToRegister(instr->input()); |
| 966 Register result = ToRegister(instr->result()); |
| 967 Register map = ToRegister(instr->temporary()); |
| 968 ASSERT(input.is(result)); |
| 969 Label done; |
| 970 |
| 971 // If the object is a smi return the object. |
| 972 __ tst(input, Operand(kSmiTagMask)); |
| 973 __ b(eq, &done); |
| 974 |
| 975 // If the object is not a value type, return the object. |
| 976 __ CompareObjectType(input, map, map, JS_VALUE_TYPE); |
| 977 __ b(ne, &done); |
| 978 __ ldr(result, FieldMemOperand(input, JSValue::kValueOffset)); |
| 979 |
| 980 __ bind(&done); |
967 } | 981 } |
968 | 982 |
969 | 983 |
970 void LCodeGen::DoBitNotI(LBitNotI* instr) { | 984 void LCodeGen::DoBitNotI(LBitNotI* instr) { |
971 LOperand* input = instr->input(); | 985 LOperand* input = instr->input(); |
972 ASSERT(input->Equals(instr->result())); | 986 ASSERT(input->Equals(instr->result())); |
973 __ mvn(ToRegister(input), Operand(ToRegister(input))); | 987 __ mvn(ToRegister(input), Operand(ToRegister(input))); |
974 Abort("DoBitNotI untested."); | |
975 } | 988 } |
976 | 989 |
977 | 990 |
978 void LCodeGen::DoThrow(LThrow* instr) { | 991 void LCodeGen::DoThrow(LThrow* instr) { |
979 Register input_reg = EmitLoadRegister(instr->input(), ip); | 992 Register input_reg = EmitLoadRegister(instr->input(), ip); |
980 __ push(input_reg); | 993 __ push(input_reg); |
981 CallRuntime(Runtime::kThrow, 1, instr); | 994 CallRuntime(Runtime::kThrow, 1, instr); |
982 | 995 |
983 if (FLAG_debug_code) { | 996 if (FLAG_debug_code) { |
984 __ stop("Unreachable code."); | 997 __ stop("Unreachable code."); |
(...skipping 416 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1401 Abort("DoHasCachedArrayIndex unimplemented."); | 1414 Abort("DoHasCachedArrayIndex unimplemented."); |
1402 } | 1415 } |
1403 | 1416 |
1404 | 1417 |
1405 void LCodeGen::DoHasCachedArrayIndexAndBranch( | 1418 void LCodeGen::DoHasCachedArrayIndexAndBranch( |
1406 LHasCachedArrayIndexAndBranch* instr) { | 1419 LHasCachedArrayIndexAndBranch* instr) { |
1407 Abort("DoHasCachedArrayIndexAndBranch unimplemented."); | 1420 Abort("DoHasCachedArrayIndexAndBranch unimplemented."); |
1408 } | 1421 } |
1409 | 1422 |
1410 | 1423 |
1411 // Branches to a label or falls through with the answer in the z flag. Trashes | 1424 // Branches to a label or falls through with the answer in flags. Trashes |
1412 // the temp registers, but not the input. Only input and temp2 may alias. | 1425 // the temp registers, but not the input. Only input and temp2 may alias. |
1413 void LCodeGen::EmitClassOfTest(Label* is_true, | 1426 void LCodeGen::EmitClassOfTest(Label* is_true, |
1414 Label* is_false, | 1427 Label* is_false, |
1415 Handle<String>class_name, | 1428 Handle<String>class_name, |
1416 Register input, | 1429 Register input, |
1417 Register temp, | 1430 Register temp, |
1418 Register temp2) { | 1431 Register temp2) { |
1419 Abort("EmitClassOfTest unimplemented."); | 1432 ASSERT(!input.is(temp)); |
| 1433 ASSERT(!temp.is(temp2)); // But input and temp2 may be the same register. |
| 1434 __ tst(input, Operand(kSmiTagMask)); |
| 1435 __ b(eq, is_false); |
| 1436 __ CompareObjectType(input, temp, temp2, FIRST_JS_OBJECT_TYPE); |
| 1437 __ b(lt, is_false); |
| 1438 |
| 1439 // Map is now in temp. |
| 1440 // Functions have class 'Function'. |
| 1441 __ CompareInstanceType(temp, temp2, JS_FUNCTION_TYPE); |
| 1442 if (class_name->IsEqualTo(CStrVector("Function"))) { |
| 1443 __ b(eq, is_true); |
| 1444 } else { |
| 1445 __ b(eq, is_false); |
| 1446 } |
| 1447 |
| 1448 // Check if the constructor in the map is a function. |
| 1449 __ ldr(temp, FieldMemOperand(temp, Map::kConstructorOffset)); |
| 1450 |
| 1451 // As long as JS_FUNCTION_TYPE is the last instance type and it is |
| 1452 // right after LAST_JS_OBJECT_TYPE, we can avoid checking for |
| 1453 // LAST_JS_OBJECT_TYPE. |
| 1454 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); |
| 1455 ASSERT(JS_FUNCTION_TYPE == LAST_JS_OBJECT_TYPE + 1); |
| 1456 |
| 1457 // Objects with a non-function constructor have class 'Object'. |
| 1458 __ CompareObjectType(temp, temp2, temp2, JS_FUNCTION_TYPE); |
| 1459 if (class_name->IsEqualTo(CStrVector("Object"))) { |
| 1460 __ b(ne, is_true); |
| 1461 } else { |
| 1462 __ b(ne, is_false); |
| 1463 } |
| 1464 |
| 1465 // temp now contains the constructor function. Grab the |
| 1466 // instance class name from there. |
| 1467 __ ldr(temp, FieldMemOperand(temp, JSFunction::kSharedFunctionInfoOffset)); |
| 1468 __ ldr(temp, FieldMemOperand(temp, |
| 1469 SharedFunctionInfo::kInstanceClassNameOffset)); |
| 1470 // The class name we are testing against is a symbol because it's a literal. |
| 1471 // The name in the constructor is a symbol because of the way the context is |
| 1472 // booted. This routine isn't expected to work for random API-created |
| 1473 // classes and it doesn't have to because you can't access it with natives |
| 1474 // syntax. Since both sides are symbols it is sufficient to use an identity |
| 1475 // comparison. |
| 1476 __ cmp(temp, Operand(class_name)); |
| 1477 // End with the answer in flags. |
1420 } | 1478 } |
1421 | 1479 |
1422 | 1480 |
1423 void LCodeGen::DoClassOfTest(LClassOfTest* instr) { | 1481 void LCodeGen::DoClassOfTest(LClassOfTest* instr) { |
1424 Abort("DoClassOfTest unimplemented."); | 1482 Register input = ToRegister(instr->input()); |
| 1483 Register result = ToRegister(instr->result()); |
| 1484 ASSERT(input.is(result)); |
| 1485 Handle<String> class_name = instr->hydrogen()->class_name(); |
| 1486 |
| 1487 Label done, is_true, is_false; |
| 1488 |
| 1489 EmitClassOfTest(&is_true, &is_false, class_name, input, scratch0(), input); |
| 1490 __ b(ne, &is_false); |
| 1491 |
| 1492 __ bind(&is_true); |
| 1493 __ LoadRoot(result, Heap::kTrueValueRootIndex); |
| 1494 __ jmp(&done); |
| 1495 |
| 1496 __ bind(&is_false); |
| 1497 __ LoadRoot(result, Heap::kFalseValueRootIndex); |
| 1498 __ bind(&done); |
1425 } | 1499 } |
1426 | 1500 |
1427 | 1501 |
1428 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { | 1502 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { |
1429 Abort("DoClassOfTestAndBranch unimplemented."); | 1503 Register input = ToRegister(instr->input()); |
| 1504 Register temp = scratch0(); |
| 1505 Register temp2 = ToRegister(instr->temporary()); |
| 1506 Handle<String> class_name = instr->hydrogen()->class_name(); |
| 1507 |
| 1508 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1509 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1510 |
| 1511 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
| 1512 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
| 1513 |
| 1514 EmitClassOfTest(true_label, false_label, class_name, input, temp, temp2); |
| 1515 |
| 1516 EmitBranch(true_block, false_block, eq); |
1430 } | 1517 } |
1431 | 1518 |
1432 | 1519 |
1433 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { | 1520 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { |
1434 Register reg = ToRegister(instr->input()); | 1521 Register reg = ToRegister(instr->input()); |
1435 Register temp = ToRegister(instr->temp()); | 1522 Register temp = ToRegister(instr->temp()); |
1436 int true_block = instr->true_block_id(); | 1523 int true_block = instr->true_block_id(); |
1437 int false_block = instr->false_block_id(); | 1524 int false_block = instr->false_block_id(); |
1438 | 1525 |
1439 __ ldr(temp, FieldMemOperand(reg, HeapObject::kMapOffset)); | 1526 __ ldr(temp, FieldMemOperand(reg, HeapObject::kMapOffset)); |
(...skipping 1206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2646 | 2733 |
2647 | 2734 |
2648 void LCodeGen::DoOsrEntry(LOsrEntry* instr) { | 2735 void LCodeGen::DoOsrEntry(LOsrEntry* instr) { |
2649 Abort("DoOsrEntry unimplemented."); | 2736 Abort("DoOsrEntry unimplemented."); |
2650 } | 2737 } |
2651 | 2738 |
2652 | 2739 |
2653 #undef __ | 2740 #undef __ |
2654 | 2741 |
2655 } } // namespace v8::internal | 2742 } } // namespace v8::internal |
OLD | NEW |