Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(858)

Side by Side Diff: src/x64/lithium-codegen-x64.cc

Issue 6374002: X64 Crank: Implemented DoBranch and all *AndBranch comparisons. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge/build-x64
Patch Set: Removed unnecessary temporary. Created 9 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/x64/lithium-codegen-x64.h ('k') | src/x64/lithium-x64.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 912 matching lines...) Expand 10 before | Expand all | Expand 10 after
923 int LCodeGen::GetNextEmittedBlock(int block) { 923 int LCodeGen::GetNextEmittedBlock(int block) {
924 for (int i = block + 1; i < graph()->blocks()->length(); ++i) { 924 for (int i = block + 1; i < graph()->blocks()->length(); ++i) {
925 LLabel* label = chunk_->GetLabel(i); 925 LLabel* label = chunk_->GetLabel(i);
926 if (!label->HasReplacement()) return i; 926 if (!label->HasReplacement()) return i;
927 } 927 }
928 return -1; 928 return -1;
929 } 929 }
930 930
931 931
932 void LCodeGen::EmitBranch(int left_block, int right_block, Condition cc) { 932 void LCodeGen::EmitBranch(int left_block, int right_block, Condition cc) {
933 Abort("Unimplemented: %s", "EmitBranch"); 933 int next_block = GetNextEmittedBlock(current_block_);
934 right_block = chunk_->LookupDestination(right_block);
935 left_block = chunk_->LookupDestination(left_block);
936
937 if (right_block == left_block) {
938 EmitGoto(left_block);
939 } else if (left_block == next_block) {
940 __ j(NegateCondition(cc), chunk_->GetAssemblyLabel(right_block));
941 } else if (right_block == next_block) {
942 __ j(cc, chunk_->GetAssemblyLabel(left_block));
943 } else {
944 __ j(cc, chunk_->GetAssemblyLabel(left_block));
945 if (cc != always) {
946 __ jmp(chunk_->GetAssemblyLabel(right_block));
947 }
948 }
934 } 949 }
935 950
936 951
937 void LCodeGen::DoBranch(LBranch* instr) { 952 void LCodeGen::DoBranch(LBranch* instr) {
938 Abort("Unimplemented: %s", "DoBranch"); 953 int true_block = chunk_->LookupDestination(instr->true_block_id());
954 int false_block = chunk_->LookupDestination(instr->false_block_id());
955
956 Representation r = instr->hydrogen()->representation();
957 if (r.IsInteger32()) {
958 Register reg = ToRegister(instr->InputAt(0));
959 __ testl(reg, reg);
960 EmitBranch(true_block, false_block, not_zero);
961 } else if (r.IsDouble()) {
962 XMMRegister reg = ToDoubleRegister(instr->InputAt(0));
963 __ xorpd(xmm0, xmm0);
964 __ ucomisd(reg, xmm0);
965 EmitBranch(true_block, false_block, not_equal);
966 } else {
967 ASSERT(r.IsTagged());
968 Register reg = ToRegister(instr->InputAt(0));
969 HType type = instr->hydrogen()->type();
970 if (type.IsBoolean()) {
971 __ Cmp(reg, Factory::true_value());
972 EmitBranch(true_block, false_block, equal);
973 } else if (type.IsSmi()) {
974 __ SmiCompare(reg, Smi::FromInt(0));
975 EmitBranch(true_block, false_block, not_equal);
976 } else {
977 Label* true_label = chunk_->GetAssemblyLabel(true_block);
978 Label* false_label = chunk_->GetAssemblyLabel(false_block);
979
980 __ Cmp(reg, Factory::undefined_value());
981 __ j(equal, false_label);
982 __ Cmp(reg, Factory::true_value());
983 __ j(equal, true_label);
984 __ Cmp(reg, Factory::false_value());
985 __ j(equal, false_label);
986 __ SmiCompare(reg, Smi::FromInt(0));
987 __ j(equal, false_label);
988 __ JumpIfSmi(reg, true_label);
989
990 // Test for double values. Plus/minus zero are false. NaN is handled
991 // in the stub.
992 NearLabel call_stub;
993 __ Cmp(FieldOperand(reg, HeapObject::kMapOffset),
994 Factory::heap_number_map());
995 __ j(not_equal, &call_stub);
996 __ movq(kScratchRegister, FieldOperand(reg, HeapNumber::kValueOffset));
997 __ shl(kScratchRegister, Immediate(1)); // Shift out the sign bit.
998 __ j(zero, false_label); // Zero or negative zero.
999 __ jmp(true_label);
1000
1001 // The conversion stub doesn't cause garbage collections so it's
1002 // safe to not record a safepoint after the call.
1003 __ bind(&call_stub);
1004 ToBooleanStub stub;
1005 __ Pushad();
1006 __ push(reg);
1007 __ CallStub(&stub);
1008 __ testq(rax, rax);
1009 __ Popad();
1010 EmitBranch(true_block, false_block, not_zero);
1011 }
1012 }
939 } 1013 }
940 1014
941 1015
942 void LCodeGen::EmitGoto(int block, LDeferredCode* deferred_stack_check) { 1016 void LCodeGen::EmitGoto(int block, LDeferredCode* deferred_stack_check) {
943 block = chunk_->LookupDestination(block); 1017 block = chunk_->LookupDestination(block);
944 int next_block = GetNextEmittedBlock(current_block_); 1018 int next_block = GetNextEmittedBlock(current_block_);
945 if (block != next_block) { 1019 if (block != next_block) {
946 // Perform stack overflow check if this goto needs it before jumping. 1020 // Perform stack overflow check if this goto needs it before jumping.
947 if (deferred_stack_check != NULL) { 1021 if (deferred_stack_check != NULL) {
948 __ CompareRoot(rsp, Heap::kStackLimitRootIndex); 1022 __ CompareRoot(rsp, Heap::kStackLimitRootIndex);
(...skipping 23 matching lines...) Expand all
972 }; 1046 };
973 1047
974 DeferredStackCheck* deferred = NULL; 1048 DeferredStackCheck* deferred = NULL;
975 if (instr->include_stack_check()) { 1049 if (instr->include_stack_check()) {
976 deferred = new DeferredStackCheck(this, instr); 1050 deferred = new DeferredStackCheck(this, instr);
977 } 1051 }
978 EmitGoto(instr->block_id(), deferred); 1052 EmitGoto(instr->block_id(), deferred);
979 } 1053 }
980 1054
981 1055
982 Condition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) { 1056 inline Condition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) {
983 Condition cond = no_condition; 1057 Condition cond = no_condition;
984 switch (op) { 1058 switch (op) {
985 case Token::EQ: 1059 case Token::EQ:
986 case Token::EQ_STRICT: 1060 case Token::EQ_STRICT:
987 cond = equal; 1061 cond = equal;
988 break; 1062 break;
989 case Token::LT: 1063 case Token::LT:
990 cond = is_unsigned ? below : less; 1064 cond = is_unsigned ? below : less;
991 break; 1065 break;
992 case Token::GT: 1066 case Token::GT:
993 cond = is_unsigned ? above : greater; 1067 cond = is_unsigned ? above : greater;
994 break; 1068 break;
995 case Token::LTE: 1069 case Token::LTE:
996 cond = is_unsigned ? below_equal : less_equal; 1070 cond = is_unsigned ? below_equal : less_equal;
997 break; 1071 break;
998 case Token::GTE: 1072 case Token::GTE:
999 cond = is_unsigned ? above_equal : greater_equal; 1073 cond = is_unsigned ? above_equal : greater_equal;
1000 break; 1074 break;
1001 case Token::IN: 1075 case Token::IN:
1002 case Token::INSTANCEOF: 1076 case Token::INSTANCEOF:
1003 default: 1077 default:
1004 UNREACHABLE(); 1078 UNREACHABLE();
1005 } 1079 }
1006 return cond; 1080 return cond;
1007 } 1081 }
1008 1082
1009 1083
1010 void LCodeGen::EmitCmpI(LOperand* left, LOperand* right) { 1084 void LCodeGen::EmitCmpI(LOperand* left, LOperand* right) {
1011 Abort("Unimplemented: %s", "EmitCmpI"); 1085 if (right->IsConstantOperand()) {
1086 int32_t value = ToInteger32(LConstantOperand::cast(right));
1087 if (left->IsRegister()) {
1088 __ cmpl(ToRegister(left), Immediate(value));
1089 } else {
1090 __ cmpl(ToOperand(left), Immediate(value));
1091 }
1092 } else if (right->IsRegister()) {
1093 __ cmpq(ToRegister(left), ToRegister(right));
1094 } else {
1095 __ cmpq(ToRegister(left), ToOperand(right));
1096 }
1012 } 1097 }
1013 1098
1014 1099
1015 void LCodeGen::DoCmpID(LCmpID* instr) { 1100 void LCodeGen::DoCmpID(LCmpID* instr) {
1016 Abort("Unimplemented: %s", "DoCmpID"); 1101 LOperand* left = instr->InputAt(0);
1102 LOperand* right = instr->InputAt(1);
1103 LOperand* result = instr->result();
1104
1105 NearLabel unordered;
1106 if (instr->is_double()) {
1107 // Don't base result on EFLAGS when a NaN is involved. Instead
1108 // jump to the unordered case, which produces a false value.
1109 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right));
1110 __ j(parity_even, &unordered);
1111 } else {
1112 EmitCmpI(left, right);
1113 }
1114
1115 NearLabel done;
1116 Condition cc = TokenToCondition(instr->op(), instr->is_double());
1117 __ LoadRoot(ToRegister(result), Heap::kTrueValueRootIndex);
1118 __ j(cc, &done);
1119
1120 __ bind(&unordered);
1121 __ LoadRoot(ToRegister(result), Heap::kFalseValueRootIndex);
1122 __ bind(&done);
1017 } 1123 }
1018 1124
1019 1125
1020 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { 1126 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) {
1021 Abort("Unimplemented: %s", "DoCmpIDAndBranch"); 1127 LOperand* left = instr->InputAt(0);
1128 LOperand* right = instr->InputAt(1);
1129 int false_block = chunk_->LookupDestination(instr->false_block_id());
1130 int true_block = chunk_->LookupDestination(instr->true_block_id());
1131
1132 if (instr->is_double()) {
1133 // Don't base result on EFLAGS when a NaN is involved. Instead
1134 // jump to the false block.
1135 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right));
1136 __ j(parity_even, chunk_->GetAssemblyLabel(false_block));
1137 } else {
1138 EmitCmpI(left, right);
1139 }
1140
1141 Condition cc = TokenToCondition(instr->op(), instr->is_double());
1142 EmitBranch(true_block, false_block, cc);
1022 } 1143 }
1023 1144
1024 1145
1025 void LCodeGen::DoCmpJSObjectEq(LCmpJSObjectEq* instr) { 1146 void LCodeGen::DoCmpJSObjectEq(LCmpJSObjectEq* instr) {
1026 Abort("Unimplemented: %s", "DoCmpJSObjectEq"); 1147 Abort("Unimplemented: %s", "DoCmpJSObjectEq");
1027 } 1148 }
1028 1149
1029 1150
1030 void LCodeGen::DoCmpJSObjectEqAndBranch(LCmpJSObjectEqAndBranch* instr) { 1151 void LCodeGen::DoCmpJSObjectEqAndBranch(LCmpJSObjectEqAndBranch* instr) {
1031 Abort("Unimplemented: %s", "DoCmpJSObjectAndBranch"); 1152 Register left = ToRegister(instr->InputAt(0));
1153 Register right = ToRegister(instr->InputAt(1));
1154 int false_block = chunk_->LookupDestination(instr->false_block_id());
1155 int true_block = chunk_->LookupDestination(instr->true_block_id());
1156
1157 __ cmpq(left, right);
1158 EmitBranch(true_block, false_block, equal);
1032 } 1159 }
1033 1160
1034 1161
1035 void LCodeGen::DoIsNull(LIsNull* instr) { 1162 void LCodeGen::DoIsNull(LIsNull* instr) {
1036 Abort("Unimplemented: %s", "DoIsNull"); 1163 Abort("Unimplemented: %s", "DoIsNull");
1037 } 1164 }
1038 1165
1039 1166
1040 void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) { 1167 void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) {
1041 Abort("Unimplemented: %s", "DoIsNullAndBranch"); 1168 Register reg = ToRegister(instr->InputAt(0));
1169
1170 int false_block = chunk_->LookupDestination(instr->false_block_id());
1171
1172 if (instr->hydrogen()->representation().IsSpecialization() ||
1173 instr->hydrogen()->type().IsSmi()) {
1174 // If the expression is known to untagged or smi, then it's definitely
1175 // not null, and it can't be a an undetectable object.
1176 // Jump directly to the false block.
1177 EmitGoto(false_block);
1178 return;
1179 }
1180
1181 int true_block = chunk_->LookupDestination(instr->true_block_id());
1182
1183 __ Cmp(reg, Factory::null_value());
1184 if (instr->is_strict()) {
1185 EmitBranch(true_block, false_block, equal);
1186 } else {
1187 Label* true_label = chunk_->GetAssemblyLabel(true_block);
1188 Label* false_label = chunk_->GetAssemblyLabel(false_block);
1189 __ j(equal, true_label);
1190 __ Cmp(reg, Factory::undefined_value());
1191 __ j(equal, true_label);
1192 __ JumpIfSmi(reg, false_label);
1193 // Check for undetectable objects by looking in the bit field in
1194 // the map. The object has already been smi checked.
1195 Register scratch = ToRegister(instr->TempAt(0));
1196 __ movq(scratch, FieldOperand(reg, HeapObject::kMapOffset));
1197 __ testb(FieldOperand(scratch, Map::kBitFieldOffset),
1198 Immediate(1 << Map::kIsUndetectable));
1199 EmitBranch(true_block, false_block, not_zero);
1200 }
1042 } 1201 }
1043 1202
1044 1203
1045 Condition LCodeGen::EmitIsObject(Register input, 1204 Condition LCodeGen::EmitIsObject(Register input,
1046 Register temp1, 1205 Register temp1,
1047 Register temp2, 1206 Register temp2,
1048 Label* is_not_object, 1207 Label* is_not_object,
1049 Label* is_object) { 1208 Label* is_object) {
1050 Abort("Unimplemented: %s", "EmitIsObject"); 1209 ASSERT(!input.is(temp1));
1210 ASSERT(!input.is(temp2));
1211 ASSERT(!temp1.is(temp2));
1212
1213 __ JumpIfSmi(input, is_not_object);
1214
1215 __ Cmp(input, Factory::null_value());
1216 __ j(equal, is_object);
1217
1218 __ movq(temp1, FieldOperand(input, HeapObject::kMapOffset));
1219 // Undetectable objects behave like undefined.
1220 __ testb(FieldOperand(temp1, Map::kBitFieldOffset),
1221 Immediate(1 << Map::kIsUndetectable));
1222 __ j(not_zero, is_not_object);
1223
1224 __ movzxbl(temp2, FieldOperand(temp1, Map::kInstanceTypeOffset));
1225 __ cmpb(temp2, Immediate(FIRST_JS_OBJECT_TYPE));
1226 __ j(below, is_not_object);
1227 __ cmpb(temp2, Immediate(LAST_JS_OBJECT_TYPE));
1051 return below_equal; 1228 return below_equal;
1052 } 1229 }
1053 1230
1054 1231
1055 void LCodeGen::DoIsObject(LIsObject* instr) { 1232 void LCodeGen::DoIsObject(LIsObject* instr) {
1056 Abort("Unimplemented: %s", "DoIsObject"); 1233 Abort("Unimplemented: %s", "DoIsObject");
1057 } 1234 }
1058 1235
1059 1236
1060 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { 1237 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) {
1061 Abort("Unimplemented: %s", "DoIsObjectAndBranch"); 1238 Register reg = ToRegister(instr->InputAt(0));
1239 Register temp = ToRegister(instr->TempAt(0));
1240 Register temp2 = ToRegister(instr->TempAt(1));
1241
1242 int true_block = chunk_->LookupDestination(instr->true_block_id());
1243 int false_block = chunk_->LookupDestination(instr->false_block_id());
1244 Label* true_label = chunk_->GetAssemblyLabel(true_block);
1245 Label* false_label = chunk_->GetAssemblyLabel(false_block);
1246
1247 Condition true_cond = EmitIsObject(reg, temp, temp2, false_label, true_label);
1248
1249 EmitBranch(true_block, false_block, true_cond);
1062 } 1250 }
1063 1251
1064 1252
1065 void LCodeGen::DoIsSmi(LIsSmi* instr) { 1253 void LCodeGen::DoIsSmi(LIsSmi* instr) {
1066 Abort("Unimplemented: %s", "DoIsSmi"); 1254 Abort("Unimplemented: %s", "DoIsSmi");
1067 } 1255 }
1068 1256
1069 1257
1070 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { 1258 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) {
1071 Abort("Unimplemented: %s", "DoIsSmiAndBranch"); 1259 int true_block = chunk_->LookupDestination(instr->true_block_id());
1260 int false_block = chunk_->LookupDestination(instr->false_block_id());
1261
1262 Condition is_smi;
1263 if (instr->InputAt(0)->IsRegister()) {
1264 Register input = ToRegister(instr->InputAt(0));
1265 is_smi = masm()->CheckSmi(input);
1266 } else {
1267 Operand input = ToOperand(instr->InputAt(0));
1268 is_smi = masm()->CheckSmi(input);
1269 }
1270 EmitBranch(true_block, false_block, is_smi);
1072 } 1271 }
1073 1272
1074 1273
1274 static InstanceType TestType(HHasInstanceType* instr) {
1275 InstanceType from = instr->from();
1276 InstanceType to = instr->to();
1277 if (from == FIRST_TYPE) return to;
1278 ASSERT(from == to || to == LAST_TYPE);
1279 return from;
1280 }
1281
1282
1283 static Condition BranchCondition(HHasInstanceType* instr) {
1284 InstanceType from = instr->from();
1285 InstanceType to = instr->to();
1286 if (from == to) return equal;
1287 if (to == LAST_TYPE) return above_equal;
1288 if (from == FIRST_TYPE) return below_equal;
1289 UNREACHABLE();
1290 return equal;
1291 }
1292
1293
1075 void LCodeGen::DoHasInstanceType(LHasInstanceType* instr) { 1294 void LCodeGen::DoHasInstanceType(LHasInstanceType* instr) {
1076 Abort("Unimplemented: %s", "DoHasInstanceType"); 1295 Abort("Unimplemented: %s", "DoHasInstanceType");
1077 } 1296 }
1078 1297
1079 1298
1080 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { 1299 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) {
1081 Abort("Unimplemented: %s", "DoHasInstanceTypeAndBranch"); 1300 Register input = ToRegister(instr->InputAt(0));
1301
1302 int true_block = chunk_->LookupDestination(instr->true_block_id());
1303 int false_block = chunk_->LookupDestination(instr->false_block_id());
1304
1305 Label* false_label = chunk_->GetAssemblyLabel(false_block);
1306
1307 __ JumpIfSmi(input, false_label);
1308
1309 __ CmpObjectType(input, TestType(instr->hydrogen()), kScratchRegister);
1310 EmitBranch(true_block, false_block, BranchCondition(instr->hydrogen()));
1082 } 1311 }
1083 1312
1084 1313
1085 void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) { 1314 void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) {
1086 Abort("Unimplemented: %s", "DoHasCachedArrayIndex"); 1315 Abort("Unimplemented: %s", "DoHasCachedArrayIndex");
1087 } 1316 }
1088 1317
1089 1318
1090 void LCodeGen::DoHasCachedArrayIndexAndBranch( 1319 void LCodeGen::DoHasCachedArrayIndexAndBranch(
1091 LHasCachedArrayIndexAndBranch* instr) { 1320 LHasCachedArrayIndexAndBranch* instr) {
1092 Abort("Unimplemented: %s", "DoHasCachedArrayIndexAndBranch"); 1321 Register input = ToRegister(instr->InputAt(0));
1322
1323 int true_block = chunk_->LookupDestination(instr->true_block_id());
1324 int false_block = chunk_->LookupDestination(instr->false_block_id());
1325
1326 __ testl(FieldOperand(input, String::kHashFieldOffset),
1327 Immediate(String::kContainsCachedArrayIndexMask));
1328 EmitBranch(true_block, false_block, not_equal);
1093 } 1329 }
1094 1330
1095 1331
1096 // Branches to a label or falls through with the answer in the z flag. Trashes 1332 // Branches to a label or falls through with the answer in the z flag.
1097 // the temp registers, but not the input. Only input and temp2 may alias. 1333 // Trashes the temp register and possibly input (if it and temp are aliased).
1098 void LCodeGen::EmitClassOfTest(Label* is_true, 1334 void LCodeGen::EmitClassOfTest(Label* is_true,
1099 Label* is_false, 1335 Label* is_false,
1100 Handle<String>class_name, 1336 Handle<String> class_name,
1101 Register input, 1337 Register input,
1102 Register temp, 1338 Register temp) {
1103 Register temp2) { 1339 __ JumpIfSmi(input, is_false);
1104 Abort("Unimplemented: %s", "EmitClassOfTest"); 1340 __ CmpObjectType(input, FIRST_JS_OBJECT_TYPE, temp);
1341 __ j(below, is_false);
1342
1343 // Map is now in temp.
1344 // Functions have class 'Function'.
1345 __ CmpInstanceType(temp, JS_FUNCTION_TYPE);
1346 if (class_name->IsEqualTo(CStrVector("Function"))) {
1347 __ j(equal, is_true);
1348 } else {
1349 __ j(equal, is_false);
1350 }
1351
1352 // Check if the constructor in the map is a function.
1353 __ movq(temp, FieldOperand(temp, Map::kConstructorOffset));
1354
1355 // As long as JS_FUNCTION_TYPE is the last instance type and it is
1356 // right after LAST_JS_OBJECT_TYPE, we can avoid checking for
1357 // LAST_JS_OBJECT_TYPE.
1358 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
1359 ASSERT(JS_FUNCTION_TYPE == LAST_JS_OBJECT_TYPE + 1);
1360
1361 // Objects with a non-function constructor have class 'Object'.
1362 __ CmpObjectType(temp, JS_FUNCTION_TYPE, kScratchRegister);
1363 if (class_name->IsEqualTo(CStrVector("Object"))) {
1364 __ j(not_equal, is_true);
1365 } else {
1366 __ j(not_equal, is_false);
1367 }
1368
1369 // temp now contains the constructor function. Grab the
1370 // instance class name from there.
1371 __ movq(temp, FieldOperand(temp, JSFunction::kSharedFunctionInfoOffset));
1372 __ movq(temp, FieldOperand(temp,
1373 SharedFunctionInfo::kInstanceClassNameOffset));
1374 // The class name we are testing against is a symbol because it's a literal.
1375 // The name in the constructor is a symbol because of the way the context is
1376 // booted. This routine isn't expected to work for random API-created
1377 // classes and it doesn't have to because you can't access it with natives
1378 // syntax. Since both sides are symbols it is sufficient to use an identity
1379 // comparison.
1380 ASSERT(class_name->IsSymbol());
1381 __ Cmp(temp, class_name);
1382 // End with the answer in the z flag.
1105 } 1383 }
1106 1384
1107 1385
1108 void LCodeGen::DoClassOfTest(LClassOfTest* instr) { 1386 void LCodeGen::DoClassOfTest(LClassOfTest* instr) {
1109 Abort("Unimplemented: %s", "DoClassOfTest"); 1387 Abort("Unimplemented: %s", "DoClassOfTest");
1110 } 1388 }
1111 1389
1112 1390
1113 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { 1391 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) {
1114 Abort("Unimplemented: %s", "DoClassOfTestAndBranch"); 1392 Register input = ToRegister(instr->InputAt(0));
1393 Register temp = ToRegister(instr->TempAt(0));
1394 Handle<String> class_name = instr->hydrogen()->class_name();
1395
1396 int true_block = chunk_->LookupDestination(instr->true_block_id());
1397 int false_block = chunk_->LookupDestination(instr->false_block_id());
1398
1399 Label* true_label = chunk_->GetAssemblyLabel(true_block);
1400 Label* false_label = chunk_->GetAssemblyLabel(false_block);
1401
1402 EmitClassOfTest(true_label, false_label, class_name, input, temp);
1403
1404 EmitBranch(true_block, false_block, equal);
1115 } 1405 }
1116 1406
1117 1407
1118 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { 1408 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) {
1119 Abort("Unimplemented: %s", "DoCmpMapAndBranch"); 1409 Abort("Unimplemented: %s", "DoCmpMapAndBranch");
1120 } 1410 }
1121 1411
1122 1412
1123 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { 1413 void LCodeGen::DoInstanceOf(LInstanceOf* instr) {
1124 Abort("Unimplemented: %s", "DoInstanceOf"); 1414 Abort("Unimplemented: %s", "DoInstanceOf");
1125 } 1415 }
1126 1416
1127 1417
1128 void LCodeGen::DoInstanceOfAndBranch(LInstanceOfAndBranch* instr) { 1418 void LCodeGen::DoInstanceOfAndBranch(LInstanceOfAndBranch* instr) {
1129 Abort("Unimplemented: %s", "DoInstanceOfAndBranch"); 1419 int true_block = chunk_->LookupDestination(instr->true_block_id());
1420 int false_block = chunk_->LookupDestination(instr->false_block_id());
1421
1422 InstanceofStub stub(InstanceofStub::kArgsInRegisters);
1423 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
1424 __ testq(rax, rax);
1425 EmitBranch(true_block, false_block, zero);
1130 } 1426 }
1131 1427
1132 1428
1133 void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { 1429 void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) {
1134 Abort("Unimplemented: %s", "DoInstanceOfKnowGLobal"); 1430 Abort("Unimplemented: %s", "DoInstanceOfKnowGLobal");
1135 } 1431 }
1136 1432
1137 1433
1138 void LCodeGen::DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, 1434 void LCodeGen::DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
1139 Label* map_check) { 1435 Label* map_check) {
1140 Abort("Unimplemented: %s", "DoDeferredLInstanceOfKnownGlobakl"); 1436 Abort("Unimplemented: %s", "DoDeferredLInstanceOfKnownGlobakl");
1141 } 1437 }
1142 1438
1143 1439
1144 void LCodeGen::DoCmpT(LCmpT* instr) { 1440 void LCodeGen::DoCmpT(LCmpT* instr) {
1145 Abort("Unimplemented: %s", "DoCmpT"); 1441 Token::Value op = instr->op();
1442
1443 Handle<Code> ic = CompareIC::GetUninitialized(op);
1444 CallCode(ic, RelocInfo::CODE_TARGET, instr);
1445
1446 Condition condition = TokenToCondition(op, false);
1447 if (op == Token::GT || op == Token::LTE) {
1448 condition = ReverseCondition(condition);
1449 }
1450 NearLabel true_value, done;
1451 __ testq(rax, rax);
1452 __ j(condition, &true_value);
1453 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex);
1454 __ jmp(&done);
1455 __ bind(&true_value);
1456 __ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex);
1457 __ bind(&done);
1146 } 1458 }
1147 1459
1148 1460
1149 void LCodeGen::DoCmpTAndBranch(LCmpTAndBranch* instr) { 1461 void LCodeGen::DoCmpTAndBranch(LCmpTAndBranch* instr) {
1150 Abort("Unimplemented: %s", "DoCmpTAndBranch"); 1462 Token::Value op = instr->op();
1463 int true_block = chunk_->LookupDestination(instr->true_block_id());
1464 int false_block = chunk_->LookupDestination(instr->false_block_id());
1465
1466 Handle<Code> ic = CompareIC::GetUninitialized(op);
1467 CallCode(ic, RelocInfo::CODE_TARGET, instr);
1468
1469 // The compare stub expects compare condition and the input operands
1470 // reversed for GT and LTE.
1471 Condition condition = TokenToCondition(op, false);
1472 if (op == Token::GT || op == Token::LTE) {
1473 condition = ReverseCondition(condition);
1474 }
1475 __ testq(rax, rax);
1476 EmitBranch(true_block, false_block, condition);
1151 } 1477 }
1152 1478
1153 1479
1154 void LCodeGen::DoReturn(LReturn* instr) { 1480 void LCodeGen::DoReturn(LReturn* instr) {
1155 if (FLAG_trace) { 1481 if (FLAG_trace) {
1156 // Preserve the return value on the stack and rely on the runtime 1482 // Preserve the return value on the stack and rely on the runtime
1157 // call to return the value in the same register. 1483 // call to return the value in the same register.
1158 __ push(rax); 1484 __ push(rax);
1159 __ CallRuntime(Runtime::kTraceExit, 1); 1485 __ CallRuntime(Runtime::kTraceExit, 1);
1160 } 1486 }
(...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after
1487 Abort("Unimplemented: %s", "DoTypeof"); 1813 Abort("Unimplemented: %s", "DoTypeof");
1488 } 1814 }
1489 1815
1490 1816
1491 void LCodeGen::DoTypeofIs(LTypeofIs* instr) { 1817 void LCodeGen::DoTypeofIs(LTypeofIs* instr) {
1492 Abort("Unimplemented: %s", "DoTypeofIs"); 1818 Abort("Unimplemented: %s", "DoTypeofIs");
1493 } 1819 }
1494 1820
1495 1821
1496 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { 1822 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) {
1497 Abort("Unimplemented: %s", "DoTypeofIsAndBranch"); 1823 Register input = ToRegister(instr->InputAt(0));
1824 int true_block = chunk_->LookupDestination(instr->true_block_id());
1825 int false_block = chunk_->LookupDestination(instr->false_block_id());
1826 Label* true_label = chunk_->GetAssemblyLabel(true_block);
1827 Label* false_label = chunk_->GetAssemblyLabel(false_block);
1828
1829 Condition final_branch_condition = EmitTypeofIs(true_label,
1830 false_label,
1831 input,
1832 instr->type_literal());
1833
1834 EmitBranch(true_block, false_block, final_branch_condition);
1498 } 1835 }
1499 1836
1500 1837
1501 Condition LCodeGen::EmitTypeofIs(Label* true_label, 1838 Condition LCodeGen::EmitTypeofIs(Label* true_label,
1502 Label* false_label, 1839 Label* false_label,
1503 Register input, 1840 Register input,
1504 Handle<String> type_name) { 1841 Handle<String> type_name) {
1505 Abort("Unimplemented: %s", "EmitTypeofIs"); 1842 Condition final_branch_condition = no_condition;
1506 return no_condition; 1843 if (type_name->Equals(Heap::number_symbol())) {
1844 __ JumpIfSmi(input, true_label);
1845 __ Cmp(FieldOperand(input, HeapObject::kMapOffset),
1846 Factory::heap_number_map());
1847 final_branch_condition = equal;
1848
1849 } else if (type_name->Equals(Heap::string_symbol())) {
1850 __ JumpIfSmi(input, false_label);
1851 __ movq(input, FieldOperand(input, HeapObject::kMapOffset));
1852 __ testb(FieldOperand(input, Map::kBitFieldOffset),
1853 Immediate(1 << Map::kIsUndetectable));
1854 __ j(not_zero, false_label);
1855 __ CmpInstanceType(input, FIRST_NONSTRING_TYPE);
1856 final_branch_condition = below;
1857
1858 } else if (type_name->Equals(Heap::boolean_symbol())) {
1859 __ CompareRoot(input, Heap::kTrueValueRootIndex);
1860 __ j(equal, true_label);
1861 __ CompareRoot(input, Heap::kFalseValueRootIndex);
1862 final_branch_condition = equal;
1863
1864 } else if (type_name->Equals(Heap::undefined_symbol())) {
1865 __ CompareRoot(input, Heap::kUndefinedValueRootIndex);
1866 __ j(equal, true_label);
1867 __ JumpIfSmi(input, false_label);
1868 // Check for undetectable objects => true.
1869 __ movq(input, FieldOperand(input, HeapObject::kMapOffset));
1870 __ testb(FieldOperand(input, Map::kBitFieldOffset),
1871 Immediate(1 << Map::kIsUndetectable));
1872 final_branch_condition = not_zero;
1873
1874 } else if (type_name->Equals(Heap::function_symbol())) {
1875 __ JumpIfSmi(input, false_label);
1876 __ CmpObjectType(input, FIRST_FUNCTION_CLASS_TYPE, input);
1877 final_branch_condition = above_equal;
1878
1879 } else if (type_name->Equals(Heap::object_symbol())) {
1880 __ JumpIfSmi(input, false_label);
1881 __ Cmp(input, Factory::null_value());
1882 __ j(equal, true_label);
1883 // Check for undetectable objects => false.
1884 __ testb(FieldOperand(input, Map::kBitFieldOffset),
1885 Immediate(1 << Map::kIsUndetectable));
1886 __ j(not_zero, false_label);
1887 // Check for JS objects that are not RegExp or Function => true.
1888 __ CmpInstanceType(input, FIRST_JS_OBJECT_TYPE);
1889 __ j(below, false_label);
1890 __ CmpInstanceType(input, FIRST_FUNCTION_CLASS_TYPE);
1891 final_branch_condition = below_equal;
1892
1893 } else {
1894 final_branch_condition = never;
1895 __ jmp(false_label);
1896 }
1897
1898 return final_branch_condition;
1507 } 1899 }
1508 1900
1509 1901
1510 void LCodeGen::DoLazyBailout(LLazyBailout* instr) { 1902 void LCodeGen::DoLazyBailout(LLazyBailout* instr) {
1511 // No code for lazy bailout instruction. Used to capture environment after a 1903 // No code for lazy bailout instruction. Used to capture environment after a
1512 // call for populating the safepoint data with deoptimization data. 1904 // call for populating the safepoint data with deoptimization data.
1513 } 1905 }
1514 1906
1515 1907
1516 void LCodeGen::DoDeoptimize(LDeoptimize* instr) { 1908 void LCodeGen::DoDeoptimize(LDeoptimize* instr) {
(...skipping 21 matching lines...) Expand all
1538 1930
1539 void LCodeGen::DoOsrEntry(LOsrEntry* instr) { 1931 void LCodeGen::DoOsrEntry(LOsrEntry* instr) {
1540 Abort("Unimplemented: %s", "DoOsrEntry"); 1932 Abort("Unimplemented: %s", "DoOsrEntry");
1541 } 1933 }
1542 1934
1543 #undef __ 1935 #undef __
1544 1936
1545 } } // namespace v8::internal 1937 } } // namespace v8::internal
1546 1938
1547 #endif // V8_TARGET_ARCH_X64 1939 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/lithium-codegen-x64.h ('k') | src/x64/lithium-x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698