| OLD | NEW |
| 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 1130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1141 mov(r1, Operand(ExternalReference(Runtime::kDebugBreak, isolate()))); | 1141 mov(r1, Operand(ExternalReference(Runtime::kDebugBreak, isolate()))); |
| 1142 CEntryStub ces(1); | 1142 CEntryStub ces(1); |
| 1143 Call(ces.GetCode(), RelocInfo::DEBUG_BREAK); | 1143 Call(ces.GetCode(), RelocInfo::DEBUG_BREAK); |
| 1144 } | 1144 } |
| 1145 #endif | 1145 #endif |
| 1146 | 1146 |
| 1147 | 1147 |
| 1148 void MacroAssembler::PushTryHandler(CodeLocation try_location, | 1148 void MacroAssembler::PushTryHandler(CodeLocation try_location, |
| 1149 HandlerType type) { | 1149 HandlerType type) { |
| 1150 // Adjust this code if not the case. | 1150 // Adjust this code if not the case. |
| 1151 ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize); | 1151 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); |
| 1152 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize); |
| 1153 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 1 * kPointerSize); |
| 1154 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 2 * kPointerSize); |
| 1155 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 3 * kPointerSize); |
| 1156 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 4 * kPointerSize); |
| 1157 |
| 1152 // The pc (return address) is passed in register lr. | 1158 // The pc (return address) is passed in register lr. |
| 1153 if (try_location == IN_JAVASCRIPT) { | 1159 if (try_location == IN_JAVASCRIPT) { |
| 1154 if (type == TRY_CATCH_HANDLER) { | 1160 if (type == TRY_CATCH_HANDLER) { |
| 1155 mov(r3, Operand(StackHandler::TRY_CATCH)); | 1161 mov(r3, Operand(StackHandler::TRY_CATCH)); |
| 1156 } else { | 1162 } else { |
| 1157 mov(r3, Operand(StackHandler::TRY_FINALLY)); | 1163 mov(r3, Operand(StackHandler::TRY_FINALLY)); |
| 1158 } | 1164 } |
| 1159 ASSERT(StackHandlerConstants::kStateOffset == 1 * kPointerSize | 1165 stm(db_w, sp, r3.bit() | cp.bit() | fp.bit() | lr.bit()); |
| 1160 && StackHandlerConstants::kFPOffset == 2 * kPointerSize | |
| 1161 && StackHandlerConstants::kPCOffset == 3 * kPointerSize); | |
| 1162 stm(db_w, sp, r3.bit() | fp.bit() | lr.bit()); | |
| 1163 // Save the current handler as the next handler. | 1166 // Save the current handler as the next handler. |
| 1164 mov(r3, Operand(ExternalReference(Isolate::k_handler_address, isolate()))); | 1167 mov(r3, Operand(ExternalReference(Isolate::k_handler_address, isolate()))); |
| 1165 ldr(r1, MemOperand(r3)); | 1168 ldr(r1, MemOperand(r3)); |
| 1166 ASSERT(StackHandlerConstants::kNextOffset == 0); | |
| 1167 push(r1); | 1169 push(r1); |
| 1168 // Link this handler as the new current one. | 1170 // Link this handler as the new current one. |
| 1169 str(sp, MemOperand(r3)); | 1171 str(sp, MemOperand(r3)); |
| 1170 } else { | 1172 } else { |
| 1171 // Must preserve r0-r4, r5-r7 are available. | 1173 // Must preserve r0-r4, r5-r7 are available. |
| 1172 ASSERT(try_location == IN_JS_ENTRY); | 1174 ASSERT(try_location == IN_JS_ENTRY); |
| 1173 // The frame pointer does not point to a JS frame so we save NULL | 1175 // The frame pointer does not point to a JS frame so we save NULL |
| 1174 // for fp. We expect the code throwing an exception to check fp | 1176 // for fp. We expect the code throwing an exception to check fp |
| 1175 // before dereferencing it to restore the context. | 1177 // before dereferencing it to restore the context. |
| 1176 mov(ip, Operand(0, RelocInfo::NONE)); // To save a NULL frame pointer. | 1178 mov(r5, Operand(StackHandler::ENTRY)); // State. |
| 1177 mov(r6, Operand(StackHandler::ENTRY)); | 1179 mov(r6, Operand(Smi::FromInt(0))); // Indicates no context. |
| 1178 ASSERT(StackHandlerConstants::kStateOffset == 1 * kPointerSize | 1180 mov(r7, Operand(0, RelocInfo::NONE)); // NULL frame pointer. |
| 1179 && StackHandlerConstants::kFPOffset == 2 * kPointerSize | 1181 stm(db_w, sp, r5.bit() | r6.bit() | r7.bit() | lr.bit()); |
| 1180 && StackHandlerConstants::kPCOffset == 3 * kPointerSize); | |
| 1181 stm(db_w, sp, r6.bit() | ip.bit() | lr.bit()); | |
| 1182 // Save the current handler as the next handler. | 1182 // Save the current handler as the next handler. |
| 1183 mov(r7, Operand(ExternalReference(Isolate::k_handler_address, isolate()))); | 1183 mov(r7, Operand(ExternalReference(Isolate::k_handler_address, isolate()))); |
| 1184 ldr(r6, MemOperand(r7)); | 1184 ldr(r6, MemOperand(r7)); |
| 1185 ASSERT(StackHandlerConstants::kNextOffset == 0); | |
| 1186 push(r6); | 1185 push(r6); |
| 1187 // Link this handler as the new current one. | 1186 // Link this handler as the new current one. |
| 1188 str(sp, MemOperand(r7)); | 1187 str(sp, MemOperand(r7)); |
| 1189 } | 1188 } |
| 1190 } | 1189 } |
| 1191 | 1190 |
| 1192 | 1191 |
| 1193 void MacroAssembler::PopTryHandler() { | 1192 void MacroAssembler::PopTryHandler() { |
| 1194 ASSERT_EQ(0, StackHandlerConstants::kNextOffset); | 1193 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); |
| 1195 pop(r1); | 1194 pop(r1); |
| 1196 mov(ip, Operand(ExternalReference(Isolate::k_handler_address, isolate()))); | 1195 mov(ip, Operand(ExternalReference(Isolate::k_handler_address, isolate()))); |
| 1197 add(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize)); | 1196 add(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize)); |
| 1198 str(r1, MemOperand(ip)); | 1197 str(r1, MemOperand(ip)); |
| 1199 } | 1198 } |
| 1200 | 1199 |
| 1201 | 1200 |
| 1202 void MacroAssembler::Throw(Register value) { | 1201 void MacroAssembler::Throw(Register value) { |
| 1202 // Adjust this code if not the case. |
| 1203 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); |
| 1204 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize); |
| 1205 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 1 * kPointerSize); |
| 1206 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 2 * kPointerSize); |
| 1207 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 3 * kPointerSize); |
| 1208 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 4 * kPointerSize); |
| 1203 // r0 is expected to hold the exception. | 1209 // r0 is expected to hold the exception. |
| 1204 if (!value.is(r0)) { | 1210 if (!value.is(r0)) { |
| 1205 mov(r0, value); | 1211 mov(r0, value); |
| 1206 } | 1212 } |
| 1207 | 1213 |
| 1208 // Adjust this code if not the case. | |
| 1209 STATIC_ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize); | |
| 1210 | |
| 1211 // Drop the sp to the top of the handler. | 1214 // Drop the sp to the top of the handler. |
| 1212 mov(r3, Operand(ExternalReference(Isolate::k_handler_address, isolate()))); | 1215 mov(r3, Operand(ExternalReference(Isolate::k_handler_address, isolate()))); |
| 1213 ldr(sp, MemOperand(r3)); | 1216 ldr(sp, MemOperand(r3)); |
| 1214 | 1217 |
| 1215 // Restore the next handler and frame pointer, discard handler state. | 1218 // Restore the next handler. |
| 1216 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); | |
| 1217 pop(r2); | 1219 pop(r2); |
| 1218 str(r2, MemOperand(r3)); | 1220 str(r2, MemOperand(r3)); |
| 1219 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize); | |
| 1220 ldm(ia_w, sp, r3.bit() | fp.bit()); // r3: discarded state. | |
| 1221 | 1221 |
| 1222 // Before returning we restore the context from the frame pointer if | 1222 // Restore context and frame pointer, discard state (r3). |
| 1223 // not NULL. The frame pointer is NULL in the exception handler of a | 1223 ldm(ia_w, sp, r3.bit() | cp.bit() | fp.bit()); |
| 1224 // JS entry frame. | 1224 |
| 1225 cmp(fp, Operand(0, RelocInfo::NONE)); | 1225 // If the handler is a JS frame, restore the context to the frame. |
| 1226 // Set cp to NULL if fp is NULL. | 1226 // (r3 == ENTRY) == (fp == 0) == (cp == 0), so we could test any |
| 1227 mov(cp, Operand(0, RelocInfo::NONE), LeaveCC, eq); | 1227 // of them. |
| 1228 // Restore cp otherwise. | 1228 cmp(r3, Operand(StackHandler::ENTRY)); |
| 1229 ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne); | 1229 str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne); |
| 1230 |
| 1230 #ifdef DEBUG | 1231 #ifdef DEBUG |
| 1231 if (emit_debug_code()) { | 1232 if (emit_debug_code()) { |
| 1232 mov(lr, Operand(pc)); | 1233 mov(lr, Operand(pc)); |
| 1233 } | 1234 } |
| 1234 #endif | 1235 #endif |
| 1235 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize); | |
| 1236 pop(pc); | 1236 pop(pc); |
| 1237 } | 1237 } |
| 1238 | 1238 |
| 1239 | 1239 |
| 1240 void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type, | 1240 void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type, |
| 1241 Register value) { | 1241 Register value) { |
| 1242 // Adjust this code if not the case. | 1242 // Adjust this code if not the case. |
| 1243 STATIC_ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize); | 1243 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); |
| 1244 | 1244 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize); |
| 1245 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 1 * kPointerSize); |
| 1246 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 2 * kPointerSize); |
| 1247 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 3 * kPointerSize); |
| 1248 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 4 * kPointerSize); |
| 1245 // r0 is expected to hold the exception. | 1249 // r0 is expected to hold the exception. |
| 1246 if (!value.is(r0)) { | 1250 if (!value.is(r0)) { |
| 1247 mov(r0, value); | 1251 mov(r0, value); |
| 1248 } | 1252 } |
| 1249 | 1253 |
| 1250 // Drop sp to the top stack handler. | 1254 // Drop sp to the top stack handler. |
| 1251 mov(r3, Operand(ExternalReference(Isolate::k_handler_address, isolate()))); | 1255 mov(r3, Operand(ExternalReference(Isolate::k_handler_address, isolate()))); |
| 1252 ldr(sp, MemOperand(r3)); | 1256 ldr(sp, MemOperand(r3)); |
| 1253 | 1257 |
| 1254 // Unwind the handlers until the ENTRY handler is found. | 1258 // Unwind the handlers until the ENTRY handler is found. |
| 1255 Label loop, done; | 1259 Label loop, done; |
| 1256 bind(&loop); | 1260 bind(&loop); |
| 1257 // Load the type of the current stack handler. | 1261 // Load the type of the current stack handler. |
| 1258 const int kStateOffset = StackHandlerConstants::kStateOffset; | 1262 const int kStateOffset = StackHandlerConstants::kStateOffset; |
| 1259 ldr(r2, MemOperand(sp, kStateOffset)); | 1263 ldr(r2, MemOperand(sp, kStateOffset)); |
| 1260 cmp(r2, Operand(StackHandler::ENTRY)); | 1264 cmp(r2, Operand(StackHandler::ENTRY)); |
| 1261 b(eq, &done); | 1265 b(eq, &done); |
| 1262 // Fetch the next handler in the list. | 1266 // Fetch the next handler in the list. |
| 1263 const int kNextOffset = StackHandlerConstants::kNextOffset; | 1267 const int kNextOffset = StackHandlerConstants::kNextOffset; |
| 1264 ldr(sp, MemOperand(sp, kNextOffset)); | 1268 ldr(sp, MemOperand(sp, kNextOffset)); |
| 1265 jmp(&loop); | 1269 jmp(&loop); |
| 1266 bind(&done); | 1270 bind(&done); |
| 1267 | 1271 |
| 1268 // Set the top handler address to next handler past the current ENTRY handler. | 1272 // Set the top handler address to next handler past the current ENTRY handler. |
| 1269 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); | |
| 1270 pop(r2); | 1273 pop(r2); |
| 1271 str(r2, MemOperand(r3)); | 1274 str(r2, MemOperand(r3)); |
| 1272 | 1275 |
| 1273 if (type == OUT_OF_MEMORY) { | 1276 if (type == OUT_OF_MEMORY) { |
| 1274 // Set external caught exception to false. | 1277 // Set external caught exception to false. |
| 1275 ExternalReference external_caught( | 1278 ExternalReference external_caught( |
| 1276 Isolate::k_external_caught_exception_address, isolate()); | 1279 Isolate::k_external_caught_exception_address, isolate()); |
| 1277 mov(r0, Operand(false, RelocInfo::NONE)); | 1280 mov(r0, Operand(false, RelocInfo::NONE)); |
| 1278 mov(r2, Operand(external_caught)); | 1281 mov(r2, Operand(external_caught)); |
| 1279 str(r0, MemOperand(r2)); | 1282 str(r0, MemOperand(r2)); |
| 1280 | 1283 |
| 1281 // Set pending exception and r0 to out of memory exception. | 1284 // Set pending exception and r0 to out of memory exception. |
| 1282 Failure* out_of_memory = Failure::OutOfMemoryException(); | 1285 Failure* out_of_memory = Failure::OutOfMemoryException(); |
| 1283 mov(r0, Operand(reinterpret_cast<int32_t>(out_of_memory))); | 1286 mov(r0, Operand(reinterpret_cast<int32_t>(out_of_memory))); |
| 1284 mov(r2, Operand(ExternalReference(Isolate::k_pending_exception_address, | 1287 mov(r2, Operand(ExternalReference(Isolate::k_pending_exception_address, |
| 1285 isolate()))); | 1288 isolate()))); |
| 1286 str(r0, MemOperand(r2)); | 1289 str(r0, MemOperand(r2)); |
| 1287 } | 1290 } |
| 1288 | 1291 |
| 1289 // Stack layout at this point. See also StackHandlerConstants. | 1292 // Stack layout at this point. See also StackHandlerConstants. |
| 1290 // sp -> state (ENTRY) | 1293 // sp -> state (ENTRY) |
| 1294 // cp |
| 1291 // fp | 1295 // fp |
| 1292 // lr | 1296 // lr |
| 1293 | 1297 |
| 1294 // Discard handler state (r2 is not used) and restore frame pointer. | 1298 // Restore context and frame pointer, discard state (r2). |
| 1295 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize); | 1299 ldm(ia_w, sp, r2.bit() | cp.bit() | fp.bit()); |
| 1296 ldm(ia_w, sp, r2.bit() | fp.bit()); // r2: discarded state. | |
| 1297 // Before returning we restore the context from the frame pointer if | |
| 1298 // not NULL. The frame pointer is NULL in the exception handler of a | |
| 1299 // JS entry frame. | |
| 1300 cmp(fp, Operand(0, RelocInfo::NONE)); | |
| 1301 // Set cp to NULL if fp is NULL. | |
| 1302 mov(cp, Operand(0, RelocInfo::NONE), LeaveCC, eq); | |
| 1303 // Restore cp otherwise. | |
| 1304 ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne); | |
| 1305 #ifdef DEBUG | 1300 #ifdef DEBUG |
| 1306 if (emit_debug_code()) { | 1301 if (emit_debug_code()) { |
| 1307 mov(lr, Operand(pc)); | 1302 mov(lr, Operand(pc)); |
| 1308 } | 1303 } |
| 1309 #endif | 1304 #endif |
| 1310 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize); | |
| 1311 pop(pc); | 1305 pop(pc); |
| 1312 } | 1306 } |
| 1313 | 1307 |
| 1314 | 1308 |
| 1315 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, | 1309 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, |
| 1316 Register scratch, | 1310 Register scratch, |
| 1317 Label* miss) { | 1311 Label* miss) { |
| 1318 Label same_contexts; | 1312 Label same_contexts; |
| 1319 | 1313 |
| 1320 ASSERT(!holder_reg.is(scratch)); | 1314 ASSERT(!holder_reg.is(scratch)); |
| (...skipping 2150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3471 void CodePatcher::EmitCondition(Condition cond) { | 3465 void CodePatcher::EmitCondition(Condition cond) { |
| 3472 Instr instr = Assembler::instr_at(masm_.pc_); | 3466 Instr instr = Assembler::instr_at(masm_.pc_); |
| 3473 instr = (instr & ~kCondMask) | cond; | 3467 instr = (instr & ~kCondMask) | cond; |
| 3474 masm_.emit(instr); | 3468 masm_.emit(instr); |
| 3475 } | 3469 } |
| 3476 | 3470 |
| 3477 | 3471 |
| 3478 } } // namespace v8::internal | 3472 } } // namespace v8::internal |
| 3479 | 3473 |
| 3480 #endif // V8_TARGET_ARCH_ARM | 3474 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |