Reverting 3159, 3151 and 3150
authorsgjesse@chromium.org <sgjesse@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 29 Oct 2009 13:17:11 +0000 (13:17 +0000)
committersgjesse@chromium.org <sgjesse@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 29 Oct 2009 13:17:11 +0000 (13:17 +0000)
TBR=christian.plesner.hansen@gmail.com
Review URL: http://codereview.chromium.org/343035

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3174 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

43 files changed:
src/api.h
src/arm/codegen-arm.cc
src/arm/frames-arm.cc
src/arm/frames-arm.h
src/arm/macro-assembler-arm.cc
src/arm/macro-assembler-arm.h
src/assembler.cc
src/assembler.h
src/code-stubs.cc
src/code-stubs.h
src/codegen.cc
src/codegen.h
src/frames.cc
src/frames.h
src/globals.h
src/handles.cc
src/handles.h
src/ia32/codegen-ia32.cc
src/ia32/frames-ia32.cc
src/ia32/frames-ia32.h
src/ia32/macro-assembler-ia32.cc
src/ia32/macro-assembler-ia32.h
src/ia32/stub-cache-ia32.cc
src/objects-debug.cc
src/objects-inl.h
src/objects.h
src/runtime.cc
src/runtime.h
src/stub-cache.cc
src/top.h
src/x64/codegen-x64.cc
src/x64/frames-x64.cc
src/x64/frames-x64.h
src/x64/macro-assembler-x64.cc
src/x64/macro-assembler-x64.h
test/cctest/SConscript
test/cctest/cctest.cc
test/cctest/cctest.h
test/cctest/test-accessors.cc [deleted file]
test/cctest/test-api.cc
test/cctest/test-debug.cc
test/cctest/test-log-stack-tracer.cc
test/mjsunit/fuzz-natives.js

index a28e1f07743c7218daaffd4e8c590bcecf686f82..1221f352cc678a35def37a2316c09a13814b3ace 100644 (file)
--- a/src/api.h
+++ b/src/api.h
@@ -125,15 +125,6 @@ static inline v8::internal::Handle<v8::internal::Object> FromCData(T obj) {
 }
 
 
-class ApiFunction {
- public:
-  explicit ApiFunction(v8::internal::Address addr) : addr_(addr) { }
-  v8::internal::Address address() { return addr_; }
- private:
-  v8::internal::Address addr_;
-};
-
-
 v8::Arguments::Arguments(v8::Local<v8::Value> data,
                          v8::Local<v8::Object> holder,
                          v8::Local<v8::Function> callee,
index 3292bdcff20ffda1c6601557b9ca55781c7e9be1..dd88515e7a95cd9ecc91fd75a0ec3ebf39ab0316 100644 (file)
@@ -5795,7 +5795,7 @@ void CEntryStub::GenerateCore(MacroAssembler* masm,
                               Label* throw_normal_exception,
                               Label* throw_termination_exception,
                               Label* throw_out_of_memory_exception,
-                              ExitFrame::Mode mode,
+                              StackFrame::Type frame_type,
                               bool do_gc,
                               bool always_allocate) {
   // r0: result parameter for PerformGC, if any
@@ -5855,7 +5855,7 @@ void CEntryStub::GenerateCore(MacroAssembler* masm,
   // r0:r1: result
   // sp: stack pointer
   // fp: frame pointer
-  __ LeaveExitFrame(mode);
+  __ LeaveExitFrame(frame_type);
 
   // check if we should retry or throw exception
   Label retry;
@@ -5901,12 +5901,12 @@ void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
   // this by performing a garbage collection and retrying the
   // builtin once.
 
-  ExitFrame::Mode mode = is_debug_break
-      ? ExitFrame::MODE_DEBUG
-      : ExitFrame::MODE_NORMAL;
+  StackFrame::Type frame_type = is_debug_break
+      ? StackFrame::EXIT_DEBUG
+      : StackFrame::EXIT;
 
   // Enter the exit frame that transitions from JavaScript to C++.
-  __ EnterExitFrame(mode);
+  __ EnterExitFrame(frame_type);
 
   // r4: number of arguments (C callee-saved)
   // r5: pointer to builtin function (C callee-saved)
@@ -5921,7 +5921,7 @@ void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
                &throw_normal_exception,
                &throw_termination_exception,
                &throw_out_of_memory_exception,
-               mode,
+               frame_type,
                false,
                false);
 
@@ -5930,7 +5930,7 @@ void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
                &throw_normal_exception,
                &throw_termination_exception,
                &throw_out_of_memory_exception,
-               mode,
+               frame_type,
                true,
                false);
 
@@ -5941,7 +5941,7 @@ void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
                &throw_normal_exception,
                &throw_termination_exception,
                &throw_out_of_memory_exception,
-               mode,
+               frame_type,
                true,
                true);
 
index b0fa13a5a1298aa157e9f1a4a3614b37ed11ea80..6fde4b73c0f7a0e164d918d28d075a28d16bd85e 100644 (file)
@@ -54,24 +54,23 @@ StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) {
   if (fp == 0) return NONE;
   // Compute frame type and stack pointer.
   Address sp = fp + ExitFrameConstants::kSPDisplacement;
-  const int offset = ExitFrameConstants::kCodeOffset;
-  Object* code = Memory::Object_at(fp + offset);
-  bool is_debug_exit = code->IsSmi();
-  if (is_debug_exit) {
+  Type type;
+  if (Memory::Address_at(fp + ExitFrameConstants::kDebugMarkOffset) != 0) {
+    type = EXIT_DEBUG;
     sp -= kNumJSCallerSaved * kPointerSize;
+  } else {
+    type = EXIT;
   }
   // Fill in the state.
   state->sp = sp;
   state->fp = fp;
   state->pc_address = reinterpret_cast<Address*>(sp - 1 * kPointerSize);
-  return EXIT;
+  return type;
 }
 
 
 void ExitFrame::Iterate(ObjectVisitor* v) const {
-  v->VisitPointer(&code_slot());
-  // The arguments are traversed as part of the expression stack of
-  // the calling frame.
+  // Do nothing
 }
 
 
index 4924c1aeb93b9d5c7eed3e692e825dfe32955408..0874c092744c7465f01f5d6000c8b25db682334d 100644 (file)
@@ -100,7 +100,7 @@ class ExitFrameConstants : public AllStatic {
   static const int kSPDisplacement = -1 * kPointerSize;
 
   // The debug marker is just above the frame pointer.
-  static const int kCodeOffset = -1 * kPointerSize;
+  static const int kDebugMarkOffset = -1 * kPointerSize;
 
   static const int kSavedRegistersOffset = 0 * kPointerSize;
 
index dc73bad93f189620ab0707a9d97bd08cfc33f58a..45c6540eeb431b6741fb864f81e8743b2cb3af20 100644 (file)
@@ -274,7 +274,9 @@ void MacroAssembler::LeaveFrame(StackFrame::Type type) {
 }
 
 
-void MacroAssembler::EnterExitFrame(ExitFrame::Mode mode) {
+void MacroAssembler::EnterExitFrame(StackFrame::Type type) {
+  ASSERT(type == StackFrame::EXIT || type == StackFrame::EXIT_DEBUG);
+
   // Compute the argv pointer and keep it in a callee-saved register.
   // r0 is argc.
   add(r6, sp, Operand(r0, LSL, kPointerSizeLog2));
@@ -296,11 +298,8 @@ void MacroAssembler::EnterExitFrame(ExitFrame::Mode mode) {
   stm(db_w, sp, fp.bit() | ip.bit() | lr.bit());
   mov(fp, Operand(sp));  // setup new frame pointer
 
-  if (mode == ExitFrame::MODE_DEBUG) {
-    mov(ip, Operand(Smi::FromInt(0)));
-  } else {
-    mov(ip, Operand(CodeObject()));
-  }
+  // Push debug marker.
+  mov(ip, Operand(type == StackFrame::EXIT_DEBUG ? 1 : 0));
   push(ip);
 
   // Save the frame pointer and the context in top.
@@ -317,7 +316,7 @@ void MacroAssembler::EnterExitFrame(ExitFrame::Mode mode) {
 #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.
-  if (mode == ExitFrame::MODE_DEBUG) {
+  if (type == StackFrame::EXIT_DEBUG) {
     // Use sp as base to push.
     CopyRegistersFromMemoryToStack(sp, kJSCallerSaved);
   }
@@ -349,14 +348,14 @@ void MacroAssembler::AlignStack(int offset) {
 }
 
 
-void MacroAssembler::LeaveExitFrame(ExitFrame::Mode mode) {
+void MacroAssembler::LeaveExitFrame(StackFrame::Type type) {
 #ifdef ENABLE_DEBUGGER_SUPPORT
   // Restore the memory copy of the registers by digging them out from
   // the stack. This is needed to allow nested break points.
-  if (mode == ExitFrame::MODE_DEBUG) {
+  if (type == StackFrame::EXIT_DEBUG) {
     // This code intentionally clobbers r2 and r3.
     const int kCallerSavedSize = kNumJSCallerSaved * kPointerSize;
-    const int kOffset = ExitFrameConstants::kCodeOffset - kCallerSavedSize;
+    const int kOffset = ExitFrameConstants::kDebugMarkOffset - kCallerSavedSize;
     add(r3, fp, Operand(kOffset));
     CopyRegistersFromStackToMemory(r3, r2, kJSCallerSaved);
   }
index 6dc2b7ae892cebb22e19a5ef39e4906834cc25d9..e37bb5e1c21388bc1e393321218e9eeca64dcaf3 100644 (file)
@@ -87,14 +87,14 @@ class MacroAssembler: public Assembler {
   void EnterConstructFrame() { EnterFrame(StackFrame::CONSTRUCT); }
   void LeaveConstructFrame() { LeaveFrame(StackFrame::CONSTRUCT); }
 
-  // Enter specific kind of exit frame; either normal or debug mode.
-  // Expects the number of arguments in register r0 and
+  // Enter specific kind of exit frame; either EXIT or
+  // EXIT_DEBUG. Expects the number of arguments in register r0 and
   // the builtin function to call in register r1. Exits with argc in
   // r4, argv in r6, and and the builtin function to call in r5.
-  void EnterExitFrame(ExitFrame::Mode mode);
+  void EnterExitFrame(StackFrame::Type type);
 
   // Leave the current exit frame. Expects the return value in r0.
-  void LeaveExitFrame(ExitFrame::Mode mode);
+  void LeaveExitFrame(StackFrame::Type type);
 
   // Align the stack by optionally pushing a Smi zero.
   void AlignStack(int offset);
index 34346a9105d3377ce3fe6c1f2dc558f20d24cea9..34595f83ff4257510eccd7a8f815e61777333b8e 100644 (file)
@@ -522,10 +522,6 @@ ExternalReference::ExternalReference(Builtins::CFunctionId id)
   : address_(Redirect(Builtins::c_function_address(id))) {}
 
 
-ExternalReference::ExternalReference(ApiFunction* fun)
-  : address_(Redirect(fun->address())) {}
-
-
 ExternalReference::ExternalReference(Builtins::Name name)
   : address_(Builtins::builtin_address(name)) {}
 
@@ -612,27 +608,6 @@ ExternalReference ExternalReference::new_space_allocation_limit_address() {
   return ExternalReference(Heap::NewSpaceAllocationLimitAddress());
 }
 
-
-ExternalReference ExternalReference::handle_scope_extensions_address() {
-  return ExternalReference(HandleScope::current_extensions_address());
-}
-
-
-ExternalReference ExternalReference::handle_scope_next_address() {
-  return ExternalReference(HandleScope::current_next_address());
-}
-
-
-ExternalReference ExternalReference::handle_scope_limit_address() {
-  return ExternalReference(HandleScope::current_limit_address());
-}
-
-
-ExternalReference ExternalReference::scheduled_exception_address() {
-  return ExternalReference(Top::scheduled_exception_address());
-}
-
-
 #ifdef V8_NATIVE_REGEXP
 
 ExternalReference ExternalReference::re_check_stack_guard_state() {
index 311dadd53c3cc4769efe9c7ec977eeed479a94ba..21a66dd501aaa90e5eced81be07a19828945c4a6 100644 (file)
@@ -373,8 +373,6 @@ class ExternalReference BASE_EMBEDDED {
  public:
   explicit ExternalReference(Builtins::CFunctionId id);
 
-  explicit ExternalReference(ApiFunction* ptr);
-
   explicit ExternalReference(Builtins::Name name);
 
   explicit ExternalReference(Runtime::FunctionId id);
@@ -424,12 +422,6 @@ class ExternalReference BASE_EMBEDDED {
   static ExternalReference double_fp_operation(Token::Value operation);
   static ExternalReference compare_doubles();
 
-  static ExternalReference handle_scope_extensions_address();
-  static ExternalReference handle_scope_next_address();
-  static ExternalReference handle_scope_limit_address();
-
-  static ExternalReference scheduled_exception_address();
-
   Address address() const {return reinterpret_cast<Address>(address_);}
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
index 7a2f8594598f6e1bb25eb55f47eff9629bd55487..73ff0115f2a3ad7edb017cc04ea3469de432bf1a 100644 (file)
@@ -36,27 +36,10 @@ namespace v8 {
 namespace internal {
 
 Handle<Code> CodeStub::GetCode() {
-  bool custom_cache = has_custom_cache();
-
-  int index = 0;
-  uint32_t key = 0;
-  if (custom_cache) {
-    Code* cached;
-    if (GetCustomCache(&cached)) {
-      return Handle<Code>(cached);
-    } else {
-      index = NumberDictionary::kNotFound;
-    }
-  } else {
-    key = GetKey();
-    index = Heap::code_stubs()->FindEntry(key);
-    if (index != NumberDictionary::kNotFound)
-      return Handle<Code>(Code::cast(Heap::code_stubs()->ValueAt(index)));
-  }
-
-  Code* result;
-  {
-    v8::HandleScope scope;
+  uint32_t key = GetKey();
+  int index = Heap::code_stubs()->FindEntry(key);
+  if (index == NumberDictionary::kNotFound) {
+    HandleScope scope;
 
     // Update the static counter each time a new code stub is generated.
     Counters::code_stubs.Increment();
@@ -96,21 +79,18 @@ Handle<Code> CodeStub::GetCode() {
     }
 #endif
 
-    if (custom_cache) {
-      SetCustomCache(*code);
-    } else {
-      // Update the dictionary and the root in Heap.
-      Handle<NumberDictionary> dict =
-          Factory::DictionaryAtNumberPut(
-              Handle<NumberDictionary>(Heap::code_stubs()),
-              key,
-              code);
-      Heap::public_set_code_stubs(*dict);
-    }
-    result = *code;
+    // Update the dictionary and the root in Heap.
+    Handle<NumberDictionary> dict =
+        Factory::DictionaryAtNumberPut(
+            Handle<NumberDictionary>(Heap::code_stubs()),
+            key,
+            code);
+    Heap::public_set_code_stubs(*dict);
+    index = Heap::code_stubs()->FindEntry(key);
   }
+  ASSERT(index != NumberDictionary::kNotFound);
 
-  return Handle<Code>(result);
+  return Handle<Code>(Code::cast(Heap::code_stubs()->ValueAt(index)));
 }
 
 
index 63461bc0c09d6a3592282297bcc4240935f900a4..121140d1bae670b1a364d100024bcf2815163c45 100644 (file)
@@ -75,7 +75,6 @@ class CodeStub BASE_EMBEDDED {
 #define DEF_ENUM(name) name,
     CODE_STUB_LIST(DEF_ENUM)
 #undef DEF_ENUM
-    NoCache,  // marker for stubs that do custom caching
     NUMBER_OF_IDS
   };
 
@@ -92,12 +91,6 @@ class CodeStub BASE_EMBEDDED {
 
   virtual ~CodeStub() {}
 
-  // Override these methods to provide a custom caching mechanism for
-  // an individual type of code stub.
-  virtual bool GetCustomCache(Code** code_out) { return false; }
-  virtual void SetCustomCache(Code* value) { }
-  virtual bool has_custom_cache() { return false; }
-
  protected:
   static const int kMajorBits = 5;
   static const int kMinorBits = kBitsPerInt - kSmiTagSize - kMajorBits;
index f2788a8838659fb50422ed916d671b6166328d1c..28c0ba5f9ef45e11616b6864cddf0e2659d7a8d9 100644 (file)
@@ -551,20 +551,4 @@ void ArgumentsAccessStub::Generate(MacroAssembler* masm) {
 }
 
 
-bool ApiGetterEntryStub::GetCustomCache(Code** code_out) {
-  Object* cache = info()->load_stub_cache();
-  if (cache->IsUndefined()) {
-    return false;
-  } else {
-    *code_out = Code::cast(cache);
-    return true;
-  }
-}
-
-
-void ApiGetterEntryStub::SetCustomCache(Code* value) {
-  info()->set_load_stub_cache(value);
-}
-
-
 } }  // namespace v8::internal
index fc4a53b2e73b0f98cbc349487a34c9d87e7e41c9..8c1b7336756bb47252cfeb241a7e4921311ca1b5 100644 (file)
@@ -301,7 +301,7 @@ class CEntryStub : public CodeStub {
                     Label* throw_normal_exception,
                     Label* throw_termination_exception,
                     Label* throw_out_of_memory_exception,
-                    ExitFrame::Mode mode,
+                    StackFrame::Type frame_type,
                     bool do_gc,
                     bool always_allocate_scope);
   void GenerateThrowTOS(MacroAssembler* masm);
@@ -320,32 +320,6 @@ class CEntryStub : public CodeStub {
 };
 
 
-class ApiGetterEntryStub : public CodeStub {
- public:
-  ApiGetterEntryStub(Handle<AccessorInfo> info,
-                     ApiFunction* fun)
-      : info_(info),
-        fun_(fun) { }
-  void Generate(MacroAssembler* masm);
-  virtual bool has_custom_cache() { return true; }
-  virtual bool GetCustomCache(Code** code_out);
-  virtual void SetCustomCache(Code* value);
-
-  static const int kStackSpace = 6;
-  static const int kArgc = 4;
- private:
-  Handle<AccessorInfo> info() { return info_; }
-  ApiFunction* fun() { return fun_; }
-  Major MajorKey() { return NoCache; }
-  int MinorKey() { return 0; }
-  const char* GetName() { return "ApiEntryStub"; }
-  // The accessor info associated with the function.
-  Handle<AccessorInfo> info_;
-  // The function to be called.
-  ApiFunction* fun_;
-};
-
-
 class CEntryDebugBreakStub : public CEntryStub {
  public:
   CEntryDebugBreakStub() : CEntryStub(1) { }
index d7302dea3da0eb9c0c5c9ecb9938ffc53df17e62..5cd83324c6f9ac4f43f6eb92e6dff916ada77ecd 100644 (file)
@@ -393,19 +393,8 @@ Code* EntryConstructFrame::code() const {
 }
 
 
-Object*& ExitFrame::code_slot() const {
-  const int offset = ExitFrameConstants::kCodeOffset;
-  return Memory::Object_at(fp() + offset);
-}
-
-
 Code* ExitFrame::code() const {
-  Object* code = code_slot();
-  if (code->IsSmi()) {
-    return Heap::c_entry_debug_break_code();
-  } else {
-    return Code::cast(code);
-  }
+  return Heap::c_entry_code();
 }
 
 
@@ -423,6 +412,11 @@ Address ExitFrame::GetCallerStackPointer() const {
 }
 
 
+Code* ExitDebugFrame::code() const {
+  return Heap::c_entry_debug_break_code();
+}
+
+
 Address StandardFrame::GetExpressionAddress(int n) const {
   const int offset = StandardFrameConstants::kExpressionsOffset;
   return fp() + offset - n * kPointerSize;
index 024065abf7eb909b1f0adbbad6a3ec62a58c5d23..768196d3c6869cd49a7aba7d391c36f3b9608089 100644 (file)
@@ -93,6 +93,7 @@ class StackHandler BASE_EMBEDDED {
   V(ENTRY,             EntryFrame)            \
   V(ENTRY_CONSTRUCT,   EntryConstructFrame)   \
   V(EXIT,              ExitFrame)             \
+  V(EXIT_DEBUG,        ExitDebugFrame)        \
   V(JAVA_SCRIPT,       JavaScriptFrame)       \
   V(INTERNAL,          InternalFrame)         \
   V(CONSTRUCT,         ConstructFrame)        \
@@ -118,6 +119,7 @@ class StackFrame BASE_EMBEDDED {
   bool is_entry() const { return type() == ENTRY; }
   bool is_entry_construct() const { return type() == ENTRY_CONSTRUCT; }
   bool is_exit() const { return type() == EXIT; }
+  bool is_exit_debug() const { return type() == EXIT_DEBUG; }
   bool is_java_script() const { return type() == JAVA_SCRIPT; }
   bool is_arguments_adaptor() const { return type() == ARGUMENTS_ADAPTOR; }
   bool is_internal() const { return type() == INTERNAL; }
@@ -258,13 +260,10 @@ class EntryConstructFrame: public EntryFrame {
 // Exit frames are used to exit JavaScript execution and go to C.
 class ExitFrame: public StackFrame {
  public:
-  enum Mode { MODE_NORMAL, MODE_DEBUG };
   virtual Type type() const { return EXIT; }
 
   virtual Code* code() const;
 
-  Object*& code_slot() const;
-
   // Garbage collection support.
   virtual void Iterate(ObjectVisitor* v) const;
 
@@ -290,6 +289,26 @@ class ExitFrame: public StackFrame {
 };
 
 
+class ExitDebugFrame: public ExitFrame {
+ public:
+  virtual Type type() const { return EXIT_DEBUG; }
+
+  virtual Code* code() const;
+
+  static ExitDebugFrame* cast(StackFrame* frame) {
+    ASSERT(frame->is_exit_debug());
+    return static_cast<ExitDebugFrame*>(frame);
+  }
+
+ protected:
+  explicit ExitDebugFrame(StackFrameIterator* iterator)
+      : ExitFrame(iterator) { }
+
+ private:
+  friend class StackFrameIterator;
+};
+
+
 class StandardFrame: public StackFrame {
  public:
   // Testers.
index ae10b72de7e0e888133453146c0c44e88ab95a94..fbb648f5b1ac34a500d84e8fdb302fb3097e57a9 100644 (file)
@@ -103,10 +103,6 @@ typedef byte* Address;
 #define V8PRIxPTR "lx"
 #endif
 
-#if defined(__APPLE__) && defined(__MACH__)
-#define USING_MAC_ABI
-#endif
-
 // Code-point values in Unicode 4.0 are 21 bits wide.
 typedef uint16_t uc16;
 typedef int32_t uc32;
index 275fe6a7c1228abc8e3351bf0a4e722e01f53475..b764334e830881859fbce0823699b2a19337c1d8 100644 (file)
@@ -105,21 +105,6 @@ void HandleScope::ZapRange(Object** start, Object** end) {
 }
 
 
-Address HandleScope::current_extensions_address() {
-  return reinterpret_cast<Address>(&current_.extensions);
-}
-
-
-Address HandleScope::current_next_address() {
-  return reinterpret_cast<Address>(&current_.next);
-}
-
-
-Address HandleScope::current_limit_address() {
-  return reinterpret_cast<Address>(&current_.limit);
-}
-
-
 Handle<FixedArray> AddKeysFromJSArray(Handle<FixedArray> content,
                                       Handle<JSArray> array) {
   CALL_HEAP_FUNCTION(content->AddKeysFromJSArray(*array), FixedArray);
index d3e9b788b5c6e8690a9885fd3cc0d08157d4a098..5d574657c5f0505346cd6fedb6f63bde1b8388c2 100644 (file)
@@ -133,13 +133,6 @@ class HandleScope {
     return result;
   }
 
-  // Deallocates any extensions used by the current scope.
-  static void DeleteExtensions();
-
-  static Address current_extensions_address();
-  static Address current_next_address();
-  static Address current_limit_address();
-
  private:
   // Prevent heap allocation or illegal handle scopes.
   HandleScope(const HandleScope&);
@@ -173,6 +166,9 @@ class HandleScope {
   // Extend the handle scope making room for more handles.
   static internal::Object** Extend();
 
+  // Deallocates any extensions used by the current scope.
+  static void DeleteExtensions();
+
   // Zaps the handles in the half-open interval [start, end).
   static void ZapRange(internal::Object** start, internal::Object** end);
 
index 8e8ff2e0b1fab9f0e7add9ead00b08f43bfe9b57..4ac552769962fc97bbe633bb553646ca3d20ad41 100644 (file)
@@ -7707,84 +7707,11 @@ void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) {
 }
 
 
-// If true, a Handle<T> passed by value is passed and returned by
-// using the location_ field directly.  If false, it is passed and
-// returned as a pointer to a handle.
-#ifdef USING_MAC_ABI
-static const bool kPassHandlesDirectly = true;
-#else
-static const bool kPassHandlesDirectly = false;
-#endif
-
-
-void ApiGetterEntryStub::Generate(MacroAssembler* masm) {
-  Label get_result;
-  Label prologue;
-  Label promote_scheduled_exception;
-  __ EnterApiExitFrame(ExitFrame::MODE_NORMAL, kStackSpace, kArgc);
-  ASSERT_EQ(kArgc, 4);
-  if (kPassHandlesDirectly) {
-    // When handles as passed directly we don't have to allocate extra
-    // space for and pass an out parameter.
-    __ mov(Operand(esp, 0 * kPointerSize), ebx);  // name.
-    __ mov(Operand(esp, 1 * kPointerSize), eax);  // arguments pointer.
-  } else {
-    // The function expects three arguments to be passed but we allocate
-    // four to get space for the output cell.  The argument slots are filled
-    // as follows:
-    //
-    //   3: output cell
-    //   2: arguments pointer
-    //   1: name
-    //   0: pointer to the output cell
-    //
-    // Note that this is one more "argument" than the function expects
-    // so the out cell will have to be popped explicitly after returning
-    // from the function.
-    __ mov(Operand(esp, 1 * kPointerSize), ebx);  // name.
-    __ mov(Operand(esp, 2 * kPointerSize), eax);  // arguments pointer.
-    __ mov(ebx, esp);
-    __ add(Operand(ebx), Immediate(3 * kPointerSize));
-    __ mov(Operand(esp, 0 * kPointerSize), ebx);  // output
-    __ mov(Operand(esp, 3 * kPointerSize), Immediate(0));  // out cell.
-  }
-  // Call the api function!
-  __ call(fun()->address(), RelocInfo::RUNTIME_ENTRY);
-  // Check if the function scheduled an exception.
-  ExternalReference scheduled_exception_address =
-      ExternalReference::scheduled_exception_address();
-  __ cmp(Operand::StaticVariable(scheduled_exception_address),
-         Immediate(Factory::the_hole_value()));
-  __ j(not_equal, &promote_scheduled_exception, not_taken);
-  if (!kPassHandlesDirectly) {
-    // The returned value is a pointer to the handle holding the result.
-    // Dereference this to get to the location.
-    __ mov(eax, Operand(eax, 0));
-  }
-  // Check if the result handle holds 0
-  __ test(eax, Operand(eax));
-  __ j(not_zero, &get_result, taken);
-  // It was zero; the result is undefined.
-  __ mov(eax, Factory::undefined_value());
-  __ jmp(&prologue);
-  // It was non-zero.  Dereference to get the result value.
-  __ bind(&get_result);
-  __ mov(eax, Operand(eax, 0));
-  __ bind(&prologue);
-  __ LeaveExitFrame(ExitFrame::MODE_NORMAL);
-  __ ret(0);
-  __ bind(&promote_scheduled_exception);
-  __ TailCallRuntime(ExternalReference(Runtime::kPromoteScheduledException),
-                     0,
-                     1);
-}
-
-
 void CEntryStub::GenerateCore(MacroAssembler* masm,
                               Label* throw_normal_exception,
                               Label* throw_termination_exception,
                               Label* throw_out_of_memory_exception,
-                              ExitFrame::Mode mode,
+                              StackFrame::Type frame_type,
                               bool do_gc,
                               bool always_allocate_scope) {
   // eax: result parameter for PerformGC, if any
@@ -7834,7 +7761,7 @@ void CEntryStub::GenerateCore(MacroAssembler* masm,
   __ j(zero, &failure_returned, not_taken);
 
   // Exit the JavaScript to C++ exit frame.
-  __ LeaveExitFrame(mode);
+  __ LeaveExitFrame(frame_type);
   __ ret(0);
 
   // Handling of failure.
@@ -7933,12 +7860,12 @@ void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
   // of a proper result. The builtin entry handles this by performing
   // a garbage collection and retrying the builtin (twice).
 
-  ExitFrame::Mode mode = is_debug_break
-      ? ExitFrame::MODE_DEBUG
-      : ExitFrame::MODE_NORMAL;
+  StackFrame::Type frame_type = is_debug_break ?
+      StackFrame::EXIT_DEBUG :
+      StackFrame::EXIT;
 
   // Enter the exit frame that transitions from JavaScript to C++.
-  __ EnterExitFrame(mode);
+  __ EnterExitFrame(frame_type);
 
   // eax: result parameter for PerformGC, if any (setup below)
   // ebx: pointer to builtin function  (C callee-saved)
@@ -7956,7 +7883,7 @@ void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
                &throw_normal_exception,
                &throw_termination_exception,
                &throw_out_of_memory_exception,
-               mode,
+               frame_type,
                false,
                false);
 
@@ -7965,7 +7892,7 @@ void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
                &throw_normal_exception,
                &throw_termination_exception,
                &throw_out_of_memory_exception,
-               mode,
+               frame_type,
                true,
                false);
 
@@ -7976,7 +7903,7 @@ void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
                &throw_normal_exception,
                &throw_termination_exception,
                &throw_out_of_memory_exception,
-               mode,
+               frame_type,
                true,
                true);
 
index 5c900bedd77ca1d60b71a644eac85beb2abcb148..dea439f24b8986f7d3055929f5ad2caee0bf4a5c 100644 (file)
@@ -56,14 +56,19 @@ StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) {
   state->fp = fp;
   state->sp = sp;
   state->pc_address = reinterpret_cast<Address*>(sp - 1 * kPointerSize);
-  return EXIT;
+  // Determine frame type.
+  if (Memory::Address_at(fp + ExitFrameConstants::kDebugMarkOffset) != 0) {
+    return EXIT_DEBUG;
+  } else {
+    return EXIT;
+  }
 }
 
 
 void ExitFrame::Iterate(ObjectVisitor* v) const {
-  v->VisitPointer(&code_slot());
-  // The arguments are traversed as part of the expression stack of
-  // the calling frame.
+  // Exit frames on IA-32 do not contain any pointers. The arguments
+  // are traversed as part of the expression stack of the calling
+  // frame.
 }
 
 
index c3fe6c748d5e5a92b371b6004c4e6feef64487af..3a7c86bf73560d2cf0dd5d212d927dbc459b08ae 100644 (file)
@@ -76,7 +76,7 @@ class EntryFrameConstants : public AllStatic {
 
 class ExitFrameConstants : public AllStatic {
  public:
-  static const int kCodeOffset      = -2 * kPointerSize;
+  static const int kDebugMarkOffset = -2 * kPointerSize;
   static const int kSPOffset        = -1 * kPointerSize;
 
   static const int kCallerFPOffset =  0 * kPointerSize;
index 34d4fd5f6dc113eeed1c23f816912d23f177b180..08c4c0c51bcc83931561b2d66c3310c6d32b25c2 100644 (file)
@@ -355,7 +355,10 @@ void MacroAssembler::LeaveFrame(StackFrame::Type type) {
   leave();
 }
 
-void MacroAssembler::EnterExitFramePrologue(ExitFrame::Mode mode) {
+
+void MacroAssembler::EnterExitFrame(StackFrame::Type type) {
+  ASSERT(type == StackFrame::EXIT || type == StackFrame::EXIT_DEBUG);
+
   // Setup the frame structure on the stack.
   ASSERT(ExitFrameConstants::kCallerSPDisplacement == +2 * kPointerSize);
   ASSERT(ExitFrameConstants::kCallerPCOffset == +1 * kPointerSize);
@@ -366,24 +369,23 @@ void MacroAssembler::EnterExitFramePrologue(ExitFrame::Mode mode) {
   // Reserve room for entry stack pointer and push the debug marker.
   ASSERT(ExitFrameConstants::kSPOffset  == -1 * kPointerSize);
   push(Immediate(0));  // saved entry sp, patched before call
-  if (mode == ExitFrame::MODE_DEBUG) {
-    push(Immediate(0));
-  } else {
-    push(Immediate(CodeObject()));
-  }
+  push(Immediate(type == StackFrame::EXIT_DEBUG ? 1 : 0));
 
   // 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);
   mov(Operand::StaticVariable(c_entry_fp_address), ebp);
   mov(Operand::StaticVariable(context_address), esi);
-}
 
-void MacroAssembler::EnterExitFrameEpilogue(ExitFrame::Mode mode, int argc) {
+  // Setup argc and argv in callee-saved registers.
+  int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize;
+  mov(edi, Operand(eax));
+  lea(esi, Operand(ebp, eax, times_4, offset));
+
 #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.
-  if (mode == ExitFrame::MODE_DEBUG) {
+  if (type == StackFrame::EXIT_DEBUG) {
     // TODO(1243899): This should be symmetric to
     // CopyRegistersFromStackToMemory() but it isn't! esp is assumed
     // correct here, but computed for the other call. Very error
@@ -394,8 +396,8 @@ void MacroAssembler::EnterExitFrameEpilogue(ExitFrame::Mode mode, int argc) {
   }
 #endif
 
-  // Reserve space for arguments.
-  sub(Operand(esp), Immediate(argc * kPointerSize));
+  // Reserve space for two arguments: argc and argv.
+  sub(Operand(esp), Immediate(2 * kPointerSize));
 
   // Get the required frame alignment for the OS.
   static const int kFrameAlignment = OS::ActivationFrameAlignment();
@@ -409,39 +411,15 @@ void MacroAssembler::EnterExitFrameEpilogue(ExitFrame::Mode mode, int argc) {
 }
 
 
-void MacroAssembler::EnterExitFrame(ExitFrame::Mode mode) {
-  EnterExitFramePrologue(mode);
-
-  // Setup argc and argv in callee-saved registers.
-  int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize;
-  mov(edi, Operand(eax));
-  lea(esi, Operand(ebp, eax, times_4, offset));
-
-  EnterExitFrameEpilogue(mode, 2);
-}
-
-
-void MacroAssembler::EnterApiExitFrame(ExitFrame::Mode mode,
-                                       int stack_space,
-                                       int argc) {
-  EnterExitFramePrologue(mode);
-
-  int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize;
-  lea(esi, Operand(ebp, (stack_space * kPointerSize) + offset));
-
-  EnterExitFrameEpilogue(mode, argc);
-}
-
-
-void MacroAssembler::LeaveExitFrame(ExitFrame::Mode mode) {
+void MacroAssembler::LeaveExitFrame(StackFrame::Type type) {
 #ifdef ENABLE_DEBUGGER_SUPPORT
   // Restore the memory copy of the registers by digging them out from
   // the stack. This is needed to allow nested break points.
-  if (mode == ExitFrame::MODE_DEBUG) {
+  if (type == StackFrame::EXIT_DEBUG) {
     // It's okay to clobber register ebx below because we don't need
     // the function pointer after this.
     const int kCallerSavedSize = kNumJSCallerSaved * kPointerSize;
-    int kOffset = ExitFrameConstants::kCodeOffset - kCallerSavedSize;
+    int kOffset = ExitFrameConstants::kDebugMarkOffset - kCallerSavedSize;
     lea(ebx, Operand(ebp, kOffset));
     CopyRegistersFromStackToMemory(ebx, ecx, kJSCallerSaved);
   }
@@ -953,48 +931,6 @@ void MacroAssembler::TailCallRuntime(const ExternalReference& ext,
 }
 
 
-void MacroAssembler::PushHandleScope(Register scratch) {
-  // Push the number of extensions, smi-tagged so the gc will ignore it.
-  ExternalReference extensions_address =
-      ExternalReference::handle_scope_extensions_address();
-  mov(scratch, Operand::StaticVariable(extensions_address));
-  ASSERT_EQ(0, kSmiTag);
-  shl(scratch, kSmiTagSize);
-  push(scratch);
-  mov(Operand::StaticVariable(extensions_address), Immediate(0));
-  // Push next and limit pointers which will be wordsize aligned and
-  // hence automatically smi tagged.
-  ExternalReference next_address =
-      ExternalReference::handle_scope_next_address();
-  push(Operand::StaticVariable(next_address));
-  ExternalReference limit_address =
-      ExternalReference::handle_scope_limit_address();
-  push(Operand::StaticVariable(limit_address));
-}
-
-
-void MacroAssembler::PopHandleScope(Register scratch) {
-  ExternalReference extensions_address =
-        ExternalReference::handle_scope_extensions_address();
-  Label write_back;
-  mov(scratch, Operand::StaticVariable(extensions_address));
-  cmp(Operand(scratch), Immediate(0));
-  j(equal, &write_back);
-  CallRuntime(Runtime::kDeleteHandleScopeExtensions, 0);
-
-  bind(&write_back);
-  ExternalReference limit_address =
-        ExternalReference::handle_scope_limit_address();
-  pop(Operand::StaticVariable(limit_address));
-  ExternalReference next_address =
-        ExternalReference::handle_scope_next_address();
-  pop(Operand::StaticVariable(next_address));
-  pop(scratch);
-  shr(scratch, kSmiTagSize);
-  mov(Operand::StaticVariable(extensions_address), scratch);
-}
-
-
 void MacroAssembler::JumpToRuntime(const ExternalReference& ext) {
   // Set the entry point and jump to the C entry runtime stub.
   mov(ebx, Immediate(ext));
index 18d221c4073c2049138324b8f228c635357de59b..a0a242806b2ac449940dd8f22045e69c4d7b65e1 100644 (file)
@@ -77,18 +77,16 @@ class MacroAssembler: public Assembler {
   void EnterConstructFrame() { EnterFrame(StackFrame::CONSTRUCT); }
   void LeaveConstructFrame() { LeaveFrame(StackFrame::CONSTRUCT); }
 
-  // Enter specific kind of exit frame; either in normal or debug mode.
-  // Expects the number of arguments in register eax and
+  // Enter specific kind of exit frame; either EXIT or
+  // EXIT_DEBUG. Expects the number of arguments in register eax and
   // sets up the number of arguments in register edi and the pointer
   // to the first argument in register esi.
-  void EnterExitFrame(ExitFrame::Mode mode);
-
-  void EnterApiExitFrame(ExitFrame::Mode mode, int stack_space, int argc);
+  void EnterExitFrame(StackFrame::Type type);
 
   // Leave the current exit frame. Expects the return value in
   // register eax:edx (untouched) and the pointer to the first
   // argument in register esi.
-  void LeaveExitFrame(ExitFrame::Mode mode);
+  void LeaveExitFrame(StackFrame::Type type);
 
 
   // ---------------------------------------------------------------------------
@@ -271,9 +269,6 @@ class MacroAssembler: public Assembler {
                        int num_arguments,
                        int result_size);
 
-  void PushHandleScope(Register scratch);
-  void PopHandleScope(Register scratch);
-
   // Jump to a runtime routine.
   void JumpToRuntime(const ExternalReference& ext);
 
@@ -351,9 +346,6 @@ class MacroAssembler: public Assembler {
   void EnterFrame(StackFrame::Type type);
   void LeaveFrame(StackFrame::Type type);
 
-  void EnterExitFramePrologue(ExitFrame::Mode mode);
-  void EnterExitFrameEpilogue(ExitFrame::Mode mode, int argc);
-
   // Allocation support helpers.
   void LoadAllocationTopHelper(Register result,
                                Register result_end,
index 3e5fc047949328ccfcdd26ef812d4e1b26e5213b..ca4e142101dd263da8ec9d10d30c584fa2dead62 100644 (file)
@@ -776,39 +776,20 @@ void StubCompiler::GenerateLoadCallback(JSObject* object,
       CheckPrototypes(object, receiver, holder,
                       scratch1, scratch2, name, miss);
 
-  Handle<AccessorInfo> callback_handle(callback);
-
-  Register other = reg.is(scratch1) ? scratch2 : scratch1;
-  __ EnterInternalFrame();
-  __ PushHandleScope(other);
-  // Push the stack address where the list of arguments ends
-  __ mov(other, esp);
-  __ sub(Operand(other), Immediate(2 * kPointerSize));
-  __ push(other);
+  // Push the arguments on the JS stack of the caller.
+  __ pop(scratch2);  // remove return address
   __ push(receiver);  // receiver
   __ push(reg);  // holder
-  __ mov(other, Immediate(callback_handle));
-  __ push(other);
-  __ push(FieldOperand(other, AccessorInfo::kDataOffset));  // data
+  __ mov(reg, Immediate(Handle<AccessorInfo>(callback)));  // callback data
+  __ push(reg);
+  __ push(FieldOperand(reg, AccessorInfo::kDataOffset));
   __ push(name_reg);  // name
-  // Save a pointer to where we pushed the arguments pointer.
-  // This will be passed as the const Arguments& to the C++ callback.
-  __ mov(eax, esp);
-  __ add(Operand(eax), Immediate(5 * kPointerSize));
-  __ mov(ebx, esp);
-
-  // Do call through the api.
-  ASSERT_EQ(6, ApiGetterEntryStub::kStackSpace);
-  Address getter_address = v8::ToCData<Address>(callback->getter());
-  ApiFunction fun(getter_address);
-  ApiGetterEntryStub stub(callback_handle, &fun);
-  __ CallStub(&stub);
+  __ push(scratch2);  // restore return address
 
-  Register tmp = other.is(eax) ? reg : other;
-  __ PopHandleScope(tmp);
-  __ LeaveInternalFrame();
-
-  __ ret(0);
+  // Do tail-call to the runtime system.
+  ExternalReference load_callback_property =
+      ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
+  __ TailCallRuntime(load_callback_property, 5, 1);
 }
 
 
index 10ad2941a38a963e06dace9001c953c4455abbef..01881346e14761cf394b1af1fa2d890162bf3e81 100644 (file)
@@ -979,7 +979,6 @@ void AccessorInfo::AccessorInfoVerify() {
   VerifyPointer(name());
   VerifyPointer(data());
   VerifyPointer(flag());
-  VerifyPointer(load_stub_cache());
 }
 
 void AccessorInfo::AccessorInfoPrint() {
index 5907a86f69ac1ea395b2bd8353e5c6e84b868bcf..2350a35ba814f712a48c04b99ac0121207a9ede6 100644 (file)
@@ -2436,7 +2436,6 @@ ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
 ACCESSORS(AccessorInfo, data, Object, kDataOffset)
 ACCESSORS(AccessorInfo, name, Object, kNameOffset)
 ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
-ACCESSORS(AccessorInfo, load_stub_cache, Object, kLoadStubCacheOffset)
 
 ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
 ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
index 61bdf44af1beb51dc750533ff1b2446c95aa05ca..89cbd4463758e2e49c449c3d23ff1a1fe569b275 100644 (file)
@@ -4719,7 +4719,6 @@ class AccessorInfo: public Struct {
   DECL_ACCESSORS(data, Object)
   DECL_ACCESSORS(name, Object)
   DECL_ACCESSORS(flag, Smi)
-  DECL_ACCESSORS(load_stub_cache, Object)
 
   inline bool all_can_read();
   inline void set_all_can_read(bool value);
@@ -4745,8 +4744,7 @@ class AccessorInfo: public Struct {
   static const int kDataOffset = kSetterOffset + kPointerSize;
   static const int kNameOffset = kDataOffset + kPointerSize;
   static const int kFlagOffset = kNameOffset + kPointerSize;
-  static const int kLoadStubCacheOffset = kFlagOffset + kPointerSize;
-  static const int kSize = kLoadStubCacheOffset + kPointerSize;
+  static const int kSize = kFlagOffset + kPointerSize;
 
  private:
   // Bit positions in flag.
index 8ed13f239894c853cf3f46642fc2a0c22ba7052d..8fd62c986c103648e120c71d7f7eaa88dbc7e330 100644 (file)
@@ -4797,12 +4797,6 @@ static Object* Runtime_ReThrow(Arguments args) {
 }
 
 
-static Object* Runtime_PromoteScheduledException(Arguments args) {
-  ASSERT_EQ(0, args.length());
-  return Top::PromoteScheduledException();
-}
-
-
 static Object* Runtime_ThrowReferenceError(Arguments args) {
   HandleScope scope;
   ASSERT(args.length() == 1);
@@ -7764,13 +7758,6 @@ static Object* Runtime_Abort(Arguments args) {
 }
 
 
-static Object* Runtime_DeleteHandleScopeExtensions(Arguments args) {
-  ASSERT(args.length() == 0);
-  HandleScope::DeleteExtensions();
-  return Heap::undefined_value();
-}
-
-
 #ifdef DEBUG
 // ListNatives is ONLY used by the fuzz-natives.js in debug mode
 // Exclude the code in release mode.
index a55ef25011a1cf46df3ae9d9574400f055fd1b47..6b1ce480b5b459b5a73b6ce10246351b0a237ff8 100644 (file)
@@ -234,7 +234,6 @@ namespace internal {
   F(ReThrow, 1, 1) \
   F(ThrowReferenceError, 1, 1) \
   F(StackGuard, 1, 1) \
-  F(PromoteScheduledException, 0, 1) \
   \
   /* Contexts */ \
   F(NewContext, 1, 1) \
@@ -264,8 +263,6 @@ namespace internal {
   F(Log, 2, 1) \
   /* ES5 */ \
   F(LocalKeys, 1, 1) \
-  /* Handle scopes */ \
-  F(DeleteHandleScopeExtensions, 0, 1) \
   \
   /* Pseudo functions - handled as macros by parser */ \
   F(IS_VAR, 1, 1)
index a399e4563ee3bcdf9962bc3941f72fab1e55f112..e10dc61b2ca2512515a0b65ee534bc0d03267289 100644 (file)
@@ -735,16 +735,11 @@ Handle<Code> ComputeCallMiss(int argc) {
 
 
 Object* LoadCallbackProperty(Arguments args) {
-  ASSERT(args[0]->IsJSObject());
-  ASSERT(args[1]->IsJSObject());
   AccessorInfo* callback = AccessorInfo::cast(args[2]);
   Address getter_address = v8::ToCData<Address>(callback->getter());
   v8::AccessorGetter fun = FUNCTION_CAST<v8::AccessorGetter>(getter_address);
   ASSERT(fun != NULL);
-  CustomArguments custom_args(callback->data(),
-                              JSObject::cast(args[0]),
-                              JSObject::cast(args[1]));
-  v8::AccessorInfo info(custom_args.end());
+  v8::AccessorInfo info(args.arguments());
   HandleScope scope;
   v8::Handle<v8::Value> result;
   {
index 0f5aa27b2b4d1b328cda704a0b3a8189ce7945b0..ae94f08e3c9e2e8ce967f8874ec6508d9330815d 100644 (file)
--- a/src/top.h
+++ b/src/top.h
@@ -170,10 +170,6 @@ class Top {
     return &thread_local_.external_caught_exception_;
   }
 
-  static Object** scheduled_exception_address() {
-    return &thread_local_.scheduled_exception_;
-  }
-
   static Object* scheduled_exception() {
     ASSERT(has_scheduled_exception());
     return thread_local_.scheduled_exception_;
index 877cfdfb459f85e85c12bc24e594d3be4c8c560b..95f30d842d46230f1837bcd8c07b9dfb9e5e66bd 100644 (file)
@@ -6771,7 +6771,7 @@ void CEntryStub::GenerateCore(MacroAssembler* masm,
                               Label* throw_normal_exception,
                               Label* throw_termination_exception,
                               Label* throw_out_of_memory_exception,
-                              ExitFrame::Mode mode,
+                              StackFrame::Type frame_type,
                               bool do_gc,
                               bool always_allocate_scope) {
   // rax: result parameter for PerformGC, if any.
@@ -6854,7 +6854,7 @@ void CEntryStub::GenerateCore(MacroAssembler* masm,
   __ j(zero, &failure_returned);
 
   // Exit the JavaScript to C++ exit frame.
-  __ LeaveExitFrame(mode, result_size_);
+  __ LeaveExitFrame(frame_type, result_size_);
   __ ret(0);
 
   // Handling of failure.
@@ -6984,12 +6984,12 @@ void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
   // this by performing a garbage collection and retrying the
   // builtin once.
 
-  ExitFrame::Mode mode = is_debug_break ?
-      ExitFrame::MODE_DEBUG :
-      ExitFrame::MODE_NORMAL;
+  StackFrame::Type frame_type = is_debug_break ?
+      StackFrame::EXIT_DEBUG :
+      StackFrame::EXIT;
 
   // Enter the exit frame that transitions from JavaScript to C++.
-  __ EnterExitFrame(mode, result_size_);
+  __ EnterExitFrame(frame_type, result_size_);
 
   // rax: Holds the context at this point, but should not be used.
   //      On entry to code generated by GenerateCore, it must hold
@@ -7012,7 +7012,7 @@ void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
                &throw_normal_exception,
                &throw_termination_exception,
                &throw_out_of_memory_exception,
-               mode,
+               frame_type,
                false,
                false);
 
@@ -7021,7 +7021,7 @@ void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
                &throw_normal_exception,
                &throw_termination_exception,
                &throw_out_of_memory_exception,
-               mode,
+               frame_type,
                true,
                false);
 
@@ -7032,7 +7032,7 @@ void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
                &throw_normal_exception,
                &throw_termination_exception,
                &throw_out_of_memory_exception,
-               mode,
+               frame_type,
                true,
                true);
 
@@ -7047,11 +7047,6 @@ void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
 }
 
 
-void ApiGetterEntryStub::Generate(MacroAssembler* masm) {
-  UNREACHABLE();
-}
-
-
 void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
   Label invoke, exit;
 #ifdef ENABLE_LOGGING_AND_PROFILING
index 6a0527cf6d666025b0b84ad3ecb168d560bd7e43..fe224ad998823a58aee088bd9c43056904056e09 100644 (file)
@@ -57,7 +57,11 @@ StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) {
   state->sp = sp;
   state->pc_address = reinterpret_cast<Address*>(sp - 1 * kPointerSize);
   // Determine frame type.
-  return EXIT;
+  if (Memory::Address_at(fp + ExitFrameConstants::kDebugMarkOffset) != 0) {
+    return EXIT_DEBUG;
+  } else {
+    return EXIT;
+  }
 }
 
 int JavaScriptFrame::GetProvidedParametersCount() const {
@@ -65,10 +69,10 @@ int JavaScriptFrame::GetProvidedParametersCount() const {
 }
 
 
-void ExitFrame::Iterate(ObjectVisitor* v) const {
-  v->VisitPointer(&code_slot());
-  // The arguments are traversed as part of the expression stack of
-  // the calling frame.
+void ExitFrame::Iterate(ObjectVisitor* a) const {
+  // Exit frames on X64 do not contain any pointers. The arguments
+  // are traversed as part of the expression stack of the calling
+  // frame.
 }
 
 byte* InternalFrame::GetCallerStackPointer() const {
index a92b248d886f4ecc26608dc91d63baabea24af55..eefaa0aeb5c5185142c3a34fbaefe1af64f51c14 100644 (file)
@@ -63,7 +63,7 @@ class EntryFrameConstants : public AllStatic {
 
 class ExitFrameConstants : public AllStatic {
  public:
-  static const int kCodeOffset      = -2 * kPointerSize;
+  static const int kDebugMarkOffset = -2 * kPointerSize;
   static const int kSPOffset        = -1 * kPointerSize;
 
   static const int kCallerFPOffset  = +0 * kPointerSize;
index 6bf6e6a712959d6cd92c178c28b79181f26a6827..b2f69bb7a99de3047e2d9a0760793957f029fd10 100644 (file)
@@ -1787,7 +1787,9 @@ void MacroAssembler::LeaveFrame(StackFrame::Type type) {
 }
 
 
-void MacroAssembler::EnterExitFrame(ExitFrame::Mode mode, int result_size) {
+void MacroAssembler::EnterExitFrame(StackFrame::Type type, int result_size) {
+  ASSERT(type == StackFrame::EXIT || type == StackFrame::EXIT_DEBUG);
+
   // Setup the frame structure on the stack.
   // All constants are relative to the frame pointer of the exit frame.
   ASSERT(ExitFrameConstants::kCallerSPDisplacement == +2 * kPointerSize);
@@ -1799,12 +1801,7 @@ void MacroAssembler::EnterExitFrame(ExitFrame::Mode mode, int result_size) {
   // Reserve room for entry stack pointer and push the debug marker.
   ASSERT(ExitFrameConstants::kSPOffset == -1 * kPointerSize);
   push(Immediate(0));  // saved entry sp, patched before call
-  if (mode == ExitFrame::MODE_DEBUG) {
-    push(Immediate(0));
-  } else {
-    movq(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT);
-    push(kScratchRegister);
-  }
+  push(Immediate(type == StackFrame::EXIT_DEBUG ? 1 : 0));
 
   // Save the frame pointer and the context in top.
   ExternalReference c_entry_fp_address(Top::k_c_entry_fp_address);
@@ -1824,7 +1821,7 @@ void MacroAssembler::EnterExitFrame(ExitFrame::Mode mode, int result_size) {
 #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.
-  if (mode == ExitFrame::MODE_DEBUG) {
+  if (type == StackFrame::EXIT_DEBUG) {
     // TODO(1243899): This should be symmetric to
     // CopyRegistersFromStackToMemory() but it isn't! esp is assumed
     // correct here, but computed for the other call. Very error
@@ -1863,17 +1860,17 @@ void MacroAssembler::EnterExitFrame(ExitFrame::Mode mode, int result_size) {
 }
 
 
-void MacroAssembler::LeaveExitFrame(ExitFrame::Mode mode, int result_size) {
+void MacroAssembler::LeaveExitFrame(StackFrame::Type type, int result_size) {
   // Registers:
   // r15 : argv
 #ifdef ENABLE_DEBUGGER_SUPPORT
   // Restore the memory copy of the registers by digging them out from
   // the stack. This is needed to allow nested break points.
-  if (mode == ExitFrame::MODE_DEBUG) {
+  if (type == StackFrame::EXIT_DEBUG) {
     // It's okay to clobber register rbx below because we don't need
     // the function pointer after this.
     const int kCallerSavedSize = kNumJSCallerSaved * kPointerSize;
-    int kOffset = ExitFrameConstants::kCodeOffset - kCallerSavedSize;
+    int kOffset = ExitFrameConstants::kDebugMarkOffset - kCallerSavedSize;
     lea(rbx, Operand(rbp, kOffset));
     CopyRegistersFromStackToMemory(rbx, rcx, kJSCallerSaved);
   }
index 11cdfc3c4c6e27356f37d69777eab339a5cf30cc..4c2f35bd9ca72a5ccaac2779a5579c47cc8fcb71 100644 (file)
@@ -106,16 +106,16 @@ class MacroAssembler: public Assembler {
   void EnterConstructFrame() { EnterFrame(StackFrame::CONSTRUCT); }
   void LeaveConstructFrame() { LeaveFrame(StackFrame::CONSTRUCT); }
 
-  // Enter specific kind of exit frame; either in normal or
-  // debug mode. Expects the number of arguments in register rax and
+  // Enter specific kind of exit frame; either EXIT or
+  // EXIT_DEBUG. Expects the number of arguments in register rax and
   // sets up the number of arguments in register rdi and the pointer
   // to the first argument in register rsi.
-  void EnterExitFrame(ExitFrame::Mode mode, int result_size = 1);
+  void EnterExitFrame(StackFrame::Type type, int result_size = 1);
 
   // Leave the current exit frame. Expects/provides the return value in
   // register rax:rdx (untouched) and the pointer to the first
   // argument in register rsi.
-  void LeaveExitFrame(ExitFrame::Mode mode, int result_size = 1);
+  void LeaveExitFrame(StackFrame::Type type, int result_size = 1);
 
 
   // ---------------------------------------------------------------------------
index 9deefa554253f86615063480419a12724f2dc512..f041041c11ec551bfb56fc0d6543120531917e6c 100644 (file)
@@ -34,7 +34,6 @@ Import('context object_files')
 
 SOURCES = {
   'all': [
-    'test-accessors.cc',
     'test-alloc.cc',
     'test-api.cc',
     'test-ast.cc',
index f638ed480fb0b4a7e14306e229ed71df7d9e779c..82a33e6da5e23781e36440b59de47b02e34ff5a0 100644 (file)
@@ -121,6 +121,3 @@ int main(int argc, char* argv[]) {
   v8::V8::Dispose();
   return 0;
 }
-
-RegisterThreadedTest *RegisterThreadedTest::first_ = NULL;
-int RegisterThreadedTest::count_ = 0;
index 404b692b27480b62c3e7313b4b63a10f52edb7ae..a95645e010eabb82f3483bf26063e3d105492950 100644 (file)
@@ -28,8 +28,6 @@
 #ifndef CCTEST_H_
 #define CCTEST_H_
 
-#include "v8.h"
-
 #ifndef TEST
 #define TEST(Name)                                                       \
   static void Test##Name();                                              \
@@ -74,138 +72,4 @@ class CcTest {
   CcTest* prev_;
 };
 
-// Switches between all the Api tests using the threading support.
-// In order to get a surprising but repeatable pattern of thread
-// switching it has extra semaphores to control the order in which
-// the tests alternate, not relying solely on the big V8 lock.
-//
-// A test is augmented with calls to ApiTestFuzzer::Fuzz() in its
-// callbacks.  This will have no effect when we are not running the
-// thread fuzzing test.  In the thread fuzzing test it will
-// pseudorandomly select a successor thread and switch execution
-// to that thread, suspending the current test.
-class ApiTestFuzzer: public v8::internal::Thread {
- public:
-  void CallTest();
-  explicit ApiTestFuzzer(int num)
-      : test_number_(num),
-        gate_(v8::internal::OS::CreateSemaphore(0)),
-        active_(true) {
-  }
-  ~ApiTestFuzzer() { delete gate_; }
-
-  // The ApiTestFuzzer is also a Thread, so it has a Run method.
-  virtual void Run();
-
-  enum PartOfTest { FIRST_PART, SECOND_PART };
-
-  static void Setup(PartOfTest part);
-  static void RunAllTests();
-  static void TearDown();
-  // This method switches threads if we are running the Threading test.
-  // Otherwise it does nothing.
-  static void Fuzz();
- private:
-  static bool fuzzing_;
-  static int tests_being_run_;
-  static int current_;
-  static int active_tests_;
-  static bool NextThread();
-  int test_number_;
-  v8::internal::Semaphore* gate_;
-  bool active_;
-  void ContextSwitch();
-  static int GetNextTestNumber();
-  static v8::internal::Semaphore* all_tests_done_;
-};
-
-
-#define THREADED_TEST(Name)                                          \
-  static void Test##Name();                                          \
-  RegisterThreadedTest register_##Name(Test##Name, #Name);           \
-  /* */ TEST(Name)
-
-
-class RegisterThreadedTest {
- public:
-  explicit RegisterThreadedTest(CcTest::TestFunction* callback,
-                                const char* name)
-      : fuzzer_(NULL), callback_(callback), name_(name) {
-    prev_ = first_;
-    first_ = this;
-    count_++;
-  }
-  static int count() { return count_; }
-  static RegisterThreadedTest* nth(int i) {
-    CHECK(i < count());
-    RegisterThreadedTest* current = first_;
-    while (i > 0) {
-      i--;
-      current = current->prev_;
-    }
-    return current;
-  }
-  CcTest::TestFunction* callback() { return callback_; }
-  ApiTestFuzzer* fuzzer_;
-  const char* name() { return name_; }
-
- private:
-  static RegisterThreadedTest* first_;
-  static int count_;
-  CcTest::TestFunction* callback_;
-  RegisterThreadedTest* prev_;
-  const char* name_;
-};
-
-
-// A LocalContext holds a reference to a v8::Context.
-class LocalContext {
- public:
-  LocalContext(v8::ExtensionConfiguration* extensions = 0,
-               v8::Handle<v8::ObjectTemplate> global_template =
-                   v8::Handle<v8::ObjectTemplate>(),
-               v8::Handle<v8::Value> global_object = v8::Handle<v8::Value>())
-    : context_(v8::Context::New(extensions, global_template, global_object)) {
-    context_->Enter();
-  }
-
-  virtual ~LocalContext() {
-    context_->Exit();
-    context_.Dispose();
-  }
-
-  v8::Context* operator->() { return *context_; }
-  v8::Context* operator*() { return *context_; }
-  bool IsReady() { return !context_.IsEmpty(); }
-
-  v8::Local<v8::Context> local() {
-    return v8::Local<v8::Context>::New(context_);
-  }
-
- private:
-  v8::Persistent<v8::Context> context_;
-};
-
-
-static inline v8::Local<v8::Value> v8_num(double x) {
-  return v8::Number::New(x);
-}
-
-
-static inline v8::Local<v8::String> v8_str(const char* x) {
-  return v8::String::New(x);
-}
-
-
-static inline v8::Local<v8::Script> v8_compile(const char* x) {
-  return v8::Script::Compile(v8_str(x));
-}
-
-
-// Helper function that compiles and runs the source.
-static inline v8::Local<v8::Value> CompileRun(const char* source) {
-  return v8::Script::Compile(v8::String::New(source))->Run();
-}
-
-
 #endif  // ifndef CCTEST_H_
diff --git a/test/cctest/test-accessors.cc b/test/cctest/test-accessors.cc
deleted file mode 100644 (file)
index b56238a..0000000
+++ /dev/null
@@ -1,424 +0,0 @@
-// Copyright 2009 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-//       notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-//       copyright notice, this list of conditions and the following
-//       disclaimer in the documentation and/or other materials provided
-//       with the distribution.
-//     * Neither the name of Google Inc. nor the names of its
-//       contributors may be used to endorse or promote products derived
-//       from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include <stdlib.h>
-
-#include "v8.h"
-
-#include "api.h"
-#include "cctest.h"
-#include "frames-inl.h"
-#include "string-stream.h"
-
-using ::v8::ObjectTemplate;
-using ::v8::Value;
-using ::v8::Context;
-using ::v8::Local;
-using ::v8::String;
-using ::v8::Script;
-using ::v8::Function;
-using ::v8::AccessorInfo;
-using ::v8::Extension;
-
-namespace i = ::v8::internal;
-
-static v8::Handle<Value> handle_property(Local<String> name,
-                                         const AccessorInfo&) {
-  ApiTestFuzzer::Fuzz();
-  return v8_num(900);
-}
-
-
-THREADED_TEST(PropertyHandler) {
-  v8::HandleScope scope;
-  Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
-  fun_templ->InstanceTemplate()->SetAccessor(v8_str("foo"), handle_property);
-  LocalContext env;
-  Local<Function> fun = fun_templ->GetFunction();
-  env->Global()->Set(v8_str("Fun"), fun);
-  Local<Script> getter = v8_compile("var obj = new Fun(); obj.foo;");
-  CHECK_EQ(900, getter->Run()->Int32Value());
-  Local<Script> setter = v8_compile("obj.foo = 901;");
-  CHECK_EQ(901, setter->Run()->Int32Value());
-}
-
-
-static v8::Handle<Value> GetIntValue(Local<String> property,
-                                     const AccessorInfo& info) {
-  ApiTestFuzzer::Fuzz();
-  int* value =
-      static_cast<int*>(v8::Handle<v8::External>::Cast(info.Data())->Value());
-  return v8_num(*value);
-}
-
-
-static void SetIntValue(Local<String> property,
-                        Local<Value> value,
-                        const AccessorInfo& info) {
-  int* field =
-      static_cast<int*>(v8::Handle<v8::External>::Cast(info.Data())->Value());
-  *field = value->Int32Value();
-}
-
-int foo, bar, baz;
-
-THREADED_TEST(GlobalVariableAccess) {
-  foo = 0;
-  bar = -4;
-  baz = 10;
-  v8::HandleScope scope;
-  v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
-  templ->InstanceTemplate()->SetAccessor(v8_str("foo"),
-                                         GetIntValue,
-                                         SetIntValue,
-                                         v8::External::New(&foo));
-  templ->InstanceTemplate()->SetAccessor(v8_str("bar"),
-                                         GetIntValue,
-                                         SetIntValue,
-                                         v8::External::New(&bar));
-  templ->InstanceTemplate()->SetAccessor(v8_str("baz"),
-                                         GetIntValue,
-                                         SetIntValue,
-                                         v8::External::New(&baz));
-  LocalContext env(0, templ->InstanceTemplate());
-  v8_compile("foo = (++bar) + baz")->Run();
-  CHECK_EQ(bar, -3);
-  CHECK_EQ(foo, 7);
-}
-
-
-static int x_register = 0;
-static v8::Handle<v8::Object> x_receiver;
-static v8::Handle<v8::Object> x_holder;
-
-
-static v8::Handle<Value> XGetter(Local<String> name, const AccessorInfo& info) {
-  ApiTestFuzzer::Fuzz();
-  CHECK_EQ(x_receiver, info.This());
-  CHECK_EQ(x_holder, info.Holder());
-  return v8_num(x_register);
-}
-
-
-static void XSetter(Local<String> name,
-                    Local<Value> value,
-                    const AccessorInfo& info) {
-  CHECK_EQ(x_holder, info.This());
-  CHECK_EQ(x_holder, info.Holder());
-  x_register = value->Int32Value();
-}
-
-
-THREADED_TEST(AccessorIC) {
-  v8::HandleScope scope;
-  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
-  obj->SetAccessor(v8_str("x"), XGetter, XSetter);
-  LocalContext context;
-  x_holder = obj->NewInstance();
-  context->Global()->Set(v8_str("holder"), x_holder);
-  x_receiver = v8::Object::New();
-  context->Global()->Set(v8_str("obj"), x_receiver);
-  v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(CompileRun(
-    "obj.__proto__ = holder;"
-    "var result = [];"
-    "for (var i = 0; i < 10; i++) {"
-    "  holder.x = i;"
-    "  result.push(obj.x);"
-    "}"
-    "result"));
-  CHECK_EQ(10, array->Length());
-  for (int i = 0; i < 10; i++) {
-    v8::Handle<Value> entry = array->Get(v8::Integer::New(i));
-    CHECK_EQ(v8::Integer::New(i), entry);
-  }
-}
-
-
-static v8::Handle<Value> AccessorProhibitsOverwritingGetter(
-    Local<String> name,
-    const AccessorInfo& info) {
-  ApiTestFuzzer::Fuzz();
-  return v8::True();
-}
-
-
-THREADED_TEST(AccessorProhibitsOverwriting) {
-  v8::HandleScope scope;
-  LocalContext context;
-  Local<ObjectTemplate> templ = ObjectTemplate::New();
-  templ->SetAccessor(v8_str("x"),
-                     AccessorProhibitsOverwritingGetter,
-                     0,
-                     v8::Handle<Value>(),
-                     v8::PROHIBITS_OVERWRITING,
-                     v8::ReadOnly);
-  Local<v8::Object> instance = templ->NewInstance();
-  context->Global()->Set(v8_str("obj"), instance);
-  Local<Value> value = CompileRun(
-      "obj.__defineGetter__('x', function() { return false; });"
-      "obj.x");
-  CHECK(value->BooleanValue());
-  value = CompileRun(
-      "var setter_called = false;"
-      "obj.__defineSetter__('x', function() { setter_called = true; });"
-      "obj.x = 42;"
-      "setter_called");
-  CHECK(!value->BooleanValue());
-  value = CompileRun(
-      "obj2 = {};"
-      "obj2.__proto__ = obj;"
-      "obj2.__defineGetter__('x', function() { return false; });"
-      "obj2.x");
-  CHECK(value->BooleanValue());
-  value = CompileRun(
-      "var setter_called = false;"
-      "obj2 = {};"
-      "obj2.__proto__ = obj;"
-      "obj2.__defineSetter__('x', function() { setter_called = true; });"
-      "obj2.x = 42;"
-      "setter_called");
-  CHECK(!value->BooleanValue());
-}
-
-
-template <int C>
-static v8::Handle<Value> HandleAllocatingGetter(Local<String> name,
-                                                const AccessorInfo& info) {
-  ApiTestFuzzer::Fuzz();
-  for (int i = 0; i < C; i++)
-    v8::String::New("foo");
-  return v8::String::New("foo");
-}
-
-
-THREADED_TEST(HandleScopePop) {
-  v8::HandleScope scope;
-  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
-  obj->SetAccessor(v8_str("one"), HandleAllocatingGetter<1>);
-  obj->SetAccessor(v8_str("many"), HandleAllocatingGetter<1024>);
-  LocalContext context;
-  v8::Handle<v8::Object> inst = obj->NewInstance();
-  context->Global()->Set(v8::String::New("obj"), inst);
-  int count_before = i::HandleScope::NumberOfHandles();
-  {
-    v8::HandleScope scope;
-    CompileRun(
-        "for (var i = 0; i < 1000; i++) {"
-        "  obj.one;"
-        "  obj.many;"
-        "}");
-  }
-  int count_after = i::HandleScope::NumberOfHandles();
-  CHECK_EQ(count_before, count_after);
-}
-
-static v8::Handle<Value> CheckAccessorArgsCorrect(Local<String> name,
-                                                  const AccessorInfo& info) {
-  CHECK(info.This() == info.Holder());
-  CHECK(info.Data()->Equals(v8::String::New("data")));
-  ApiTestFuzzer::Fuzz();
-  CHECK(info.This() == info.Holder());
-  CHECK(info.Data()->Equals(v8::String::New("data")));
-  i::Heap::CollectAllGarbage(true);
-  CHECK(info.This() == info.Holder());
-  CHECK(info.Data()->Equals(v8::String::New("data")));
-  return v8::Integer::New(17);
-}
-
-THREADED_TEST(DirectCall) {
-  v8::HandleScope scope;
-  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
-  obj->SetAccessor(v8_str("xxx"),
-                   CheckAccessorArgsCorrect,
-                   NULL,
-                   v8::String::New("data"));
-  LocalContext context;
-  v8::Handle<v8::Object> inst = obj->NewInstance();
-  context->Global()->Set(v8::String::New("obj"), inst);
-  Local<Script> scr = v8::Script::Compile(v8::String::New("obj.xxx"));
-  for (int i = 0; i < 10; i++) {
-    Local<Value> result = scr->Run();
-    CHECK(!result.IsEmpty());
-    CHECK_EQ(17, result->Int32Value());
-  }
-}
-
-static v8::Handle<Value> EmptyGetter(Local<String> name,
-                                     const AccessorInfo& info) {
-  CheckAccessorArgsCorrect(name, info);
-  ApiTestFuzzer::Fuzz();
-  CheckAccessorArgsCorrect(name, info);
-  return v8::Handle<v8::Value>();
-}
-
-THREADED_TEST(EmptyResult) {
-  v8::HandleScope scope;
-  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
-  obj->SetAccessor(v8_str("xxx"), EmptyGetter, NULL, v8::String::New("data"));
-  LocalContext context;
-  v8::Handle<v8::Object> inst = obj->NewInstance();
-  context->Global()->Set(v8::String::New("obj"), inst);
-  Local<Script> scr = v8::Script::Compile(v8::String::New("obj.xxx"));
-  for (int i = 0; i < 10; i++) {
-    Local<Value> result = scr->Run();
-    CHECK(result == v8::Undefined());
-  }
-}
-
-
-THREADED_TEST(NoReuseRegress) {
-  // Check that the IC generated for the one test doesn't get reused
-  // for the other.
-  v8::HandleScope scope;
-  {
-    v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
-    obj->SetAccessor(v8_str("xxx"), EmptyGetter, NULL, v8::String::New("data"));
-    LocalContext context;
-    v8::Handle<v8::Object> inst = obj->NewInstance();
-    context->Global()->Set(v8::String::New("obj"), inst);
-    Local<Script> scr = v8::Script::Compile(v8::String::New("obj.xxx"));
-    for (int i = 0; i < 2; i++) {
-      Local<Value> result = scr->Run();
-      CHECK(result == v8::Undefined());
-    }
-  }
-  {
-    v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
-    obj->SetAccessor(v8_str("xxx"),
-                     CheckAccessorArgsCorrect,
-                     NULL,
-                     v8::String::New("data"));
-    LocalContext context;
-    v8::Handle<v8::Object> inst = obj->NewInstance();
-    context->Global()->Set(v8::String::New("obj"), inst);
-    Local<Script> scr = v8::Script::Compile(v8::String::New("obj.xxx"));
-    for (int i = 0; i < 10; i++) {
-      Local<Value> result = scr->Run();
-      CHECK(!result.IsEmpty());
-      CHECK_EQ(17, result->Int32Value());
-    }
-  }
-}
-
-static v8::Handle<Value> ThrowingGetAccessor(Local<String> name,
-                                             const AccessorInfo& info) {
-  ApiTestFuzzer::Fuzz();
-  return v8::ThrowException(v8_str("g"));
-}
-
-
-static void ThrowingSetAccessor(Local<String> name,
-                                Local<Value> value,
-                                const AccessorInfo& info) {
-  v8::ThrowException(value);
-}
-
-
-THREADED_TEST(Regress1054726) {
-  v8::HandleScope scope;
-  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
-  obj->SetAccessor(v8_str("x"),
-                   ThrowingGetAccessor,
-                   ThrowingSetAccessor,
-                   Local<Value>());
-
-  LocalContext env;
-  env->Global()->Set(v8_str("obj"), obj->NewInstance());
-
-  // Use the throwing property setter/getter in a loop to force
-  // the accessor ICs to be initialized.
-  v8::Handle<Value> result;
-  result = Script::Compile(v8_str(
-      "var result = '';"
-      "for (var i = 0; i < 5; i++) {"
-      "  try { obj.x; } catch (e) { result += e; }"
-      "}; result"))->Run();
-  CHECK_EQ(v8_str("ggggg"), result);
-
-  result = Script::Compile(String::New(
-      "var result = '';"
-      "for (var i = 0; i < 5; i++) {"
-      "  try { obj.x = i; } catch (e) { result += e; }"
-      "}; result"))->Run();
-  CHECK_EQ(v8_str("01234"), result);
-}
-
-
-static v8::Handle<Value> AllocGetter(Local<String> name,
-                                     const AccessorInfo& info) {
-  ApiTestFuzzer::Fuzz();
-  return v8::Array::New(1000);
-}
-
-
-THREADED_TEST(Gc) {
-  v8::HandleScope scope;
-  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
-  obj->SetAccessor(v8_str("xxx"), AllocGetter);
-  LocalContext env;
-  env->Global()->Set(v8_str("obj"), obj->NewInstance());
-  Script::Compile(String::New(
-      "var last = [];"
-      "for (var i = 0; i < 2048; i++) {"
-      "  var result = obj.xxx;"
-      "  result[0] = last;"
-      "  last = result;"
-      "}"))->Run();
-}
-
-
-static v8::Handle<Value> StackCheck(Local<String> name,
-                                    const AccessorInfo& info) {
-  i::StackFrameIterator iter;
-  for (int i = 0; !iter.done(); i++) {
-    i::StackFrame* frame = iter.frame();
-    CHECK(i != 0 || (frame->type() == i::StackFrame::EXIT));
-    CHECK(frame->code()->IsCode());
-    i::Address pc = frame->pc();
-    i::Code* code = frame->code();
-    CHECK(code->contains(pc));
-    iter.Advance();
-  }
-  return v8::Undefined();
-}
-
-
-THREADED_TEST(StackIteration) {
-  v8::HandleScope scope;
-  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
-  i::StringStream::ClearMentionedObjectCache();
-  obj->SetAccessor(v8_str("xxx"), StackCheck);
-  LocalContext env;
-  env->Global()->Set(v8_str("obj"), obj->NewInstance());
-  Script::Compile(String::New(
-      "function foo() {"
-      "  return obj.xxx;"
-      "}"
-      "for (var i = 0; i < 100; i++) {"
-      "  foo();"
-      "}"))->Run();
-}
index 83038ae1a73087223a6d0fb782fbff3633a6af76..1d4b2c34c3f5155ea2dc83a11ceae0f9c21c86bf 100644 (file)
@@ -38,8 +38,6 @@
 #include "utils.h"
 #include "cctest.h"
 
-static const bool kLogThreading = false;
-
 static bool IsNaN(double x) {
 #ifdef WIN32
   return _isnan(x);
@@ -60,6 +58,131 @@ using ::v8::Extension;
 
 namespace i = ::v8::internal;
 
+static Local<Value> v8_num(double x) {
+  return v8::Number::New(x);
+}
+
+
+static Local<String> v8_str(const char* x) {
+  return String::New(x);
+}
+
+
+static Local<Script> v8_compile(const char* x) {
+  return Script::Compile(v8_str(x));
+}
+
+
+// A LocalContext holds a reference to a v8::Context.
+class LocalContext {
+ public:
+  LocalContext(v8::ExtensionConfiguration* extensions = 0,
+               v8::Handle<ObjectTemplate> global_template =
+                   v8::Handle<ObjectTemplate>(),
+               v8::Handle<Value> global_object = v8::Handle<Value>())
+    : context_(Context::New(extensions, global_template, global_object)) {
+    context_->Enter();
+  }
+
+  virtual ~LocalContext() {
+    context_->Exit();
+    context_.Dispose();
+  }
+
+  Context* operator->() { return *context_; }
+  Context* operator*() { return *context_; }
+  Local<Context> local() { return Local<Context>::New(context_); }
+  bool IsReady() { return !context_.IsEmpty(); }
+
+ private:
+  v8::Persistent<Context> context_;
+};
+
+
+// Switches between all the Api tests using the threading support.
+// In order to get a surprising but repeatable pattern of thread
+// switching it has extra semaphores to control the order in which
+// the tests alternate, not relying solely on the big V8 lock.
+//
+// A test is augmented with calls to ApiTestFuzzer::Fuzz() in its
+// callbacks.  This will have no effect when we are not running the
+// thread fuzzing test.  In the thread fuzzing test it will
+// pseudorandomly select a successor thread and switch execution
+// to that thread, suspending the current test.
+class ApiTestFuzzer: public v8::internal::Thread {
+ public:
+  void CallTest();
+  explicit ApiTestFuzzer(int num)
+      : test_number_(num),
+        gate_(v8::internal::OS::CreateSemaphore(0)),
+        active_(true) {
+  }
+  ~ApiTestFuzzer() { delete gate_; }
+
+  // The ApiTestFuzzer is also a Thread, so it has a Run method.
+  virtual void Run();
+
+  enum PartOfTest { FIRST_PART, SECOND_PART };
+
+  static void Setup(PartOfTest part);
+  static void RunAllTests();
+  static void TearDown();
+  // This method switches threads if we are running the Threading test.
+  // Otherwise it does nothing.
+  static void Fuzz();
+ private:
+  static bool fuzzing_;
+  static int tests_being_run_;
+  static int current_;
+  static int active_tests_;
+  static bool NextThread();
+  int test_number_;
+  v8::internal::Semaphore* gate_;
+  bool active_;
+  void ContextSwitch();
+  static int GetNextTestNumber();
+  static v8::internal::Semaphore* all_tests_done_;
+};
+
+
+#define THREADED_TEST(Name)                                          \
+  static void Test##Name();                                          \
+  RegisterThreadedTest register_##Name(Test##Name);                  \
+  /* */ TEST(Name)
+
+
+class RegisterThreadedTest {
+ public:
+  explicit RegisterThreadedTest(CcTest::TestFunction* callback)
+      : fuzzer_(NULL), callback_(callback) {
+    prev_ = first_;
+    first_ = this;
+    count_++;
+  }
+  static int count() { return count_; }
+  static RegisterThreadedTest* nth(int i) {
+    CHECK(i < count());
+    RegisterThreadedTest* current = first_;
+    while (i > 0) {
+      i--;
+      current = current->prev_;
+    }
+    return current;
+  }
+  CcTest::TestFunction* callback() { return callback_; }
+  ApiTestFuzzer* fuzzer_;
+
+ private:
+  static RegisterThreadedTest* first_;
+  static int count_;
+  CcTest::TestFunction* callback_;
+  RegisterThreadedTest* prev_;
+};
+
+
+RegisterThreadedTest *RegisterThreadedTest::first_ = NULL;
+int RegisterThreadedTest::count_ = 0;
+
 
 static int signature_callback_count;
 static v8::Handle<Value> IncrementingSignatureCallback(
@@ -108,6 +231,11 @@ THREADED_TEST(Handles) {
 }
 
 
+// Helper function that compiles and runs the source.
+static Local<Value> CompileRun(const char* source) {
+  return Script::Compile(String::New(source))->Run();
+}
+
 THREADED_TEST(ReceiverSignature) {
   v8::HandleScope scope;
   LocalContext env;
@@ -592,6 +720,27 @@ THREADED_TEST(FindInstanceInPrototypeChain) {
 }
 
 
+static v8::Handle<Value> handle_property(Local<String> name,
+                                         const AccessorInfo&) {
+  ApiTestFuzzer::Fuzz();
+  return v8_num(900);
+}
+
+
+THREADED_TEST(PropertyHandler) {
+  v8::HandleScope scope;
+  Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
+  fun_templ->InstanceTemplate()->SetAccessor(v8_str("foo"), handle_property);
+  LocalContext env;
+  Local<Function> fun = fun_templ->GetFunction();
+  env->Global()->Set(v8_str("Fun"), fun);
+  Local<Script> getter = v8_compile("var obj = new Fun(); obj.foo;");
+  CHECK_EQ(900, getter->Run()->Int32Value());
+  Local<Script> setter = v8_compile("obj.foo = 901;");
+  CHECK_EQ(901, setter->Run()->Int32Value());
+}
+
+
 THREADED_TEST(TinyInteger) {
   v8::HandleScope scope;
   LocalContext env;
@@ -758,6 +907,49 @@ THREADED_TEST(GlobalPrototype) {
 }
 
 
+static v8::Handle<Value> GetIntValue(Local<String> property,
+                                     const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  int* value =
+      static_cast<int*>(v8::Handle<v8::External>::Cast(info.Data())->Value());
+  return v8_num(*value);
+}
+
+static void SetIntValue(Local<String> property,
+                        Local<Value> value,
+                        const AccessorInfo& info) {
+  int* field =
+      static_cast<int*>(v8::Handle<v8::External>::Cast(info.Data())->Value());
+  *field = value->Int32Value();
+}
+
+int foo, bar, baz;
+
+THREADED_TEST(GlobalVariableAccess) {
+  foo = 0;
+  bar = -4;
+  baz = 10;
+  v8::HandleScope scope;
+  v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
+  templ->InstanceTemplate()->SetAccessor(v8_str("foo"),
+                                         GetIntValue,
+                                         SetIntValue,
+                                         v8::External::New(&foo));
+  templ->InstanceTemplate()->SetAccessor(v8_str("bar"),
+                                         GetIntValue,
+                                         SetIntValue,
+                                         v8::External::New(&bar));
+  templ->InstanceTemplate()->SetAccessor(v8_str("baz"),
+                                         GetIntValue,
+                                         SetIntValue,
+                                         v8::External::New(&baz));
+  LocalContext env(0, templ->InstanceTemplate());
+  v8_compile("foo = (++bar) + baz")->Run();
+  CHECK_EQ(bar, -3);
+  CHECK_EQ(foo, 7);
+}
+
+
 THREADED_TEST(ObjectTemplate) {
   v8::HandleScope scope;
   Local<ObjectTemplate> templ1 = ObjectTemplate::New();
@@ -1173,6 +1365,50 @@ THREADED_TEST(CallbackExceptionRegression) {
 }
 
 
+static v8::Handle<Value> ThrowingGetAccessor(Local<String> name,
+                                             const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  return v8::ThrowException(v8_str("g"));
+}
+
+
+static void ThrowingSetAccessor(Local<String> name,
+                                Local<Value> value,
+                                const AccessorInfo& info) {
+  v8::ThrowException(value);
+}
+
+
+THREADED_TEST(Regress1054726) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
+  obj->SetAccessor(v8_str("x"),
+                   ThrowingGetAccessor,
+                   ThrowingSetAccessor,
+                   Local<Value>());
+
+  LocalContext env;
+  env->Global()->Set(v8_str("obj"), obj->NewInstance());
+
+  // Use the throwing property setter/getter in a loop to force
+  // the accessor ICs to be initialized.
+  v8::Handle<Value> result;
+  result = Script::Compile(v8_str(
+      "var result = '';"
+      "for (var i = 0; i < 5; i++) {"
+      "  try { obj.x; } catch (e) { result += e; }"
+      "}; result"))->Run();
+  CHECK_EQ(v8_str("ggggg"), result);
+
+  result = Script::Compile(String::New(
+      "var result = '';"
+      "for (var i = 0; i < 5; i++) {"
+      "  try { obj.x = i; } catch (e) { result += e; }"
+      "}; result"))->Run();
+  CHECK_EQ(v8_str("01234"), result);
+}
+
+
 THREADED_TEST(FunctionPrototype) {
   v8::HandleScope scope;
   Local<v8::FunctionTemplate> Foo = v8::FunctionTemplate::New();
@@ -2948,6 +3184,53 @@ THREADED_TEST(Arguments) {
 }
 
 
+static int x_register = 0;
+static v8::Handle<v8::Object> x_receiver;
+static v8::Handle<v8::Object> x_holder;
+
+
+static v8::Handle<Value> XGetter(Local<String> name, const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  CHECK_EQ(x_receiver, info.This());
+  CHECK_EQ(x_holder, info.Holder());
+  return v8_num(x_register);
+}
+
+
+static void XSetter(Local<String> name,
+                    Local<Value> value,
+                    const AccessorInfo& info) {
+  CHECK_EQ(x_holder, info.This());
+  CHECK_EQ(x_holder, info.Holder());
+  x_register = value->Int32Value();
+}
+
+
+THREADED_TEST(AccessorIC) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
+  obj->SetAccessor(v8_str("x"), XGetter, XSetter);
+  LocalContext context;
+  x_holder = obj->NewInstance();
+  context->Global()->Set(v8_str("holder"), x_holder);
+  x_receiver = v8::Object::New();
+  context->Global()->Set(v8_str("obj"), x_receiver);
+  v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(CompileRun(
+    "obj.__proto__ = holder;"
+    "var result = [];"
+    "for (var i = 0; i < 10; i++) {"
+    "  holder.x = i;"
+    "  result.push(obj.x);"
+    "}"
+    "result"));
+  CHECK_EQ(10, array->Length());
+  for (int i = 0; i < 10; i++) {
+    v8::Handle<Value> entry = array->Get(v8::Integer::New(i));
+    CHECK_EQ(v8::Integer::New(i), entry);
+  }
+}
+
+
 static v8::Handle<Value> NoBlockGetterX(Local<String> name,
                                         const AccessorInfo&) {
   return v8::Handle<Value>();
@@ -5811,17 +6094,13 @@ void ApiTestFuzzer::Fuzz() {
 // not start immediately.
 bool ApiTestFuzzer::NextThread() {
   int test_position = GetNextTestNumber();
-  const char* test_name = RegisterThreadedTest::nth(current_)->name();
+  int test_number = RegisterThreadedTest::nth(current_)->fuzzer_->test_number_;
   if (test_position == current_) {
-    if (kLogThreading)
-      printf("Stay with %s\n", test_name);
+    printf("Stay with %d\n", test_number);
     return false;
   }
-  if (kLogThreading) {
-    printf("Switch from %s to %s\n",
-           test_name,
-           RegisterThreadedTest::nth(test_position)->name());
-  }
+  printf("Switch from %d to %d\n",
+         current_ < 0 ? 0 : test_number, test_position < 0 ? 0 : test_number);
   current_ = test_position;
   RegisterThreadedTest::nth(current_)->fuzzer_->gate_->Signal();
   return true;
@@ -5930,11 +6209,9 @@ TEST(Threading2) {
 
 
 void ApiTestFuzzer::CallTest() {
-  if (kLogThreading)
-    printf("Start test %d\n", test_number_);
+  printf("Start test %d\n", test_number_);
   CallTestNumber(test_number_);
-  if (kLogThreading)
-    printf("End test %d\n", test_number_);
+  printf("End test %d\n", test_number_);
 }
 
 
@@ -6422,6 +6699,53 @@ THREADED_TEST(PropertyEnumeration) {
 }
 
 
+static v8::Handle<Value> AccessorProhibitsOverwritingGetter(
+    Local<String> name,
+    const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  return v8::True();
+}
+
+
+THREADED_TEST(AccessorProhibitsOverwriting) {
+  v8::HandleScope scope;
+  LocalContext context;
+  Local<ObjectTemplate> templ = ObjectTemplate::New();
+  templ->SetAccessor(v8_str("x"),
+                     AccessorProhibitsOverwritingGetter,
+                     0,
+                     v8::Handle<Value>(),
+                     v8::PROHIBITS_OVERWRITING,
+                     v8::ReadOnly);
+  Local<v8::Object> instance = templ->NewInstance();
+  context->Global()->Set(v8_str("obj"), instance);
+  Local<Value> value = CompileRun(
+      "obj.__defineGetter__('x', function() { return false; });"
+      "obj.x");
+  CHECK(value->BooleanValue());
+  value = CompileRun(
+      "var setter_called = false;"
+      "obj.__defineSetter__('x', function() { setter_called = true; });"
+      "obj.x = 42;"
+      "setter_called");
+  CHECK(!value->BooleanValue());
+  value = CompileRun(
+      "obj2 = {};"
+      "obj2.__proto__ = obj;"
+      "obj2.__defineGetter__('x', function() { return false; });"
+      "obj2.x");
+  CHECK(value->BooleanValue());
+  value = CompileRun(
+      "var setter_called = false;"
+      "obj2 = {};"
+      "obj2.__proto__ = obj;"
+      "obj2.__defineSetter__('x', function() { setter_called = true; });"
+      "obj2.x = 42;"
+      "setter_called");
+  CHECK(!value->BooleanValue());
+}
+
+
 static bool NamedSetAccessBlocker(Local<v8::Object> obj,
                                   Local<Value> name,
                                   v8::AccessType type,
index 656a456faa09d3c602da284225347bb18cc3df34..4ffcee3dbf64125c08e379e40a928f565f4b348d 100644 (file)
@@ -178,6 +178,12 @@ static v8::Local<v8::Function> CompileFunction(const char* source,
 }
 
 
+// Helper function that compiles and runs the source.
+static v8::Local<v8::Value> CompileRun(const char* source) {
+  return v8::Script::Compile(v8::String::New(source))->Run();
+}
+
+
 // Is there any debug info for the function?
 static bool HasDebugInfo(v8::Handle<v8::Function> fun) {
   Handle<v8::internal::JSFunction> f = v8::Utils::OpenHandle(*fun);
index 68cbc26191c1ed8628e0ea9999f70d16dadf3710..39f90647e35ee0b03ceda753e653d0ce25eed115 100644 (file)
@@ -163,6 +163,11 @@ v8::Handle<v8::Value> TraceExtension::JSEntrySP(const v8::Arguments& args) {
 }
 
 
+static void CompileRun(const char* source) {
+  Script::Compile(String::New(source))->Run();
+}
+
+
 v8::Handle<v8::Value> TraceExtension::JSEntrySPLevel2(
     const v8::Arguments& args) {
   v8::HandleScope scope;
index f495c727872a040043dc53b96698d17db5473eb6..cdf58a559aecd45f7aed223314e8af939f885462 100644 (file)
@@ -129,9 +129,7 @@ var knownProblems = {
   "Log": true,
   "DeclareGlobals": true,
 
-  "CollectStackTrace": true,
-  "PromoteScheduledException": true,
-  "DeleteHandleScopeExtensions": true
+  "CollectStackTrace": true
 };
 
 var currentlyUncallable = {