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

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

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