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. | |
Søren Thygesen Gjesse
2011/01/11 13:48:14
Can't we get rid of temp2 and just use the scratch
| |
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 Register temp = ToRegister(instr->temporary()); | |
1486 Handle<String> class_name = instr->hydrogen()->class_name(); | |
1487 | |
1488 Label done, is_true, is_false; | |
1489 | |
1490 EmitClassOfTest(&is_true, &is_false, class_name, input, temp, input); | |
1491 __ b(ne, &is_false); | |
1492 | |
1493 __ bind(&is_true); | |
1494 __ LoadRoot(result, Heap::kTrueValueRootIndex); | |
1495 __ jmp(&done); | |
1496 | |
1497 __ bind(&is_false); | |
1498 __ LoadRoot(result, Heap::kFalseValueRootIndex); | |
1499 __ bind(&done); | |
1425 } | 1500 } |
1426 | 1501 |
1427 | 1502 |
1428 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { | 1503 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { |
1429 Abort("DoClassOfTestAndBranch unimplemented."); | 1504 Register input = ToRegister(instr->input()); |
1505 Register temp = ToRegister(instr->temporary()); | |
Søren Thygesen Gjesse
2011/01/11 13:48:14
Probably don't need temp2 for the instruction afte
| |
1506 Register temp2 = ToRegister(instr->temporary2()); | |
1507 if (input.is(temp)) { | |
1508 // Swap. | |
1509 Register swapper = temp; | |
1510 temp = temp2; | |
1511 temp2 = swapper; | |
1512 } | |
1513 Handle<String> class_name = instr->hydrogen()->class_name(); | |
1514 | |
1515 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
1516 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
1517 | |
1518 Label* true_label = chunk_->GetAssemblyLabel(true_block); | |
1519 Label* false_label = chunk_->GetAssemblyLabel(false_block); | |
1520 | |
1521 EmitClassOfTest(true_label, false_label, class_name, input, temp, temp2); | |
1522 | |
1523 EmitBranch(true_block, false_block, eq); | |
1430 } | 1524 } |
1431 | 1525 |
1432 | 1526 |
1433 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { | 1527 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { |
1434 Register reg = ToRegister(instr->input()); | 1528 Register reg = ToRegister(instr->input()); |
1435 Register temp = ToRegister(instr->temp()); | 1529 Register temp = ToRegister(instr->temp()); |
1436 int true_block = instr->true_block_id(); | 1530 int true_block = instr->true_block_id(); |
1437 int false_block = instr->false_block_id(); | 1531 int false_block = instr->false_block_id(); |
1438 | 1532 |
1439 __ ldr(temp, FieldMemOperand(reg, HeapObject::kMapOffset)); | 1533 __ ldr(temp, FieldMemOperand(reg, HeapObject::kMapOffset)); |
(...skipping 1206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2646 | 2740 |
2647 | 2741 |
2648 void LCodeGen::DoOsrEntry(LOsrEntry* instr) { | 2742 void LCodeGen::DoOsrEntry(LOsrEntry* instr) { |
2649 Abort("DoOsrEntry unimplemented."); | 2743 Abort("DoOsrEntry unimplemented."); |
2650 } | 2744 } |
2651 | 2745 |
2652 | 2746 |
2653 #undef __ | 2747 #undef __ |
2654 | 2748 |
2655 } } // namespace v8::internal | 2749 } } // namespace v8::internal |
OLD | NEW |