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

Side by Side Diff: src/mips/macro-assembler-mips.cc

Issue 7648026: MIPS: port Simplify handling of exits from with and catch. (Closed)
Patch Set: Created 9 years, 4 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
« no previous file with comments | « src/mips/frames-mips.h ('k') | no next file » | 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 2226 matching lines...) Expand 10 before | Expand all | Expand 10 after
2237 2237
2238 #endif // ENABLE_DEBUGGER_SUPPORT 2238 #endif // ENABLE_DEBUGGER_SUPPORT
2239 2239
2240 2240
2241 // --------------------------------------------------------------------------- 2241 // ---------------------------------------------------------------------------
2242 // Exception handling. 2242 // Exception handling.
2243 2243
2244 void MacroAssembler::PushTryHandler(CodeLocation try_location, 2244 void MacroAssembler::PushTryHandler(CodeLocation try_location,
2245 HandlerType type) { 2245 HandlerType type) {
2246 // Adjust this code if not the case. 2246 // Adjust this code if not the case.
2247 ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize); 2247 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
2248 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize);
2249 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 1 * kPointerSize);
2250 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 2 * kPointerSize);
2251 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 3 * kPointerSize);
2252 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 4 * kPointerSize);
2253
2248 // The return address is passed in register ra. 2254 // The return address is passed in register ra.
2249 if (try_location == IN_JAVASCRIPT) { 2255 if (try_location == IN_JAVASCRIPT) {
2250 if (type == TRY_CATCH_HANDLER) { 2256 if (type == TRY_CATCH_HANDLER) {
2251 li(t0, Operand(StackHandler::TRY_CATCH)); 2257 li(t0, Operand(StackHandler::TRY_CATCH));
2252 } else { 2258 } else {
2253 li(t0, Operand(StackHandler::TRY_FINALLY)); 2259 li(t0, Operand(StackHandler::TRY_FINALLY));
2254 } 2260 }
2255 ASSERT(StackHandlerConstants::kStateOffset == 1 * kPointerSize
2256 && StackHandlerConstants::kFPOffset == 2 * kPointerSize
2257 && StackHandlerConstants::kPCOffset == 3 * kPointerSize
2258 && StackHandlerConstants::kNextOffset == 0 * kPointerSize);
2259 // Save the current handler as the next handler. 2261 // Save the current handler as the next handler.
2260 li(t2, Operand(ExternalReference(Isolate::k_handler_address, isolate()))); 2262 li(t2, Operand(ExternalReference(Isolate::k_handler_address, isolate())));
2261 lw(t1, MemOperand(t2)); 2263 lw(t1, MemOperand(t2));
2262 2264
2263 addiu(sp, sp, -StackHandlerConstants::kSize); 2265 addiu(sp, sp, -StackHandlerConstants::kSize);
2264 sw(ra, MemOperand(sp, 12)); 2266 sw(ra, MemOperand(sp, StackHandlerConstants::kPCOffset));
2265 sw(fp, MemOperand(sp, 8)); 2267 sw(fp, MemOperand(sp, StackHandlerConstants::kFPOffset));
2266 sw(t0, MemOperand(sp, 4)); 2268 sw(cp, MemOperand(sp, StackHandlerConstants::kContextOffset));
2267 sw(t1, MemOperand(sp, 0)); 2269 sw(t0, MemOperand(sp, StackHandlerConstants::kStateOffset));
2270 sw(t1, MemOperand(sp, StackHandlerConstants::kNextOffset));
2268 2271
2269 // Link this handler as the new current one. 2272 // Link this handler as the new current one.
2270 sw(sp, MemOperand(t2)); 2273 sw(sp, MemOperand(t2));
2271 2274
2272 } else { 2275 } else {
2273 // Must preserve a0-a3, and s0 (argv). 2276 // Must preserve a0-a3, and s0 (argv).
2274 ASSERT(try_location == IN_JS_ENTRY); 2277 ASSERT(try_location == IN_JS_ENTRY);
2275 ASSERT(StackHandlerConstants::kStateOffset == 1 * kPointerSize
2276 && StackHandlerConstants::kFPOffset == 2 * kPointerSize
2277 && StackHandlerConstants::kPCOffset == 3 * kPointerSize
2278 && StackHandlerConstants::kNextOffset == 0 * kPointerSize);
2279
2280 // The frame pointer does not point to a JS frame so we save NULL 2278 // The frame pointer does not point to a JS frame so we save NULL
2281 // for fp. We expect the code throwing an exception to check fp 2279 // for fp. We expect the code throwing an exception to check fp
2282 // before dereferencing it to restore the context. 2280 // before dereferencing it to restore the context.
2283 li(t0, Operand(StackHandler::ENTRY)); 2281 li(t0, Operand(StackHandler::ENTRY));
Kevin Millikin (Chromium) 2011/08/16 08:42:14 StackHandler::ENTRY is zero. If you wanted to rel
2284 2282
2285 // Save the current handler as the next handler. 2283 // Save the current handler as the next handler.
2286 li(t2, Operand(ExternalReference(Isolate::k_handler_address, isolate()))); 2284 li(t2, Operand(ExternalReference(Isolate::k_handler_address, isolate())));
2287 lw(t1, MemOperand(t2)); 2285 lw(t1, MemOperand(t2));
2288 2286
2287 ASSERT(Smi::FromInt(0) == 0); // Used for no context.
2288
2289 addiu(sp, sp, -StackHandlerConstants::kSize); 2289 addiu(sp, sp, -StackHandlerConstants::kSize);
2290 sw(ra, MemOperand(sp, 12)); 2290 sw(ra, MemOperand(sp, StackHandlerConstants::kPCOffset));
2291 sw(zero_reg, MemOperand(sp, 8)); 2291 sw(zero_reg, MemOperand(sp, StackHandlerConstants::kFPOffset));
2292 sw(t0, MemOperand(sp, 4)); 2292 sw(zero_reg, MemOperand(sp, StackHandlerConstants::kContextOffset));
2293 sw(t1, MemOperand(sp, 0)); 2293 sw(t0, MemOperand(sp, StackHandlerConstants::kStateOffset));
2294 sw(t1, MemOperand(sp, StackHandlerConstants::kNextOffset));
2294 2295
2295 // Link this handler as the new current one. 2296 // Link this handler as the new current one.
2296 sw(sp, MemOperand(t2)); 2297 sw(sp, MemOperand(t2));
2297 } 2298 }
2298 } 2299 }
2299 2300
2300 2301
2301 void MacroAssembler::PopTryHandler() { 2302 void MacroAssembler::PopTryHandler() {
2302 ASSERT_EQ(0, StackHandlerConstants::kNextOffset); 2303 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
2303 pop(a1); 2304 pop(a1);
2304 Addu(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize)); 2305 Addu(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize));
2305 li(at, Operand(ExternalReference(Isolate::k_handler_address, isolate()))); 2306 li(at, Operand(ExternalReference(Isolate::k_handler_address, isolate())));
2306 sw(a1, MemOperand(at)); 2307 sw(a1, MemOperand(at));
2307 } 2308 }
2308 2309
2309 2310
2310 void MacroAssembler::Throw(Register value) { 2311 void MacroAssembler::Throw(Register value) {
2311 // v0 is expected to hold the exception. 2312 // v0 is expected to hold the exception.
2312 Move(v0, value); 2313 Move(v0, value);
2313 2314
2314 // Adjust this code if not the case. 2315 // Adjust this code if not the case.
2315 STATIC_ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize); 2316 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
2317 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize);
2318 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 1 * kPointerSize);
2319 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 2 * kPointerSize);
2320 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 3 * kPointerSize);
2321 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 4 * kPointerSize);
2316 2322
2317 // Drop the sp to the top of the handler. 2323 // Drop the sp to the top of the handler.
2318 li(a3, Operand(ExternalReference(Isolate::k_handler_address, 2324 li(a3, Operand(ExternalReference(Isolate::k_handler_address,
2319 isolate()))); 2325 isolate())));
2320 lw(sp, MemOperand(a3)); 2326 lw(sp, MemOperand(a3));
2321 2327
2322 // Restore the next handler and frame pointer, discard handler state. 2328 // Restore the next handler.
2323 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
2324 pop(a2); 2329 pop(a2);
2325 sw(a2, MemOperand(a3)); 2330 sw(a2, MemOperand(a3));
2326 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize);
2327 MultiPop(a3.bit() | fp.bit());
2328 2331
2329 // Before returning we restore the context from the frame pointer if 2332 // Restore context and frame pointer, discard state (a3).
2330 // not NULL. The frame pointer is NULL in the exception handler of a 2333 MultiPop(a3.bit() | cp.bit() | fp.bit());
2331 // JS entry frame. 2334
2332 // Set cp to NULL if fp is NULL. 2335 // If the handler is a JS frame, restore the context to the frame.
2336 // (a3 == ENTRY) == (fp == 0) == (cp == 0), so we could test any
2337 // of them.
2333 Label done; 2338 Label done;
2334 Branch(USE_DELAY_SLOT, &done, eq, fp, Operand(zero_reg)); 2339 Branch(&done, eq, fp, Operand(zero_reg));
2335 mov(cp, zero_reg); // In branch delay slot. 2340 sw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
2336 lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
2337 bind(&done); 2341 bind(&done);
2338 2342
2339 #ifdef DEBUG 2343 #ifdef DEBUG
2340 // When emitting debug_code, set ra as return address for the jump. 2344 // When emitting debug_code, set ra as return address for the jump.
2341 // 5 instructions: add: 1, pop: 2, jump: 2. 2345 // 5 instructions: add: 1, pop: 2, jump: 2.
2342 const int kOffsetRaInstructions = 5; 2346 const int kOffsetRaInstructions = 5;
2343 Label find_ra; 2347 Label find_ra;
2344 2348
2345 if (emit_debug_code()) { 2349 if (emit_debug_code()) {
2346 // Compute ra for the Jump(t9). 2350 // Compute ra for the Jump(t9).
2347 const int kOffsetRaBytes = kOffsetRaInstructions * Assembler::kInstrSize; 2351 const int kOffsetRaBytes = kOffsetRaInstructions * Assembler::kInstrSize;
2348 2352
2349 // This branch-and-link sequence is needed to get the current PC on mips, 2353 // This branch-and-link sequence is needed to get the current PC on mips,
2350 // saved to the ra register. Then adjusted for instruction count. 2354 // saved to the ra register. Then adjusted for instruction count.
2351 bal(&find_ra); // bal exposes branch-delay. 2355 bal(&find_ra); // bal exposes branch-delay.
2352 nop(); // Branch delay slot nop. 2356 nop(); // Branch delay slot nop.
2353 bind(&find_ra); 2357 bind(&find_ra);
2354 addiu(ra, ra, kOffsetRaBytes); 2358 addiu(ra, ra, kOffsetRaBytes);
2355 } 2359 }
2356 #endif 2360 #endif
2357 2361
2358 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize);
2359 pop(t9); // 2 instructions: lw, add sp. 2362 pop(t9); // 2 instructions: lw, add sp.
2360 Jump(t9); // 2 instructions: jr, nop (in delay slot). 2363 Jump(t9); // 2 instructions: jr, nop (in delay slot).
2361 2364
2362 if (emit_debug_code()) { 2365 if (emit_debug_code()) {
2363 // Make sure that the expected number of instructions were generated. 2366 // Make sure that the expected number of instructions were generated.
2364 ASSERT_EQ(kOffsetRaInstructions, 2367 ASSERT_EQ(kOffsetRaInstructions,
2365 InstructionsGeneratedSince(&find_ra)); 2368 InstructionsGeneratedSince(&find_ra));
2366 } 2369 }
2367 } 2370 }
2368 2371
2369 2372
2370 void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type, 2373 void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type,
2371 Register value) { 2374 Register value) {
2372 // Adjust this code if not the case. 2375 // Adjust this code if not the case.
2373 STATIC_ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize); 2376 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
2377 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize);
2378 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 1 * kPointerSize);
2379 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 2 * kPointerSize);
2380 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 3 * kPointerSize);
2381 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 4 * kPointerSize);
2374 2382
2375 // v0 is expected to hold the exception. 2383 // v0 is expected to hold the exception.
2376 Move(v0, value); 2384 Move(v0, value);
2377 2385
2378 // Drop sp to the top stack handler. 2386 // Drop sp to the top stack handler.
2379 li(a3, Operand(ExternalReference(Isolate::k_handler_address, isolate()))); 2387 li(a3, Operand(ExternalReference(Isolate::k_handler_address, isolate())));
2380 lw(sp, MemOperand(a3)); 2388 lw(sp, MemOperand(a3));
2381 2389
2382 // Unwind the handlers until the ENTRY handler is found. 2390 // Unwind the handlers until the ENTRY handler is found.
2383 Label loop, done; 2391 Label loop, done;
2384 bind(&loop); 2392 bind(&loop);
2385 // Load the type of the current stack handler. 2393 // Load the type of the current stack handler.
2386 const int kStateOffset = StackHandlerConstants::kStateOffset; 2394 const int kStateOffset = StackHandlerConstants::kStateOffset;
2387 lw(a2, MemOperand(sp, kStateOffset)); 2395 lw(a2, MemOperand(sp, kStateOffset));
2388 Branch(&done, eq, a2, Operand(StackHandler::ENTRY)); 2396 Branch(&done, eq, a2, Operand(StackHandler::ENTRY));
2389 // Fetch the next handler in the list. 2397 // Fetch the next handler in the list.
2390 const int kNextOffset = StackHandlerConstants::kNextOffset; 2398 const int kNextOffset = StackHandlerConstants::kNextOffset;
2391 lw(sp, MemOperand(sp, kNextOffset)); 2399 lw(sp, MemOperand(sp, kNextOffset));
2392 jmp(&loop); 2400 jmp(&loop);
2393 bind(&done); 2401 bind(&done);
2394 2402
2395 // Set the top handler address to next handler past the current ENTRY handler. 2403 // Set the top handler address to next handler past the current ENTRY handler.
2396 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
2397 pop(a2); 2404 pop(a2);
2398 sw(a2, MemOperand(a3)); 2405 sw(a2, MemOperand(a3));
2399 2406
2400 if (type == OUT_OF_MEMORY) { 2407 if (type == OUT_OF_MEMORY) {
2401 // Set external caught exception to false. 2408 // Set external caught exception to false.
2402 ExternalReference external_caught( 2409 ExternalReference external_caught(
2403 Isolate::k_external_caught_exception_address, isolate()); 2410 Isolate::k_external_caught_exception_address, isolate());
2404 li(a0, Operand(false, RelocInfo::NONE)); 2411 li(a0, Operand(false, RelocInfo::NONE));
2405 li(a2, Operand(external_caught)); 2412 li(a2, Operand(external_caught));
2406 sw(a0, MemOperand(a2)); 2413 sw(a0, MemOperand(a2));
2407 2414
2408 // Set pending exception and v0 to out of memory exception. 2415 // Set pending exception and v0 to out of memory exception.
2409 Failure* out_of_memory = Failure::OutOfMemoryException(); 2416 Failure* out_of_memory = Failure::OutOfMemoryException();
2410 li(v0, Operand(reinterpret_cast<int32_t>(out_of_memory))); 2417 li(v0, Operand(reinterpret_cast<int32_t>(out_of_memory)));
2411 li(a2, Operand(ExternalReference(Isolate::k_pending_exception_address, 2418 li(a2, Operand(ExternalReference(Isolate::k_pending_exception_address,
2412 isolate()))); 2419 isolate())));
2413 sw(v0, MemOperand(a2)); 2420 sw(v0, MemOperand(a2));
2414 } 2421 }
2415 2422
2416 // Stack layout at this point. See also StackHandlerConstants. 2423 // Stack layout at this point. See also StackHandlerConstants.
2417 // sp -> state (ENTRY) 2424 // sp -> state (ENTRY)
2425 // cp
2418 // fp 2426 // fp
2419 // ra 2427 // ra
2420 2428
2421 // Discard handler state (a2 is not used) and restore frame pointer. 2429 // Restore context and frame pointer, discard state (r2).
2422 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize); 2430 MultiPop(a2.bit() | cp.bit() | fp.bit());
2423 MultiPop(a2.bit() | fp.bit()); // a2: discarded state.
2424 // Before returning we restore the context from the frame pointer if
2425 // not NULL. The frame pointer is NULL in the exception handler of a
2426 // JS entry frame.
2427 Label cp_null;
2428 Branch(USE_DELAY_SLOT, &cp_null, eq, fp, Operand(zero_reg));
2429 mov(cp, zero_reg); // In the branch delay slot.
2430 lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
2431 bind(&cp_null);
2432 2431
2433 #ifdef DEBUG 2432 #ifdef DEBUG
2434 // When emitting debug_code, set ra as return address for the jump. 2433 // When emitting debug_code, set ra as return address for the jump.
2435 // 5 instructions: add: 1, pop: 2, jump: 2. 2434 // 5 instructions: add: 1, pop: 2, jump: 2.
2436 const int kOffsetRaInstructions = 5; 2435 const int kOffsetRaInstructions = 5;
2437 Label find_ra; 2436 Label find_ra;
2438 2437
2439 if (emit_debug_code()) { 2438 if (emit_debug_code()) {
2440 // Compute ra for the Jump(t9). 2439 // Compute ra for the Jump(t9).
2441 const int kOffsetRaBytes = kOffsetRaInstructions * Assembler::kInstrSize; 2440 const int kOffsetRaBytes = kOffsetRaInstructions * Assembler::kInstrSize;
2442 2441
2443 // This branch-and-link sequence is needed to get the current PC on mips, 2442 // This branch-and-link sequence is needed to get the current PC on mips,
2444 // saved to the ra register. Then adjusted for instruction count. 2443 // saved to the ra register. Then adjusted for instruction count.
2445 bal(&find_ra); // bal exposes branch-delay slot. 2444 bal(&find_ra); // bal exposes branch-delay slot.
2446 nop(); // Branch delay slot nop. 2445 nop(); // Branch delay slot nop.
2447 bind(&find_ra); 2446 bind(&find_ra);
2448 addiu(ra, ra, kOffsetRaBytes); 2447 addiu(ra, ra, kOffsetRaBytes);
2449 } 2448 }
2450 #endif 2449 #endif
2451 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize);
2452 pop(t9); // 2 instructions: lw, add sp. 2450 pop(t9); // 2 instructions: lw, add sp.
2453 Jump(t9); // 2 instructions: jr, nop (in delay slot). 2451 Jump(t9); // 2 instructions: jr, nop (in delay slot).
2454 2452
2455 if (emit_debug_code()) { 2453 if (emit_debug_code()) {
2456 // Make sure that the expected number of instructions were generated. 2454 // Make sure that the expected number of instructions were generated.
2457 ASSERT_EQ(kOffsetRaInstructions, 2455 ASSERT_EQ(kOffsetRaInstructions,
2458 InstructionsGeneratedSince(&find_ra)); 2456 InstructionsGeneratedSince(&find_ra));
2459 } 2457 }
2460 } 2458 }
2461 2459
(...skipping 1829 matching lines...) Expand 10 before | Expand all | Expand 10 after
4291 opcode == BGTZL); 4289 opcode == BGTZL);
4292 opcode = (cond == eq) ? BEQ : BNE; 4290 opcode = (cond == eq) ? BEQ : BNE;
4293 instr = (instr & ~kOpcodeMask) | opcode; 4291 instr = (instr & ~kOpcodeMask) | opcode;
4294 masm_.emit(instr); 4292 masm_.emit(instr);
4295 } 4293 }
4296 4294
4297 4295
4298 } } // namespace v8::internal 4296 } } // namespace v8::internal
4299 4297
4300 #endif // V8_TARGET_ARCH_MIPS 4298 #endif // V8_TARGET_ARCH_MIPS
OLDNEW
« no previous file with comments | « src/mips/frames-mips.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698