Version 2.3.4

Fixed problems in implementation of ES5 function.prototype.bind.

Fixed error when using apply with arguments object on ARM (issue 784).

Added setting of global flags to debugger protocol.

Fixed an error affecting cached results of sin and cos (issue 792).

Removed memory leak from a boundary case where V8 is not initialized.

Fixed issue where debugger could set breakpoints outside the body of a function.

Fixed issue in debugger when using both live edit and step in features.

Added Number-letter (Nl) category to Unicode tables.  These characters can now be used in identifiers.

Fixed an assert failure on X64 (issue 806).

Performance improvements on all platforms.


git-svn-id: http://v8.googlecode.com/svn/trunk@5164 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc
index a5634a7..88f61d4 100644
--- a/src/x64/macro-assembler-x64.cc
+++ b/src/x64/macro-assembler-x64.cc
@@ -336,12 +336,32 @@
 }
 
 
+Object* MacroAssembler::TryCallStub(CodeStub* stub) {
+  ASSERT(allow_stub_calls());  // Calls are not allowed in some stubs.
+  Object* result = stub->TryGetCode();
+  if (!result->IsFailure()) {
+    call(Handle<Code>(Code::cast(result)), RelocInfo::CODE_TARGET);
+  }
+  return result;
+}
+
+
 void MacroAssembler::TailCallStub(CodeStub* stub) {
   ASSERT(allow_stub_calls());  // calls are not allowed in some stubs
   Jump(stub->GetCode(), RelocInfo::CODE_TARGET);
 }
 
 
+Object* MacroAssembler::TryTailCallStub(CodeStub* stub) {
+  ASSERT(allow_stub_calls());  // Calls are not allowed in some stubs.
+  Object* result = stub->TryGetCode();
+  if (!result->IsFailure()) {
+    jmp(Handle<Code>(Code::cast(result)), RelocInfo::CODE_TARGET);
+  }
+  return result;
+}
+
+
 void MacroAssembler::StubReturn(int argc) {
   ASSERT(argc >= 1 && generating_stub());
   ret((argc - 1) * kPointerSize);
@@ -361,6 +381,12 @@
 }
 
 
+Object* MacroAssembler::TryCallRuntime(Runtime::FunctionId id,
+                                       int num_arguments) {
+  return TryCallRuntime(Runtime::FunctionForId(id), num_arguments);
+}
+
+
 void MacroAssembler::CallRuntime(Runtime::Function* f, int num_arguments) {
   // If the expected number of arguments of the runtime function is
   // constant, we check that the actual number of arguments match the
@@ -381,6 +407,26 @@
 }
 
 
+Object* MacroAssembler::TryCallRuntime(Runtime::Function* f,
+                                       int num_arguments) {
+  if (f->nargs >= 0 && f->nargs != num_arguments) {
+    IllegalOperation(num_arguments);
+    // Since we did not call the stub, there was no allocation failure.
+    // Return some non-failure object.
+    return Heap::undefined_value();
+  }
+
+  // TODO(1236192): Most runtime routines don't need the number of
+  // arguments passed in because it is constant. At some point we
+  // should remove this need and make the runtime routine entry code
+  // smarter.
+  Set(rax, num_arguments);
+  movq(rbx, ExternalReference(f));
+  CEntryStub ces(f->result_size);
+  return TryCallStub(&ces);
+}
+
+
 void MacroAssembler::CallExternalReference(const ExternalReference& ext,
                                            int num_arguments) {
   Set(rax, num_arguments);
@@ -417,6 +463,87 @@
 }
 
 
