OLD | NEW |
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 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 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
43 masm_(new MacroAssembler(NULL, buffer_size)), | 43 masm_(new MacroAssembler(NULL, buffer_size)), |
44 scope_(NULL), | 44 scope_(NULL), |
45 frame_(NULL), | 45 frame_(NULL), |
46 allocator_(NULL), | 46 allocator_(NULL), |
47 state_(NULL), | 47 state_(NULL), |
48 loop_nesting_(0), | 48 loop_nesting_(0), |
49 function_return_is_shadowed_(false), | 49 function_return_is_shadowed_(false), |
50 in_spilled_code_(false) { | 50 in_spilled_code_(false) { |
51 } | 51 } |
52 | 52 |
53 #define __ masm-> | 53 #define __ ACCESS_MASM(masm) |
| 54 |
54 | 55 |
55 | 56 |
56 void CodeGenerator::DeclareGlobals(Handle<FixedArray> a) { | 57 void CodeGenerator::DeclareGlobals(Handle<FixedArray> a) { |
57 UNIMPLEMENTED(); | 58 UNIMPLEMENTED(); |
58 } | 59 } |
59 | 60 |
60 void CodeGenerator::GenCode(FunctionLiteral* a) { | 61 void CodeGenerator::GenCode(FunctionLiteral* a) { |
61 masm_->int3(); // UNIMPLEMENTED | 62 masm_->int3(); // UNIMPLEMENTED |
62 } | 63 } |
63 | 64 |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
221 | 222 |
222 void CodeGenerator::VisitCompareOperation(CompareOperation* a) { | 223 void CodeGenerator::VisitCompareOperation(CompareOperation* a) { |
223 UNIMPLEMENTED(); | 224 UNIMPLEMENTED(); |
224 } | 225 } |
225 | 226 |
226 void CodeGenerator::VisitThisFunction(ThisFunction* a) { | 227 void CodeGenerator::VisitThisFunction(ThisFunction* a) { |
227 UNIMPLEMENTED(); | 228 UNIMPLEMENTED(); |
228 } | 229 } |
229 | 230 |
230 | 231 |
| 232 void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) { |
| 233 // Check that stack should contain frame pointer, code pointer, state and |
| 234 // return address in that order. |
| 235 ASSERT_EQ(StackHandlerConstants::kFPOffset + kPointerSize, |
| 236 StackHandlerConstants::kCodeOffset); |
| 237 ASSERT_EQ(StackHandlerConstants::kCodeOffset + kPointerSize, |
| 238 StackHandlerConstants::kStateOffset); |
| 239 ASSERT_EQ(StackHandlerConstants::kStateOffset + kPointerSize, |
| 240 StackHandlerConstants::kPCOffset); |
| 241 |
| 242 ExternalReference handler_address(Top::k_handler_address); |
| 243 __ movq(kScratchRegister, handler_address); |
| 244 __ movq(rdx, Operand(kScratchRegister, 0)); |
| 245 // get next in chain |
| 246 __ movq(rcx, Operand(rdx, StackHandlerConstants::kAddressDisplacement)); |
| 247 __ movq(Operand(kScratchRegister, 0), rcx); |
| 248 __ movq(rsp, rdx); |
| 249 __ pop(rbp); // pop frame pointer |
| 250 __ pop(rdx); // remove code pointer |
| 251 __ pop(rdx); // remove state |
| 252 |
| 253 // Before returning we restore the context from the frame pointer if not NULL. |
| 254 // The frame pointer is NULL in the exception handler of a JS entry frame. |
| 255 __ xor_(rsi, rsi); // tentatively set context pointer to NULL |
| 256 Label skip; |
| 257 __ cmp(rbp, Immediate(0)); |
| 258 __ j(equal, &skip); |
| 259 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 260 __ bind(&skip); |
| 261 |
| 262 __ ret(0); |
| 263 } |
| 264 |
| 265 |
| 266 |
| 267 void CEntryStub::GenerateCore(MacroAssembler* masm, |
| 268 Label* throw_normal_exception, |
| 269 Label* throw_out_of_memory_exception, |
| 270 StackFrame::Type frame_type, |
| 271 bool do_gc, |
| 272 bool always_allocate_scope) { |
| 273 // rax: result parameter for PerformGC, if any |
| 274 // rbx: pointer to C function (C callee-saved) |
| 275 // rbp: frame pointer (restored after C call) |
| 276 // rsp: stack pointer (restored after C call) |
| 277 // rdi: number of arguments including receiver (C callee-saved) |
| 278 // rsi: pointer to the first argument (C callee-saved) |
| 279 |
| 280 if (do_gc) { |
| 281 __ movq(Operand(rsp, 0), rax); // Result. |
| 282 __ movq(kScratchRegister, |
| 283 FUNCTION_ADDR(Runtime::PerformGC), |
| 284 RelocInfo::RUNTIME_ENTRY); |
| 285 __ call(kScratchRegister); |
| 286 } |
| 287 |
| 288 ExternalReference scope_depth = |
| 289 ExternalReference::heap_always_allocate_scope_depth(); |
| 290 if (always_allocate_scope) { |
| 291 __ movq(kScratchRegister, scope_depth); |
| 292 __ inc(Operand(kScratchRegister, 0)); |
| 293 } |
| 294 |
| 295 // Call C function. |
| 296 __ movq(Operand(rsp, 0 * kPointerSize), rdi); // argc. |
| 297 __ movq(Operand(rsp, 1 * kPointerSize), rsi); // argv. |
| 298 __ call(rbx); |
| 299 // Result is in rax - do not destroy this register! |
| 300 |
| 301 if (always_allocate_scope) { |
| 302 __ movq(kScratchRegister, scope_depth); |
| 303 __ dec(Operand(kScratchRegister, 0)); |
| 304 } |
| 305 |
| 306 // Check for failure result. |
| 307 Label failure_returned; |
| 308 ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0); |
| 309 __ lea(rcx, Operand(rax, 1)); |
| 310 // Lower 2 bits of rcx are 0 iff rax has failure tag. |
| 311 __ testl(rcx, Immediate(kFailureTagMask)); |
| 312 __ j(zero, &failure_returned); |
| 313 |
| 314 // Exit the JavaScript to C++ exit frame. |
| 315 __ LeaveExitFrame(frame_type); |
| 316 __ ret(0); |
| 317 |
| 318 // Handling of failure. |
| 319 __ bind(&failure_returned); |
| 320 |
| 321 Label retry; |
| 322 // If the returned exception is RETRY_AFTER_GC continue at retry label |
| 323 ASSERT(Failure::RETRY_AFTER_GC == 0); |
| 324 __ testq(rax, Immediate(((1 << kFailureTypeTagSize) - 1) << kFailureTagSize)); |
| 325 __ j(zero, &retry); |
| 326 |
| 327 Label continue_exception; |
| 328 // If the returned failure is EXCEPTION then promote Top::pending_exception(). |
| 329 __ movq(kScratchRegister, Failure::Exception(), RelocInfo::NONE); |
| 330 __ cmp(rax, kScratchRegister); |
| 331 __ j(not_equal, &continue_exception); |
| 332 |
| 333 // Retrieve the pending exception and clear the variable. |
| 334 ExternalReference pending_exception_address(Top::k_pending_exception_address); |
| 335 __ movq(kScratchRegister, pending_exception_address); |
| 336 __ movq(rax, Operand(kScratchRegister, 0)); |
| 337 __ movq(rdx, ExternalReference::the_hole_value_location()); |
| 338 __ movq(rdx, Operand(rdx, 0)); |
| 339 __ movq(Operand(kScratchRegister, 0), rdx); |
| 340 |
| 341 __ bind(&continue_exception); |
| 342 // Special handling of out of memory exception. |
| 343 __ movq(kScratchRegister, Failure::OutOfMemoryException(), RelocInfo::NONE); |
| 344 __ cmp(rax, kScratchRegister); |
| 345 __ j(equal, throw_out_of_memory_exception); |
| 346 |
| 347 // Handle normal exception. |
| 348 __ jmp(throw_normal_exception); |
| 349 |
| 350 // Retry. |
| 351 __ bind(&retry); |
| 352 } |
| 353 |
| 354 |
| 355 void CEntryStub::GenerateThrowOutOfMemory(MacroAssembler* masm) { |
| 356 // Fetch top stack handler. |
| 357 ExternalReference handler_address(Top::k_handler_address); |
| 358 __ movq(kScratchRegister, handler_address); |
| 359 __ movq(rdx, Operand(kScratchRegister, 0)); |
| 360 |
| 361 // Unwind the handlers until the ENTRY handler is found. |
| 362 Label loop, done; |
| 363 __ bind(&loop); |
| 364 // Load the type of the current stack handler. |
| 365 const int kStateOffset = StackHandlerConstants::kAddressDisplacement + |
| 366 StackHandlerConstants::kStateOffset; |
| 367 __ cmp(Operand(rdx, kStateOffset), Immediate(StackHandler::ENTRY)); |
| 368 __ j(equal, &done); |
| 369 // Fetch the next handler in the list. |
| 370 const int kNextOffset = StackHandlerConstants::kAddressDisplacement + |
| 371 StackHandlerConstants::kNextOffset; |
| 372 __ movq(rdx, Operand(rdx, kNextOffset)); |
| 373 __ jmp(&loop); |
| 374 __ bind(&done); |
| 375 |
| 376 // Set the top handler address to next handler past the current ENTRY handler. |
| 377 __ movq(rax, Operand(rdx, kNextOffset)); |
| 378 __ store_rax(handler_address); |
| 379 |
| 380 // Set external caught exception to false. |
| 381 __ movq(rax, Immediate(false)); |
| 382 ExternalReference external_caught(Top::k_external_caught_exception_address); |
| 383 __ store_rax(external_caught); |
| 384 |
| 385 // Set pending exception and rax to out of memory exception. |
| 386 __ movq(rax, Failure::OutOfMemoryException(), RelocInfo::NONE); |
| 387 ExternalReference pending_exception(Top::k_pending_exception_address); |
| 388 __ store_rax(pending_exception); |
| 389 |
| 390 // Restore the stack to the address of the ENTRY handler |
| 391 __ movq(rsp, rdx); |
| 392 |
| 393 // Clear the context pointer; |
| 394 __ xor_(rsi, rsi); |
| 395 |
| 396 // Restore registers from handler. |
| 397 __ pop(rbp); // FP |
| 398 __ pop(rdx); // Code |
| 399 __ pop(rdx); // State |
| 400 |
| 401 __ ret(0); |
| 402 } |
| 403 |
| 404 |
231 void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) { | 405 void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) { |
232 masm->int3(); // TODO(X64): UNIMPLEMENTED. | 406 // rax: number of arguments including receiver |
233 } | 407 // rbx: pointer to C function (C callee-saved) |
234 | 408 // rbp: frame pointer (restored after C call) |
235 | 409 // rsp: stack pointer (restored after C call) |
| 410 // rsi: current context (C callee-saved) |
| 411 // rdi: caller's parameter pointer pp (C callee-saved) |
| 412 |
| 413 // NOTE: Invocations of builtins may return failure objects |
| 414 // instead of a proper result. The builtin entry handles |
| 415 // this by performing a garbage collection and retrying the |
| 416 // builtin once. |
| 417 |
| 418 StackFrame::Type frame_type = is_debug_break ? |
| 419 StackFrame::EXIT_DEBUG : |
| 420 StackFrame::EXIT; |
| 421 |
| 422 // Enter the exit frame that transitions from JavaScript to C++. |
| 423 __ EnterExitFrame(frame_type); |
| 424 |
| 425 // rax: result parameter for PerformGC, if any (setup below) |
| 426 // rbx: pointer to builtin function (C callee-saved) |
| 427 // rbp: frame pointer (restored after C call) |
| 428 // rsp: stack pointer (restored after C call) |
| 429 // rdi: number of arguments including receiver (C callee-saved) |
| 430 // rsi: argv pointer (C callee-saved) |
| 431 |
| 432 Label throw_out_of_memory_exception; |
| 433 Label throw_normal_exception; |
| 434 |
| 435 // Call into the runtime system. Collect garbage before the call if |
| 436 // running with --gc-greedy set. |
| 437 if (FLAG_gc_greedy) { |
| 438 Failure* failure = Failure::RetryAfterGC(0); |
| 439 __ movq(rax, failure, RelocInfo::NONE); |
| 440 } |
| 441 GenerateCore(masm, &throw_normal_exception, |
| 442 &throw_out_of_memory_exception, |
| 443 frame_type, |
| 444 FLAG_gc_greedy, |
| 445 false); |
| 446 |
| 447 // Do space-specific GC and retry runtime call. |
| 448 GenerateCore(masm, |
| 449 &throw_normal_exception, |
| 450 &throw_out_of_memory_exception, |
| 451 frame_type, |
| 452 true, |
| 453 false); |
| 454 |
| 455 // Do full GC and retry runtime call one final time. |
| 456 Failure* failure = Failure::InternalError(); |
| 457 __ movq(rax, failure, RelocInfo::NONE); |
| 458 GenerateCore(masm, |
| 459 &throw_normal_exception, |
| 460 &throw_out_of_memory_exception, |
| 461 frame_type, |
| 462 true, |
| 463 true); |
| 464 |
| 465 __ bind(&throw_out_of_memory_exception); |
| 466 GenerateThrowOutOfMemory(masm); |
| 467 // control flow for generated will not return. |
| 468 |
| 469 __ bind(&throw_normal_exception); |
| 470 GenerateThrowTOS(masm); |
| 471 } |
| 472 |
| 473 |
236 void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) { | 474 void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) { |
237 Label invoke, exit; | 475 Label invoke, exit; |
238 | 476 |
239 // Setup frame. | 477 // Setup frame. |
240 __ push(rbp); | 478 __ push(rbp); |
241 __ movq(rbp, rsp); | 479 __ movq(rbp, rsp); |
242 | 480 |
243 // Save callee-saved registers (X64 calling conventions). | 481 // Save callee-saved registers (X64 calling conventions). |
244 int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY; | 482 int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY; |
245 // Push something that is not an arguments adaptor. | 483 // Push something that is not an arguments adaptor. |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
319 | 557 |
320 // Restore frame pointer and return. | 558 // Restore frame pointer and return. |
321 __ pop(rbp); | 559 __ pop(rbp); |
322 __ ret(0); | 560 __ ret(0); |
323 } | 561 } |
324 | 562 |
325 | 563 |
326 #undef __ | 564 #undef __ |
327 | 565 |
328 } } // namespace v8::internal | 566 } } // namespace v8::internal |
OLD | NEW |