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 1140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1151 mov(r0, Operand(0, RelocInfo::NONE)); | 1151 mov(r0, Operand(0, RelocInfo::NONE)); |
1152 mov(r1, Operand(ExternalReference(Runtime::kDebugBreak, isolate()))); | 1152 mov(r1, Operand(ExternalReference(Runtime::kDebugBreak, isolate()))); |
1153 CEntryStub ces(1); | 1153 CEntryStub ces(1); |
1154 ASSERT(AllowThisStubCall(&ces)); | 1154 ASSERT(AllowThisStubCall(&ces)); |
1155 Call(ces.GetCode(), RelocInfo::DEBUG_BREAK); | 1155 Call(ces.GetCode(), RelocInfo::DEBUG_BREAK); |
1156 } | 1156 } |
1157 #endif | 1157 #endif |
1158 | 1158 |
1159 | 1159 |
1160 void MacroAssembler::PushTryHandler(CodeLocation try_location, | 1160 void MacroAssembler::PushTryHandler(CodeLocation try_location, |
1161 HandlerType type) { | 1161 HandlerType type, |
1162 int handler_index) { | |
1162 // Adjust this code if not the case. | 1163 // Adjust this code if not the case. |
1163 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); | 1164 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); |
1164 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize); | 1165 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize); |
1165 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 1 * kPointerSize); | 1166 STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize); |
1166 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 2 * kPointerSize); | 1167 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize); |
1167 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 3 * kPointerSize); | 1168 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize); |
1168 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 4 * kPointerSize); | 1169 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize); |
1169 | 1170 |
1170 // The pc (return address) is passed in register lr. | 1171 // For the JSEntry handler, we must preserve r0-r4, r5-r7 are available. |
1172 // We will build up the handler from the bottom by pushing on the stack. | |
1173 // First compute the state. | |
1174 unsigned state = StackHandler::OffsetField::encode(handler_index); | |
1171 if (try_location == IN_JAVASCRIPT) { | 1175 if (try_location == IN_JAVASCRIPT) { |
1172 if (type == TRY_CATCH_HANDLER) { | 1176 state |= (type == TRY_CATCH_HANDLER) |
1173 mov(r3, Operand(StackHandler::TRY_CATCH)); | 1177 ? StackHandler::KindField::encode(StackHandler::TRY_CATCH) |
1174 } else { | 1178 : StackHandler::KindField::encode(StackHandler::TRY_FINALLY); |
1175 mov(r3, Operand(StackHandler::TRY_FINALLY)); | |
1176 } | |
1177 stm(db_w, sp, r3.bit() | cp.bit() | fp.bit() | lr.bit()); | |
1178 // Save the current handler as the next handler. | |
1179 mov(r3, Operand(ExternalReference(Isolate::kHandlerAddress, isolate()))); | |
1180 ldr(r1, MemOperand(r3)); | |
1181 push(r1); | |
1182 // Link this handler as the new current one. | |
1183 str(sp, MemOperand(r3)); | |
1184 } else { | 1179 } else { |
1185 // Must preserve r0-r4, r5-r7 are available. | |
1186 ASSERT(try_location == IN_JS_ENTRY); | 1180 ASSERT(try_location == IN_JS_ENTRY); |
1187 // The frame pointer does not point to a JS frame so we save NULL | 1181 state |= StackHandler::KindField::encode(StackHandler::ENTRY); |
1188 // for fp. We expect the code throwing an exception to check fp | |
1189 // before dereferencing it to restore the context. | |
1190 mov(r5, Operand(StackHandler::ENTRY)); // State. | |
1191 mov(r6, Operand(Smi::FromInt(0))); // Indicates no context. | |
1192 mov(r7, Operand(0, RelocInfo::NONE)); // NULL frame pointer. | |
1193 stm(db_w, sp, r5.bit() | r6.bit() | r7.bit() | lr.bit()); | |
1194 // Save the current handler as the next handler. | |
1195 mov(r7, Operand(ExternalReference(Isolate::kHandlerAddress, isolate()))); | |
1196 ldr(r6, MemOperand(r7)); | |
1197 push(r6); | |
1198 // Link this handler as the new current one. | |
1199 str(sp, MemOperand(r7)); | |
1200 } | 1182 } |
1183 | |
1184 // Set up the code object (r5) and the state (r6) for pushing. | |
1185 mov(r5, Operand(CodeObject())); | |
1186 mov(r6, Operand(state)); | |
1187 | |
1188 // Push the frame pointer, context, state, and code object. | |
1189 if (try_location == IN_JAVASCRIPT) { | |
1190 stm(db_w, sp, r5.bit() | r6.bit() | cp.bit() | fp.bit()); | |
1191 } else { | |
1192 mov(r7, Operand(Smi::FromInt(0))); // Indicates no context. | |
1193 mov(ip, Operand(0, RelocInfo::NONE)); // NULL frame pointer. | |
1194 stm(db_w, sp, r5.bit() | r6.bit() | r7.bit() | ip.bit()); | |
1195 } | |
1196 | |
1197 // Link the current handler as the next handler. | |
1198 mov(r6, Operand(ExternalReference(Isolate::kHandlerAddress, isolate()))); | |
1199 ldr(r5, MemOperand(r6)); | |
1200 push(r5); | |
1201 // Set this new handler as the current one. | |
1202 str(sp, MemOperand(r6)); | |
1201 } | 1203 } |
1202 | 1204 |
1203 | 1205 |
1204 void MacroAssembler::PopTryHandler() { | 1206 void MacroAssembler::PopTryHandler() { |
1205 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); | 1207 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); |
1206 pop(r1); | 1208 pop(r1); |
1207 mov(ip, Operand(ExternalReference(Isolate::kHandlerAddress, isolate()))); | 1209 mov(ip, Operand(ExternalReference(Isolate::kHandlerAddress, isolate()))); |
1208 add(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize)); | 1210 add(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize)); |
1209 str(r1, MemOperand(ip)); | 1211 str(r1, MemOperand(ip)); |
1210 } | 1212 } |
1211 | 1213 |
1212 | 1214 |
1213 void MacroAssembler::Throw(Register value) { | 1215 void MacroAssembler::Throw(Register value) { |
1214 // Adjust this code if not the case. | 1216 // Adjust this code if not the case. |
1215 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); | 1217 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); |
1216 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize); | 1218 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); |
1217 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 1 * kPointerSize); | 1219 STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize); |
1218 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 2 * kPointerSize); | 1220 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize); |
1219 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 3 * kPointerSize); | 1221 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize); |
1220 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 4 * kPointerSize); | 1222 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize); |
1221 // r0 is expected to hold the exception. | 1223 |
1224 // The exception is expected in r0. | |
1222 if (!value.is(r0)) { | 1225 if (!value.is(r0)) { |
1223 mov(r0, value); | 1226 mov(r0, value); |
1224 } | 1227 } |
1225 | 1228 // Drop the stack pointer to the top of the top handler. |
1226 // Drop the sp to the top of the handler. | |
1227 mov(r3, Operand(ExternalReference(Isolate::kHandlerAddress, isolate()))); | 1229 mov(r3, Operand(ExternalReference(Isolate::kHandlerAddress, isolate()))); |
1228 ldr(sp, MemOperand(r3)); | 1230 ldr(sp, MemOperand(r3)); |
1229 | |
1230 // Restore the next handler. | 1231 // Restore the next handler. |
1231 pop(r2); | 1232 pop(r2); |
1232 str(r2, MemOperand(r3)); | 1233 str(r2, MemOperand(r3)); |
1233 | 1234 |
1234 // Restore context and frame pointer, discard state (r3). | 1235 // Get the code object (r1) and state (r2). Restore the context and frame |
1235 ldm(ia_w, sp, r3.bit() | cp.bit() | fp.bit()); | 1236 // pointer. |
1237 ldm(ia_w, sp, r1.bit() | r2.bit() | cp.bit() | fp.bit()); | |
1236 | 1238 |
1237 // If the handler is a JS frame, restore the context to the frame. | 1239 // If the handler is a JS frame, restore the context to the frame. |
1238 // (r3 == ENTRY) == (fp == 0) == (cp == 0), so we could test any | 1240 // (kind == ENTRY) == (fp == 0) == (cp == 0), so we could test either fp |
1239 // of them. | 1241 // or cp. |
1240 cmp(r3, Operand(StackHandler::ENTRY)); | 1242 tst(cp, cp); |
1241 str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne); | 1243 str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne); |
1242 | 1244 |
1243 #ifdef DEBUG | 1245 // Compute the handler entry address and jump to it. The handler table is |
1244 if (emit_debug_code()) { | 1246 // a fixed array of (smi-tagged) code offsets. |
1245 mov(lr, Operand(pc)); | 1247 // r1 = code object, r2 = state. |
1246 } | 1248 ldr(r3, FieldMemOperand(r1, Code::kHandlerTableOffset)); // Handler table. |
1247 #endif | 1249 add(r3, r3, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
1248 pop(pc); | 1250 mov(r2, Operand(r2, LSR, StackHandler::kKindWidth)); // Handler index. |
1251 ldr(r2, MemOperand(r3, r2, LSL, kPointerSizeLog2)); // Smi-tagged offset. | |
1252 add(r1, r1, Operand(Code::kHeaderSize - kHeapObjectTag)); // Code start. | |
1253 add(pc, r1, Operand(r2, ASR, kSmiTagSize)); // Jump. | |
1249 } | 1254 } |
1250 | 1255 |
1251 | 1256 |
1252 void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type, | 1257 void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type, |
1253 Register value) { | 1258 Register value) { |
1254 // Adjust this code if not the case. | 1259 // Adjust this code if not the case. |
1255 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); | 1260 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); |
1256 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize); | 1261 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize); |
1257 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 1 * kPointerSize); | 1262 STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize); |
1258 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 2 * kPointerSize); | 1263 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize); |
1259 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 3 * kPointerSize); | 1264 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize); |
1260 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 4 * kPointerSize); | 1265 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize); |
1261 | 1266 |
1262 // The exception is expected in r0. | 1267 // The exception is expected in eax. |
fschneider
2011/11/11 09:43:13
Should be r0 for arm.
Kevin Millikin (Chromium)
2011/11/11 11:22:50
Thanks. Silly that it was right and I changed it
| |
1263 if (type == OUT_OF_MEMORY) { | 1268 if (type == OUT_OF_MEMORY) { |
1264 // Set external caught exception to false. | 1269 // Set external caught exception to false. |
1265 ExternalReference external_caught(Isolate::kExternalCaughtExceptionAddress, | 1270 ExternalReference external_caught(Isolate::kExternalCaughtExceptionAddress, |
1266 isolate()); | 1271 isolate()); |
1267 mov(r0, Operand(false, RelocInfo::NONE)); | 1272 mov(r0, Operand(false, RelocInfo::NONE)); |
1268 mov(r2, Operand(external_caught)); | 1273 mov(r2, Operand(external_caught)); |
1269 str(r0, MemOperand(r2)); | 1274 str(r0, MemOperand(r2)); |
1270 | 1275 |
1271 // Set pending exception and r0 to out of memory exception. | 1276 // Set pending exception and r0 to out of memory exception. |
1272 Failure* out_of_memory = Failure::OutOfMemoryException(); | 1277 Failure* out_of_memory = Failure::OutOfMemoryException(); |
1273 mov(r0, Operand(reinterpret_cast<int32_t>(out_of_memory))); | 1278 mov(r0, Operand(reinterpret_cast<int32_t>(out_of_memory))); |
1274 mov(r2, Operand(ExternalReference(Isolate::kPendingExceptionAddress, | 1279 mov(r2, Operand(ExternalReference(Isolate::kPendingExceptionAddress, |
1275 isolate()))); | 1280 isolate()))); |
1276 str(r0, MemOperand(r2)); | 1281 str(r0, MemOperand(r2)); |
1277 } else if (!value.is(r0)) { | 1282 } else if (!value.is(r0)) { |
1278 mov(r0, value); | 1283 mov(r0, value); |
1279 } | 1284 } |
1280 | 1285 |
1281 // Drop the stack pointer to the top of the top stack handler. | 1286 // Drop the stack pointer to the top of the top stack handler. |
1282 mov(r3, Operand(ExternalReference(Isolate::kHandlerAddress, isolate()))); | 1287 mov(r3, Operand(ExternalReference(Isolate::kHandlerAddress, isolate()))); |
1283 ldr(sp, MemOperand(r3)); | 1288 ldr(sp, MemOperand(r3)); |
1284 | 1289 |
1285 // Unwind the handlers until the top ENTRY handler is found. | 1290 // Unwind the handlers until the ENTRY handler is found. |
1286 Label fetch_next, check_kind; | 1291 Label fetch_next, check_kind; |
1287 jmp(&check_kind); | 1292 jmp(&check_kind); |
1288 bind(&fetch_next); | 1293 bind(&fetch_next); |
1289 ldr(sp, MemOperand(sp, StackHandlerConstants::kNextOffset)); | 1294 ldr(sp, MemOperand(sp, StackHandlerConstants::kNextOffset)); |
1290 | 1295 |
1291 bind(&check_kind); | 1296 bind(&check_kind); |
1297 STATIC_ASSERT(StackHandler::ENTRY == 0); | |
1292 ldr(r2, MemOperand(sp, StackHandlerConstants::kStateOffset)); | 1298 ldr(r2, MemOperand(sp, StackHandlerConstants::kStateOffset)); |
1293 cmp(r2, Operand(StackHandler::ENTRY)); | 1299 tst(r2, Operand(StackHandler::KindField::kMask)); |
1294 b(ne, &fetch_next); | 1300 b(ne, &fetch_next); |
1295 | 1301 |
1296 // Set the top handler address to next handler past the top ENTRY handler. | 1302 // Set the top handler address to next handler past the top ENTRY handler. |
1297 pop(r2); | 1303 pop(r2); |
1298 str(r2, MemOperand(r3)); | 1304 str(r2, MemOperand(r3)); |
1305 // Get the code object (r1) and state (r2). Clear the context and frame | |
1306 // pointer (0 was saved in the handler). | |
1307 ldm(ia_w, sp, r1.bit() | r2.bit() | cp.bit() | fp.bit()); | |
1299 | 1308 |
1300 // Clear the context and frame pointer (0 was saved in the handler), and | 1309 // Compute the handler entry address and jump to it. The handler table is |
Vyacheslav Egorov (Chromium)
2011/11/10 19:01:04
Seems this code can be shared between throw and th
Kevin Millikin (Chromium)
2011/11/11 11:22:50
Yeah, good idea. Done.
| |
1301 // discard the state (r2). | 1310 // a fixed array of (smi-tagged) code offsets. |
1302 ldm(ia_w, sp, r2.bit() | cp.bit() | fp.bit()); | 1311 // r1 = code object, r2 = state. |
1303 | 1312 ldr(r3, FieldMemOperand(r1, Code::kHandlerTableOffset)); // Handler table. |
1304 pop(pc); | 1313 add(r3, r3, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
1314 mov(r2, Operand(r2, LSR, StackHandler::kKindWidth)); // Handler index. | |
1315 ldr(r2, MemOperand(r3, r2, LSL, kPointerSizeLog2)); // Smi-tagged offset. | |
1316 add(r1, r1, Operand(Code::kHeaderSize - kHeapObjectTag)); // Code start. | |
1317 add(pc, r1, Operand(r2, ASR, kSmiTagSize)); // Jump. | |
1305 } | 1318 } |
1306 | 1319 |
1307 | 1320 |
1308 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, | 1321 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, |
1309 Register scratch, | 1322 Register scratch, |
1310 Label* miss) { | 1323 Label* miss) { |
1311 Label same_contexts; | 1324 Label same_contexts; |
1312 | 1325 |
1313 ASSERT(!holder_reg.is(scratch)); | 1326 ASSERT(!holder_reg.is(scratch)); |
1314 ASSERT(!holder_reg.is(ip)); | 1327 ASSERT(!holder_reg.is(ip)); |
(...skipping 2278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3593 void CodePatcher::EmitCondition(Condition cond) { | 3606 void CodePatcher::EmitCondition(Condition cond) { |
3594 Instr instr = Assembler::instr_at(masm_.pc_); | 3607 Instr instr = Assembler::instr_at(masm_.pc_); |
3595 instr = (instr & ~kCondMask) | cond; | 3608 instr = (instr & ~kCondMask) | cond; |
3596 masm_.emit(instr); | 3609 masm_.emit(instr); |
3597 } | 3610 } |
3598 | 3611 |
3599 | 3612 |
3600 } } // namespace v8::internal | 3613 } } // namespace v8::internal |
3601 | 3614 |
3602 #endif // V8_TARGET_ARCH_ARM | 3615 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |