| 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 | 
|---|