+static int Offset(ExternalReference ref0, ExternalReference ref1) {
+  int64_t offset = (ref0.address() - ref1.address());
+  // Check that fits into int.
+  ASSERT(static_cast<int>(offset) == offset);
+  return static_cast<int>(offset);
+}
+
+
+void MacroAssembler::PushHandleScope(Register scratch) {
+  ExternalReference extensions_address =
+      ExternalReference::handle_scope_extensions_address();
+  const int kExtensionsOffset = 0;
+  const int kNextOffset = Offset(
+      ExternalReference::handle_scope_next_address(),
+      extensions_address);
+  const int kLimitOffset = Offset(
+      ExternalReference::handle_scope_limit_address(),
+      extensions_address);
+
+  // Push the number of extensions, smi-tagged so the gc will ignore it.
+  movq(kScratchRegister, extensions_address);
+  movq(scratch, Operand(kScratchRegister, kExtensionsOffset));
+  movq(Operand(kScratchRegister, kExtensionsOffset), Immediate(0));
+  Integer32ToSmi(scratch, scratch);
+  push(scratch);
+  // Push next and limit pointers which will be wordsize aligned and
+  // hence automatically smi tagged.
+  push(Operand(kScratchRegister, kNextOffset));
+  push(Operand(kScratchRegister, kLimitOffset));
+}
+
+
+Object* MacroAssembler::PopHandleScopeHelper(Register saved,
+                                             Register scratch,
+                                             bool gc_allowed) {
+  ExternalReference extensions_address =
+      ExternalReference::handle_scope_extensions_address();
+  const int kExtensionsOffset = 0;
+  const int kNextOffset = Offset(
+      ExternalReference::handle_scope_next_address(),
+      extensions_address);
+  const int kLimitOffset = Offset(
+      ExternalReference::handle_scope_limit_address(),
+      extensions_address);
+
+  Object* result = NULL;
+  Label write_back;
+  movq(kScratchRegister, extensions_address);
+  cmpq(Operand(kScratchRegister, kExtensionsOffset), Immediate(0));
+  j(equal, &write_back);
+  push(saved);
+  if (gc_allowed) {
+    CallRuntime(Runtime::kDeleteHandleScopeExtensions, 0);
+  } else {
+    result = TryCallRuntime(Runtime::kDeleteHandleScopeExtensions, 0);
+    if (result->IsFailure()) return result;
+  }
+  pop(saved);
+  movq(kScratchRegister, extensions_address);
+
+  bind(&write_back);
+  pop(Operand(kScratchRegister, kLimitOffset));
+  pop(Operand(kScratchRegister, kNextOffset));
+  pop(scratch);
+  SmiToInteger32(scratch, scratch);
+  movq(Operand(kScratchRegister, kExtensionsOffset), scratch);
+
+  return result;
+}
+
+
+void MacroAssembler::PopHandleScope(Register saved, Register scratch) {
+  PopHandleScopeHelper(saved, scratch, true);
+}
+
+
+Object* MacroAssembler::TryPopHandleScope(Register saved, Register scratch) {
+  return PopHandleScopeHelper(saved, scratch, false);
+}
+
+
 void MacroAssembler::JumpToExternalReference(const ExternalReference& ext,
                                              int result_size) {
   // Set the entry point and jump to the C entry runtime stub.
@@ -2208,7 +2335,8 @@
 }
 
 
-void MacroAssembler::EnterExitFrame(ExitFrame::Mode mode, int result_size) {
+void MacroAssembler::EnterExitFramePrologue(ExitFrame::Mode mode,
+                                            bool save_rax) {
   // Setup the frame structure on the stack.
   // All constants are relative to the frame pointer of the exit frame.
   ASSERT(ExitFrameConstants::kCallerSPDisplacement == +2 * kPointerSize);
@@ -2226,18 +2354,19 @@
   // Save the frame pointer and the context in top.
   ExternalReference c_entry_fp_address(Top::k_c_entry_fp_address);
   ExternalReference context_address(Top::k_context_address);
-  movq(r14, rax);  // Backup rax before we use it.
+  if (save_rax) {
+    movq(r14, rax);  // Backup rax before we use it.
+  }
 
   movq(rax, rbp);
   store_rax(c_entry_fp_address);
   movq(rax, rsi);
   store_rax(context_address);
+}
 
-  // Setup argv in callee-saved register r12. It is reused in LeaveExitFrame,
-  // so it must be retained across the C-call.
-  int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize;
-  lea(r12, Operand(rbp, r14, times_pointer_size, offset));
-
+void MacroAssembler::EnterExitFrameEpilogue(ExitFrame::Mode mode,
+                                            int result_size,
+                                            int argc) {
 #ifdef ENABLE_DEBUGGER_SUPPORT
   // Save the state of all registers to the stack from the memory
   // location. This is needed to allow nested break points.
@@ -2258,7 +2387,7 @@
   // Reserve space for the Arguments object.  The Windows 64-bit ABI
   // requires us to pass this structure as a pointer to its location on
   // the stack.  The structure contains 2 values.
-  int argument_stack_space = 2 * kPointerSize;
+  int argument_stack_space = argc * kPointerSize;
   // We also need backing space for 4 parameters, even though
   // we only pass one or two parameter, and it is in a register.
   int argument_mirror_space = 4 * kPointerSize;
@@ -2280,6 +2409,33 @@
 }
 
 
+void MacroAssembler::EnterExitFrame(ExitFrame::Mode mode, int result_size) {
+  EnterExitFramePrologue(mode, true);
+
+  // Setup argv in callee-saved register r12. It is reused in LeaveExitFrame,
+  // so it must be retained across the C-call.
+  int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize;
+  lea(r12, Operand(rbp, r14, times_pointer_size, offset));
+
+  EnterExitFrameEpilogue(mode, result_size, 2);
+}
+
+
+void MacroAssembler::EnterApiExitFrame(ExitFrame::Mode mode,
+                                       int stack_space,
+                                       int argc,
+                                       int result_size) {
+  EnterExitFramePrologue(mode, false);
+
+  // Setup argv in callee-saved register r12. It is reused in LeaveExitFrame,
+  // so it must be retained across the C-call.
+  int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize;
+  lea(r12, Operand(rbp, (stack_space * kPointerSize) + offset));
+
+  EnterExitFrameEpilogue(mode, result_size, argc);
+}
+
+
 void MacroAssembler::LeaveExitFrame(ExitFrame::Mode mode, int result_size) {
   // Registers:
   // r12 : argv