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 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 |