Chromium Code Reviews| 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 |