Author: [EMAIL PROTECTED]
Date: Thu Nov 20 01:17:38 2008
New Revision: 798

Modified:
    branches/experimental/regexp2000/ChangeLog
    branches/experimental/regexp2000/include/v8.h
    branches/experimental/regexp2000/src/api.cc
    branches/experimental/regexp2000/src/ast.h
    branches/experimental/regexp2000/src/builtins-arm.cc
    branches/experimental/regexp2000/src/codegen-arm.h
    branches/experimental/regexp2000/src/codegen-ia32.cc
    branches/experimental/regexp2000/src/codegen-ia32.h
    branches/experimental/regexp2000/src/codegen.cc
    branches/experimental/regexp2000/src/codegen.h
    branches/experimental/regexp2000/src/compiler.cc
    branches/experimental/regexp2000/src/compiler.h
    branches/experimental/regexp2000/src/debug-delay.js
    branches/experimental/regexp2000/src/debug.cc
    branches/experimental/regexp2000/src/globals.h
    branches/experimental/regexp2000/src/handles.cc
    branches/experimental/regexp2000/src/handles.h
    branches/experimental/regexp2000/src/heap-inl.h
    branches/experimental/regexp2000/src/heap.cc
    branches/experimental/regexp2000/src/heap.h
    branches/experimental/regexp2000/src/ic.cc
    branches/experimental/regexp2000/src/jsregexp.cc
    branches/experimental/regexp2000/src/objects.cc
    branches/experimental/regexp2000/src/runtime.cc
    branches/experimental/regexp2000/src/scanner.cc
    branches/experimental/regexp2000/src/stub-cache.cc
    branches/experimental/regexp2000/src/stub-cache.h
    branches/experimental/regexp2000/src/top.h
    branches/experimental/regexp2000/src/v8natives.js
    branches/experimental/regexp2000/test/cctest/cctest.status
    branches/experimental/regexp2000/test/cctest/test-api.cc
    branches/experimental/regexp2000/test/mjsunit/mjsunit.status
    branches/experimental/regexp2000/test/mozilla/mozilla.status
    branches/experimental/regexp2000/tools/test.py

Log:
Merged bleeding edge 746:795 into regexp2000.

Review URL: http://codereview.chromium.org/11316

Modified: branches/experimental/regexp2000/ChangeLog
==============================================================================
--- branches/experimental/regexp2000/ChangeLog  (original)
+++ branches/experimental/regexp2000/ChangeLog  Thu Nov 20 01:17:38 2008
@@ -1,3 +1,28 @@
+2008-11-17: Version 0.4.4
+
+        Reduced code size by using shorter instruction encoding when
+        possible.
+
+        Added a --help option to the shell sample and to the d8 shell.
+
+        Added visual studio project files for building the ARM simulator.
+
+        Fixed a number of ARM simulator issues.
+
+        Fixed bug in out-of-memory handling on ARM.
+
+        Implemented shell support for passing arguments to a script from
+        the command line.
+
+        Fixed bug in date code that made certain date functions return -0
+        instead of 0 for dates before the epoch.
+
+        Restricted applications of eval so it can only be used in the
+        context of the associated global object.
+
+        Treat byte-order marks as whitespace characters.
+
+
  2008-11-04: Version 0.4.3

          Added support for API accessors that prohibit overwriting by

Modified: branches/experimental/regexp2000/include/v8.h
==============================================================================
--- branches/experimental/regexp2000/include/v8.h       (original)
+++ branches/experimental/regexp2000/include/v8.h       Thu Nov 20 01:17:38 2008
@@ -1811,7 +1811,7 @@
  };


-// --- C o u n t e r s  C a l l b a c k s
+// --- C o u n t e r s  C a l l b a c k s ---

  typedef int* (*CounterLookupCallback)(const wchar_t* name);

@@ -1832,7 +1832,24 @@
  typedef void (*GCCallback)();


-//  --- C o n t e x t  G e n e r a t o r
+// --- E x t e r n a l  S y m b o l  C a l l b a c k ---
+
+/**
+ * Callback used to allocate certain V8 symbols as external strings.
+ *
+ * The data passed to the callback is utf8 encoded.
+ *
+ * Allocations are not allowed in the callback function, you therefore
+ * cannot manipulate objects (set or delete properties for example)
+ * since it is possible such operations will result in the allocation
+ * of objects.
+ */
+typedef String::ExternalStringResource* (*ExternalSymbolCallback)(
+    const char* utf8,
+    size_t length);
+
+
+// --- C o n t e x t  G e n e r a t o r ---

  /**
   * Applications must provide a callback function which is called to  
generate
@@ -1930,6 +1947,20 @@
     * operations will result in the allocation of objects.
     */
    static void SetGlobalGCEpilogueCallback(GCCallback);
+
+  /**
+   * Applications can register a callback that will be used when
+   * allocating most of the V8 symbols.  The callback must return an
+   * external string resource that represents the symbols.
+   *
+   * Most often when performing a property lookup the key will be a
+   * symbol.  Allocating symbols as external strings can reduce the
+   * amount of string conversions needed when using interceptors and
+   * accessors.
+   *
+   * \note This is an experimental feature and it might be removed.
+   */
+  static void SetExternalSymbolCallback(ExternalSymbolCallback);

    /**
     * Allows the host application to group objects together. If one

Modified: branches/experimental/regexp2000/src/api.cc
==============================================================================
--- branches/experimental/regexp2000/src/api.cc (original)
+++ branches/experimental/regexp2000/src/api.cc Thu Nov 20 01:17:38 2008
@@ -2203,7 +2203,7 @@


  const char* v8::V8::GetVersion() {
-  return "0.4.4 (candidate)";
+  return "0.4.5 (candidate)";
  }


@@ -2649,6 +2649,12 @@
  void V8::SetGlobalGCEpilogueCallback(GCCallback callback) {
    if (IsDeadCheck("v8::V8::SetGlobalGCEpilogueCallback()")) return;
    i::Heap::SetGlobalGCEpilogueCallback(callback);
+}
+
+
+void V8::SetExternalSymbolCallback(ExternalSymbolCallback callback) {
+  if (IsDeadCheck("v8::V8::SetExternalSymbolCallback()")) return;
+  i::Heap::SetExternalSymbolCallback(callback);
  }



Modified: branches/experimental/regexp2000/src/ast.h
==============================================================================
--- branches/experimental/regexp2000/src/ast.h  (original)
+++ branches/experimental/regexp2000/src/ast.h  Thu Nov 20 01:17:38 2008
@@ -1126,6 +1126,7 @@
          start_position_(start_position),
          end_position_(end_position),
          is_expression_(is_expression),
+        loop_nesting_(0),
          function_token_position_(RelocInfo::kNoPosition) {
    }

@@ -1150,6 +1151,9 @@

    bool AllowsLazyCompilation();

+  bool loop_nesting() const { return loop_nesting_; }
+  void set_loop_nesting(int nesting) { loop_nesting_ = nesting; }
+
   private:
    Handle<String> name_;
    Scope* scope_;
@@ -1161,6 +1165,7 @@
    int start_position_;
    int end_position_;
    bool is_expression_;
+  int loop_nesting_;
    int function_token_position_;
  };


Modified: branches/experimental/regexp2000/src/builtins-arm.cc
==============================================================================
--- branches/experimental/regexp2000/src/builtins-arm.cc        (original)
+++ branches/experimental/regexp2000/src/builtins-arm.cc        Thu Nov 20  
01:17:38 2008
@@ -663,36 +663,7 @@
    // they will have the correct value when returning from the debugger.
    __ SaveRegistersToMemory(kJSCallerSaved);

-  // This is a direct call from a debug breakpoint. To build a fake JS  
frame
-  // with no parameters push a function and a receiver, keep the current
-  // return address in lr, and set r0 to zero.
-  __ mov(ip, Operand(ExternalReference::the_hole_value_location()));
-  __ ldr(r3, MemOperand(ip));
-  __ mov(r0, Operand(0));  // Null receiver and zero arguments.
-  __ stm(db_w, sp, r0.bit() | r3.bit());  // push function and receiver
-
-  // r0: number of arguments.
-  // What follows is an inlined version of EnterJSFrame(0, 0).
-  // It needs to be kept in sync if any calling conventions are changed.
-
-  // Compute parameter pointer before making changes
-  // ip = sp + kPointerSize*(args_len+1);  // +1 for receiver, args_len ==  
0
-  __ add(ip, sp, Operand(kPointerSize));
-
-  __ mov(r3, Operand(0));  // args_len to be saved
-  __ mov(r2, Operand(cp));  // context to be saved
-
-  // push in reverse order: context (r2), args_len (r3), caller_pp,  
caller_fp,
-  // sp_on_exit (ip == pp), return address
-  __ stm(db_w, sp, r2.bit() | r3.bit() | pp.bit() | fp.bit() |
-         ip.bit() | lr.bit());
-  // Setup new frame pointer.
-  __ add(fp, sp, Operand(-StandardFrameConstants::kContextOffset));
-  __ mov(pp, Operand(ip));  // setup new parameter pointer
-  // r0 is already set to 0 as spare slot to store caller code object  
during GC
-  __ push(r0);  // code pointer
-
-  // Inlined EnterJSFrame ends here.
+  __ EnterInternalFrame();

    // Store the registers containing object pointers on the expression  
stack to
    // make sure that these are correctly updated during GC.
@@ -702,7 +673,7 @@
  #ifdef DEBUG
    __ RecordComment("// Calling from debug break to runtime - come in -  
over");
  #endif
-  // r0 is already 0, no arguments
+  __ mov(r0, Operand(0));  // no arguments
    __ mov(r1, Operand(ExternalReference::debug_break()));

    CEntryDebugBreakStub ceb;
@@ -713,14 +684,7 @@
    // Use sp as base to pop.
    __ CopyRegistersFromStackToMemory(sp, r3, pointer_regs);

-  // What follows is an inlined version of ExitJSFrame(0).
-  // It needs to be kept in sync if any calling conventions are changed.
-  // NOTE: loading the return address to lr and discarding the (fake)  
function
-  //       is an addition to this inlined copy.
-
-  __ mov(sp, Operand(fp));  // respect ABI stack constraint
-  __ ldm(ia, sp, pp.bit() | fp.bit() | sp.bit() | lr.bit());
-  __ pop();  // discard fake function
+  __ LeaveInternalFrame();

    // Inlined ExitJSFrame ends here.


Modified: branches/experimental/regexp2000/src/codegen-arm.h
==============================================================================
--- branches/experimental/regexp2000/src/codegen-arm.h  (original)
+++ branches/experimental/regexp2000/src/codegen-arm.h  Thu Nov 20 01:17:38  
2008
@@ -296,6 +296,7 @@
    void ProcessDeclarations(ZoneList<Declaration*>* declarations);

    Handle<Code> ComputeCallInitialize(int argc);
+  Handle<Code> ComputeCallInitializeInLoop(int argc);

    // Declare global variables and functions in the given array of
    // name/value pairs.

Modified: branches/experimental/regexp2000/src/codegen-ia32.cc
==============================================================================
--- branches/experimental/regexp2000/src/codegen-ia32.cc        (original)
+++ branches/experimental/regexp2000/src/codegen-ia32.cc        Thu Nov 20  
01:17:38 2008
@@ -197,6 +197,10 @@
    VirtualFrame virtual_frame(this);
    frame_ = &virtual_frame;
    cc_reg_ = no_condition;
+
+  // Adjust for function-level loop nesting.
+  loop_nesting_ += fun->loop_nesting();
+
    {
      CodeGenState state(this);

@@ -383,11 +387,15 @@
      }
    }

+  // Adjust for function-level loop nesting.
+  loop_nesting_ -= fun->loop_nesting();
+
    // Code generation state must be reset.
    scope_ = NULL;
    frame_ = NULL;
    ASSERT(!has_cc());
    ASSERT(state_ == NULL);
+  ASSERT(loop_nesting() == 0);
  }


@@ -2694,14 +2702,15 @@
      // patch the stack to use the global proxy as 'this' in the
      // invoked function.
      LoadGlobal();
-
      // Load the arguments.
      for (int i = 0; i < args->length(); i++) {
        Load(args->at(i));
      }

      // Setup the receiver register and call the IC initialization code.
-    Handle<Code> stub = ComputeCallInitialize(args->length());
+    Handle<Code> stub = (loop_nesting() > 0)
+        ? ComputeCallInitializeInLoop(args->length())
+        : ComputeCallInitialize(args->length());
      __ RecordPosition(node->position());
      __ call(stub, RelocInfo::CODE_TARGET_CONTEXT);
      __ mov(esi, frame_->Context());
@@ -2745,7 +2754,9 @@
        for (int i = 0; i < args->length(); i++) Load(args->at(i));

        // Call the IC initialization code.
-      Handle<Code> stub = ComputeCallInitialize(args->length());
+      Handle<Code> stub = (loop_nesting() > 0)
+        ? ComputeCallInitializeInLoop(args->length())
+        : ComputeCallInitialize(args->length());
        __ RecordPosition(node->position());
        __ call(stub, RelocInfo::CODE_TARGET);
        __ mov(esi, frame_->Context());

Modified: branches/experimental/regexp2000/src/codegen-ia32.h
==============================================================================
--- branches/experimental/regexp2000/src/codegen-ia32.h (original)
+++ branches/experimental/regexp2000/src/codegen-ia32.h Thu Nov 20 01:17:38  
2008
@@ -320,6 +320,7 @@
    void ProcessDeclarations(ZoneList<Declaration*>* declarations);

    Handle<Code> ComputeCallInitialize(int argc);
+  Handle<Code> ComputeCallInitializeInLoop(int argc);

    // Declare global variables and functions in the given array of
    // name/value pairs.

Modified: branches/experimental/regexp2000/src/codegen.cc
==============================================================================
--- branches/experimental/regexp2000/src/codegen.cc     (original)
+++ branches/experimental/regexp2000/src/codegen.cc     Thu Nov 20 01:17:38 2008
@@ -242,6 +242,15 @@
  }


+Handle<Code> CodeGenerator::ComputeCallInitializeInLoop(int argc) {
+  // Force the creation of the corresponding stub outside loops,
+  // because it will be used when clearing the ICs later - when we
+  // don't know if we're inside a loop or not.
+  ComputeCallInitialize(argc);
+  CALL_HEAP_FUNCTION(StubCache::ComputeCallInitializeInLoop(argc), Code);
+}
+
+
  void CodeGenerator::ProcessDeclarations(ZoneList<Declaration*>*  
declarations) {
    int length = declarations->length();
    int globals = 0;

Modified: branches/experimental/regexp2000/src/codegen.h
==============================================================================
--- branches/experimental/regexp2000/src/codegen.h      (original)
+++ branches/experimental/regexp2000/src/codegen.h      Thu Nov 20 01:17:38 2008
@@ -48,6 +48,7 @@
  // CodeGenerator::GenCode
  // CodeGenerator::BuildBoilerplate
  // CodeGenerator::ComputeCallInitialize
+// CodeGenerator::ComputeCallInitializeInLoop
  // CodeGenerator::ProcessDeclarations
  // CodeGenerator::DeclareGlobals
  // CodeGenerator::CheckForInlineRuntimeCall

Modified: branches/experimental/regexp2000/src/compiler.cc
==============================================================================
--- branches/experimental/regexp2000/src/compiler.cc    (original)
+++ branches/experimental/regexp2000/src/compiler.cc    Thu Nov 20 01:17:38  
2008
@@ -239,7 +239,8 @@
  }


-bool Compiler::CompileLazy(Handle<SharedFunctionInfo> shared) {
+bool Compiler::CompileLazy(Handle<SharedFunctionInfo> shared,
+                           int loop_nesting) {
    ZoneScope zone_scope(DELETE_ON_EXIT);

    // The VM is in the COMPILER state until exiting this function.
@@ -270,6 +271,9 @@
      ASSERT(Top::has_pending_exception());
      return false;
    }
+
+  // Update the loop nesting in the function literal.
+  lit->set_loop_nesting(loop_nesting);

    // Measure how long it takes to do the lazy compilation; only take
    // the rest of the function into account to avoid overlap with the

Modified: branches/experimental/regexp2000/src/compiler.h
==============================================================================
--- branches/experimental/regexp2000/src/compiler.h     (original)
+++ branches/experimental/regexp2000/src/compiler.h     Thu Nov 20 01:17:38 2008
@@ -64,7 +64,7 @@
    // Compile from function info (used for lazy compilation). Returns
    // true on success and false if the compilation resulted in a stack
    // overflow.
-  static bool CompileLazy(Handle<SharedFunctionInfo> shared);
+  static bool CompileLazy(Handle<SharedFunctionInfo> shared, int  
loop_nesting);
  };

  } }  // namespace v8::internal

Modified: branches/experimental/regexp2000/src/debug-delay.js
==============================================================================
--- branches/experimental/regexp2000/src/debug-delay.js (original)
+++ branches/experimental/regexp2000/src/debug-delay.js Thu Nov 20 01:17:38  
2008
@@ -752,46 +752,6 @@
  };


-BreakEvent.prototype.details = function() {
-  // Build the break details.
-  var details = '';
-  if (this.breakPointsHit()) {
-    details += 'breakpoint';
-    if (this.breakPointsHit().length > 1) {
-      details += 's';
-    }
-    details += ' ';
-    for (var i = 0; i < this.breakPointsHit().length; i++) {
-      if (i > 0) {
-        details += ',';
-      }
-      details += this.breakPointsHit()[i].number();
-    }
-  } else {
-    details += 'break';
-  }
-  details += ' in ';
-  details += this.exec_state_.frame(0).invocationText();
-  details += ' at ';
-  details += this.exec_state_.frame(0).sourceAndPositionText();
-  details += '\n'
-  if (this.func().script()) {
-    details += FrameSourceUnderline(this.exec_state_.frame(0));
-  }
-  return details;
-};
-
-
-BreakEvent.prototype.debugPrompt = function() {
-  // Build the debug break prompt.
-  if (this.breakPointsHit()) {
-    return 'breakpoint';
-  } else {
-    return 'break';
-  }
-};
-
-
  BreakEvent.prototype.toJSONProtocol = function() {
    var o = { seq: next_response_seq++,
              type: "event",
@@ -869,32 +829,6 @@
  };


-ExceptionEvent.prototype.details = function() {
-  var details = "";
-  if (this.uncaught_) {
-    details += "Uncaught: ";
-  } else {
-    details += "Exception: ";
-  }
-
-  details += '"';
-  details += MakeMirror(this.exception_).toText();
-  details += '" at ';
-  details += this.exec_state_.frame(0).sourceAndPositionText();
-  details += '\n';
-  details += FrameSourceUnderline(this.exec_state_.frame(0));
-
-  return details;
-};
-
-ExceptionEvent.prototype.debugPrompt = function() {
-  if (this.uncaught_) {
-    return "uncaught exception";
-  } else {
-    return "exception";
-  }
-};
-
  ExceptionEvent.prototype.toJSONProtocol = function() {
    var o = { seq: next_response_seq++,
              type: "event",
@@ -920,75 +854,37 @@
    return SimpleObjectToJSON_(o);
  };

+
  function MakeCompileEvent(script_source, script_name, script_function) {
    return new CompileEvent(script_source, script_name, script_function);
  }

+
  function CompileEvent(script_source, script_name, script_function) {
    this.scriptSource = script_source;
    this.scriptName = script_name;
    this.scriptFunction = script_function;
  }

-CompileEvent.prototype.details = function() {
-  var result = "";
-  result = "Script added"
-  if (this.scriptData) {
-    result += ": '";
-    result += this.scriptData;
-    result += "'";
-  }
-  return result;
-};
-
-CompileEvent.prototype.debugPrompt = function() {
-  var result = "source"
-  if (this.scriptData) {
-    result += " '";
-    result += this.scriptData;
-    result += "'";
-  }
-  if (this.func) {
-    result += " added";
-  } else {
-    result += " compiled";
-  }
-  return result;
-};

  function MakeNewFunctionEvent(func) {
    return new NewFunctionEvent(func);
  }

+
  function NewFunctionEvent(func) {
    this.func = func;
  }

-NewFunctionEvent.prototype.details = function() {
-  var result = "";
-  result = "Function added: ";
-  result += this.func.name;
-  return result;
-};
-
-NewFunctionEvent.prototype.debugPrompt = function() {
-  var result = "function";
-  if (this.func.name) {
-    result += " '";
-    result += this.func.name;
-    result += "'";
-  }
-  result += " added";
-  return result;
-};
-
  NewFunctionEvent.prototype.name = function() {
    return this.func.name;
  };

+
  NewFunctionEvent.prototype.setBreakPoint = function(p) {
    Debug.setBreakPoint(this.func, p || 0);
  };
+

  function DebugCommandProcessor(exec_state) {
    this.exec_state_ = exec_state;

Modified: branches/experimental/regexp2000/src/debug.cc
==============================================================================
--- branches/experimental/regexp2000/src/debug.cc       (original)
+++ branches/experimental/regexp2000/src/debug.cc       Thu Nov 20 01:17:38 2008
@@ -1135,7 +1135,7 @@

  bool Debug::EnsureCompiled(Handle<SharedFunctionInfo> shared) {
    if (shared->is_compiled()) return true;
-  return CompileLazyShared(shared, CLEAR_EXCEPTION);
+  return CompileLazyShared(shared, CLEAR_EXCEPTION, 0);
  }



Modified: branches/experimental/regexp2000/src/globals.h
==============================================================================
--- branches/experimental/regexp2000/src/globals.h      (original)
+++ branches/experimental/regexp2000/src/globals.h      Thu Nov 20 01:17:38 2008
@@ -288,6 +288,8 @@
  enum InlineCacheState {
    // Has never been executed.
    UNINITIALIZED,
+  // Has never been executed, but is in a loop.
+  UNINITIALIZED_IN_LOOP,
    // Has been executed but monomorhic state has been delayed.
    PREMONOMORPHIC,
    // Has been executed and only one receiver type has been seen.

Modified: branches/experimental/regexp2000/src/handles.cc
==============================================================================
--- branches/experimental/regexp2000/src/handles.cc     (original)
+++ branches/experimental/regexp2000/src/handles.cc     Thu Nov 20 01:17:38 2008
@@ -422,10 +422,11 @@


  bool CompileLazyShared(Handle<SharedFunctionInfo> shared,
-                       ClearExceptionFlag flag) {
+                       ClearExceptionFlag flag,
+                       int loop_nesting) {
    // Compile the source information to a code object.
    ASSERT(!shared->is_compiled());
-  bool result = Compiler::CompileLazy(shared);
+  bool result = Compiler::CompileLazy(shared, loop_nesting);
    ASSERT(result != Top::has_pending_exception());
    if (!result && flag == CLEAR_EXCEPTION) Top::clear_pending_exception();
    return result;
@@ -435,9 +436,15 @@
  bool CompileLazy(Handle<JSFunction> function, ClearExceptionFlag flag) {
    // Compile the source information to a code object.
    Handle<SharedFunctionInfo> shared(function->shared());
-  return CompileLazyShared(shared, flag);
+  return CompileLazyShared(shared, flag, 0);
  }

+
+bool CompileLazyInLoop(Handle<JSFunction> function, ClearExceptionFlag  
flag) {
+  // Compile the source information to a code object.
+  Handle<SharedFunctionInfo> shared(function->shared());
+  return CompileLazyShared(shared, flag, 1);
+}

  OptimizedObjectForAddingMultipleProperties::
  OptimizedObjectForAddingMultipleProperties(Handle<JSObject> object,

Modified: branches/experimental/regexp2000/src/handles.h
==============================================================================
--- branches/experimental/regexp2000/src/handles.h      (original)
+++ branches/experimental/regexp2000/src/handles.h      Thu Nov 20 01:17:38 2008
@@ -194,9 +194,13 @@
  // Do lazy compilation of the given function. Returns true on success
  // and false if the compilation resulted in a stack overflow.
  enum ClearExceptionFlag { KEEP_EXCEPTION, CLEAR_EXCEPTION };
+
  bool CompileLazyShared(Handle<SharedFunctionInfo> shared,
-                       ClearExceptionFlag flag);
+                       ClearExceptionFlag flag,
+                       int loop_nesting);
+
  bool CompileLazy(Handle<JSFunction> function, ClearExceptionFlag flag);
+bool CompileLazyInLoop(Handle<JSFunction> function, ClearExceptionFlag  
flag);

  // These deal with lazily loaded properties.
  void SetupLazy(Handle<JSFunction> fun,

Modified: branches/experimental/regexp2000/src/heap-inl.h
==============================================================================
--- branches/experimental/regexp2000/src/heap-inl.h     (original)
+++ branches/experimental/regexp2000/src/heap-inl.h     Thu Nov 20 01:17:38 2008
@@ -38,6 +38,18 @@
  }


+Object* Heap::AllocateSymbol(Vector<const char> str,
+                             int chars,
+                             uint32_t length_field) {
+  if (global_external_symbol_callback_) {
+    return AllocateExternalSymbol(str, chars);
+  }
+  unibrow::Utf8InputBuffer<> buffer(str.start(),
+                                    static_cast<unsigned>(str.length()));
+  return AllocateInternalSymbol(&buffer, chars, length_field);
+}
+
+
  Object* Heap::AllocateRaw(int size_in_bytes,
                            AllocationSpace space,
                            AllocationSpace retry_space) {

Modified: branches/experimental/regexp2000/src/heap.cc
==============================================================================
--- branches/experimental/regexp2000/src/heap.cc        (original)
+++ branches/experimental/regexp2000/src/heap.cc        Thu Nov 20 01:17:38 2008
@@ -84,6 +84,8 @@
  GCCallback Heap::global_gc_prologue_callback_ = NULL;
  GCCallback Heap::global_gc_epilogue_callback_ = NULL;

+ExternalSymbolCallback Heap::global_external_symbol_callback_ = NULL;
+
  // Variables set based on semispace_size_ and old_generation_size_ in
  // ConfigureHeap.
  int Heap::young_generation_size_ = 0;  // Will be 2 * semispace_size_.
@@ -1542,6 +1544,29 @@
  }


+Object* Heap::AllocateExternalSymbolFromTwoByte(
+    ExternalTwoByteString::Resource* resource) {
+  Map* map;
+  int length = resource->length();
+  if (length <= String::kMaxShortStringSize) {
+    map = short_external_symbol_map();
+  } else if (length <= String::kMaxMediumStringSize) {
+    map = medium_external_symbol_map();
+  } else {
+    map = long_external_symbol_map();
+  }
+
+  Object* result = Allocate(map, OLD_DATA_SPACE);
+  if (result->IsFailure()) return result;
+
+  ExternalTwoByteString* external_string =  
ExternalTwoByteString::cast(result);
+  external_string->set_length(length);
+  external_string->set_resource(resource);
+
+  return result;
+}
+
+
  Object* Heap::LookupSingleCharacterStringFromCode(uint16_t code) {
    if (code <= String::kMaxAsciiCharCode) {
      Object* value = Heap::single_character_string_cache()->get(code);
@@ -2053,9 +2078,9 @@
  }


-Object* Heap::AllocateSymbol(unibrow::CharacterStream* buffer,
-                             int chars,
-                             uint32_t length_field) {
+Object* Heap::AllocateInternalSymbol(unibrow::CharacterStream* buffer,
+                                     int chars,
+                                     uint32_t length_field) {
    // Ensure the chars matches the number of characters in the buffer.
    ASSERT(static_cast<unsigned>(chars) == buffer->Length());
    // Determine whether the string is ascii.
@@ -2108,6 +2133,44 @@
      answer->Set(answer_shape, i, buffer->GetNext());
    }
    return answer;
+}
+
+
+// External string resource that only contains a length field.  These
+// are used temporarily when allocating external symbols.
+class DummyExternalStringResource
+    : public v8::String::ExternalStringResource {
+ public:
+  explicit DummyExternalStringResource(size_t length) : length_(length) { }
+
+  virtual const uint16_t* data() const {
+    UNREACHABLE();
+    return NULL;
+  }
+
+  virtual size_t length() const { return length_; }
+ private:
+  size_t length_;
+};
+
+
+Object* Heap::AllocateExternalSymbol(Vector<const char> string, int chars)  
{
+  // Attempt to allocate the resulting external string first.  Use a
+  // dummy string resource that has the correct length so that we only
+  // have to patch the external string resource after the callback.
+  DummyExternalStringResource dummy_resource(chars);
+  Object* obj = AllocateExternalSymbolFromTwoByte(&dummy_resource);
+  if (obj->IsFailure()) return obj;
+  // Perform callback.
+  v8::String::ExternalStringResource* resource =
+      global_external_symbol_callback_(string.start(), string.length());
+  // Patch the resource pointer of the result.
+  ExternalTwoByteString* result = ExternalTwoByteString::cast(obj);
+  result->set_resource(resource);
+  // Force hash code to be computed.
+  result->Hash();
+  ASSERT(result->IsEqualTo(string));
+  return result;
  }



Modified: branches/experimental/regexp2000/src/heap.h
==============================================================================
--- branches/experimental/regexp2000/src/heap.h (original)
+++ branches/experimental/regexp2000/src/heap.h Thu Nov 20 01:17:38 2008
@@ -356,9 +356,17 @@
    // Returns Failure::RetryAfterGC(requested_bytes, space) if the  
allocation
    // failed.
    // Please note this function does not perform a garbage collection.
-  static Object* AllocateSymbol(unibrow::CharacterStream* buffer,
-                                int chars,
-                                uint32_t length_field);
+  static inline Object* AllocateSymbol(Vector<const char> str,
+                                       int chars,
+                                       uint32_t length_field);
+
+  static Object* AllocateInternalSymbol(unibrow::CharacterStream* buffer,
+                                        int chars,
+                                        uint32_t length_field);
+
+  static Object* AllocateExternalSymbol(Vector<const char> str,
+                                        int chars);
+

    // Allocates and partially initializes a String.  There are two String
    // encodings: ASCII and two byte.  These functions allocate a string of  
the
@@ -533,6 +541,8 @@
        ExternalAsciiString::Resource* resource);
    static Object* AllocateExternalStringFromTwoByte(
        ExternalTwoByteString::Resource* resource);
+  static Object* AllocateExternalSymbolFromTwoByte(
+      ExternalTwoByteString::Resource* resource);

    // Allocates an uninitialized object.  The memory is non-executable if  
the
    // hardware and OS allow.
@@ -604,6 +614,10 @@
      global_gc_epilogue_callback_ = callback;
    }

+  static void SetExternalSymbolCallback(ExternalSymbolCallback callback) {
+    global_external_symbol_callback_ = callback;
+  }
+
    // Heap roots
  #define ROOT_ACCESSOR(type, name) static type* name() { return name##_; }
    ROOT_LIST(ROOT_ACCESSOR)
@@ -862,6 +876,9 @@
    // Allocations in the callback function are disallowed.
    static GCCallback global_gc_prologue_callback_;
    static GCCallback global_gc_epilogue_callback_;
+
+  // Callback function used for allocating external symbols.
+  static ExternalSymbolCallback global_external_symbol_callback_;

    // Checks whether a global GC is necessary
    static GarbageCollector SelectGarbageCollector(AllocationSpace space);

Modified: branches/experimental/regexp2000/src/ic.cc
==============================================================================
--- branches/experimental/regexp2000/src/ic.cc  (original)
+++ branches/experimental/regexp2000/src/ic.cc  Thu Nov 20 01:17:38 2008
@@ -41,6 +41,7 @@
  static char TransitionMarkFromState(IC::State state) {
    switch (state) {
      case UNINITIALIZED: return '0';
+    case UNINITIALIZED_IN_LOOP: return 'L';
      case PREMONOMORPHIC: return '0';
      case MONOMORPHIC: return '1';
      case MONOMORPHIC_PROTOTYPE_FAILURE: return '^';
@@ -223,7 +224,8 @@


  void CallIC::Clear(Address address, Code* target) {
-  if (target->ic_state() == UNINITIALIZED) return;
+  State state = target->ic_state();
+  if (state == UNINITIALIZED || state == UNINITIALIZED_IN_LOOP) return;
    Code* code = StubCache::FindCallInitialize(target->arguments_count());
    SetTargetAtAddress(address, code);
  }
@@ -434,8 +436,9 @@
    if (code->IsFailure()) return;

    // Patch the call site depending on the state of the cache.
-  if (state == UNINITIALIZED || state == PREMONOMORPHIC ||
-      state == MONOMORPHIC || state == MONOMORPHIC_PROTOTYPE_FAILURE) {
+  if (state == UNINITIALIZED || state == UNINITIALIZED_IN_LOOP ||
+      state == PREMONOMORPHIC || state == MONOMORPHIC ||
+      state == MONOMORPHIC_PROTOTYPE_FAILURE) {
      set_target(Code::cast(code));
    }

@@ -1044,7 +1047,17 @@
    ASSERT(args.length() == 2);
    CallIC ic;
    IC::State state = IC::StateFrom(ic.target(), args[0]);
-  return ic.LoadFunction(state, args.at<Object>(0), args.at<String>(1));
+  Object* result =
+      ic.LoadFunction(state, args.at<Object>(0), args.at<String>(1));
+  if (state != UNINITIALIZED_IN_LOOP || !result->IsJSFunction())
+    return result;
+
+  // Compile the function with the knowledge that it's called from
+  // within a loop. This enables further optimization of the function.
+  HandleScope scope;
+  Handle<JSFunction> function =  
Handle<JSFunction>(JSFunction::cast(result));
+  if (!function->is_compiled()) CompileLazyInLoop(function,  
CLEAR_EXCEPTION);
+  return *function;
  }



Modified: branches/experimental/regexp2000/src/jsregexp.cc
==============================================================================
--- branches/experimental/regexp2000/src/jsregexp.cc    (original)
+++ branches/experimental/regexp2000/src/jsregexp.cc    Thu Nov 20 01:17:38  
2008
@@ -111,7 +111,7 @@
    // Ensure that the constructor function has been loaded.
    if (!constructor->IsLoaded()) {
      LoadLazy(constructor, has_pending_exception);
-    if (*has_pending_exception) return  
Handle<Object>(Failure::Exception());
+    if (*has_pending_exception) return Handle<Object>();
    }
    // Call the construct code with 2 arguments.
    Object** argv[2] = { Handle<Object>::cast(pattern).location(),

Modified: branches/experimental/regexp2000/src/objects.cc
==============================================================================
--- branches/experimental/regexp2000/src/objects.cc     (original)
+++ branches/experimental/regexp2000/src/objects.cc     Thu Nov 20 01:17:38 2008
@@ -4654,6 +4654,7 @@
  const char* Code::ICState2String(InlineCacheState state) {
    switch (state) {
      case UNINITIALIZED: return "UNINITIALIZED";
+    case UNINITIALIZED_IN_LOOP: return "UNINITIALIZED_IN_LOOP";
      case PREMONOMORPHIC: return "PREMONOMORPHIC";
      case MONOMORPHIC: return "MONOMORPHIC";
      case MONOMORPHIC_PROTOTYPE_FAILURE:  
return "MONOMORPHIC_PROTOTYPE_FAILURE";
@@ -5856,9 +5857,7 @@

    Object* GetObject() {
      if (length_field_ == 0) Hash();
-    unibrow::Utf8InputBuffer<> buffer(string_.start(),
-                                       
static_cast<unsigned>(string_.length()));
-    return Heap::AllocateSymbol(&buffer, chars_, length_field_);
+    return Heap::AllocateSymbol(string_, chars_, length_field_);
    }

    static uint32_t StringHash(Object* obj) {
@@ -5907,9 +5906,9 @@
      }
      // Otherwise allocate a new symbol.
      StringInputBuffer buffer(string_);
-    return Heap::AllocateSymbol(&buffer,
-                                string_->length(),
-                                string_->length_field());
+    return Heap::AllocateInternalSymbol(&buffer,
+                                        string_->length(),
+                                        string_->length_field());
    }

    static uint32_t StringHash(Object* obj) {

Modified: branches/experimental/regexp2000/src/runtime.cc
==============================================================================
--- branches/experimental/regexp2000/src/runtime.cc     (original)
+++ branches/experimental/regexp2000/src/runtime.cc     Thu Nov 20 01:17:38 2008
@@ -3956,29 +3956,28 @@
    Handle<Context> target = Top::global_context();
    if (caller->global_context() == *target) return *caller;

-  // Compute a function closure that captures the calling context. We
-  // need a function that has trivial scope info, since it is only
-  // used to hold the context chain together.
-  Handle<JSFunction> closure =  
Factory::NewFunction(Factory::empty_symbol(),
-                                                     
Factory::undefined_value());
-  closure->set_context(*caller);
-
-  // Create a new adaptor context that has the target environment as
-  // the extension object. This enables the evaluated code to see both
-  // the current context with locals and everything and to see global
-  // variables declared in the target global object. Furthermore, any
-  // properties introduced with 'var' will be added to the target
-  // global object because it is the extension object.
-  Handle<Context> adaptor =
-    Factory::NewFunctionContext(Context::MIN_CONTEXT_SLOTS, closure);
-  adaptor->set_extension(target->global());
-  return *adaptor;
+  // Otherwise, use the global context from the other environment.
+  return *target;
  }


  static Object* Runtime_EvalReceiver(Arguments args) {
+  ASSERT(args.length() == 1);
    StackFrameLocator locator;
-  return locator.FindJavaScriptFrame(1)->receiver();
+  JavaScriptFrame* frame = locator.FindJavaScriptFrame(1);
+  // Fetch the caller context from the frame.
+  Context* caller = Context::cast(frame->context());
+
+  // Check for eval() invocations that cross environments. Use the
+  // top frames receiver if evaluating in current environment.
+  Context* global_context = Top::context()->global()->global_context();
+  if (caller->global_context() == global_context) {
+    return frame->receiver();
+  }
+
+  // Otherwise use the given argument (the global object of the
+  // receiving context).
+  return args[0];
  }


@@ -4797,9 +4796,10 @@
    // Traverse the saved contexts chain to find the active context for the
    // selected frame.
    SaveContext* save = Top::save_context();
-  while (save != NULL && reinterpret_cast<Address>(save) <  
it.frame()->sp()) {
+  while (save != NULL && !save->below(it.frame())) {
      save = save->prev();
    }
+  ASSERT(save != NULL);

    // Get the frame id.
    Handle<Object> frame_id(WrapFrameId(it.frame()->id()));
@@ -5088,7 +5088,7 @@
      if (!done) {
        // If the candidate is not compiled compile it to reveal any inner
        // functions which might contain the requested source position.
-      CompileLazyShared(target, KEEP_EXCEPTION);
+      CompileLazyShared(target, KEEP_EXCEPTION, 0);
      }
    }

@@ -5299,7 +5299,7 @@
    // Traverse the saved contexts chain to find the active context for the
    // selected frame.
    SaveContext* save = Top::save_context();
-  while (save != NULL && reinterpret_cast<Address>(save) < frame->sp()) {
+  while (save != NULL && !save->below(frame)) {
      save = save->prev();
    }
    ASSERT(save != NULL);

Modified: branches/experimental/regexp2000/src/scanner.cc
==============================================================================
--- branches/experimental/regexp2000/src/scanner.cc     (original)
+++ branches/experimental/regexp2000/src/scanner.cc     Thu Nov 20 01:17:38 2008
@@ -234,11 +234,25 @@
  }


+static inline bool IsByteOrderMark(uc32 c) {
+  // The Unicode value U+FFFE is guaranteed never to be assigned as a
+  // Unicode character; this implies that in a Unicode context the
+  // 0xFF, 0xFE byte pattern can only be interpreted as the U+FEFF
+  // character expressed in little-endian byte order (since it could
+  // not be a U+FFFE character expressed in big-endian byte
+  // order). Nevertheless, we check for it to be compatible with
+  // Spidermonkey.
+  return c == 0xFEFF || c == 0xFFFE;
+}
+
+
  void Scanner::SkipWhiteSpace(bool initial) {
    has_line_terminator_before_next_ = initial;

    while (true) {
-    while (kIsWhiteSpace.get(c0_)) {
+    // We treat byte-order marks (BOMs) as whitespace for better
+    // compatibility with Spidermonkey and other JavaScript engines.
+    while (kIsWhiteSpace.get(c0_) || IsByteOrderMark(c0_)) {
        // IsWhiteSpace() includes line terminators!
        if (kIsLineTerminator.get(c0_))
          // Ignore line terminators, but remember them. This is necessary

Modified: branches/experimental/regexp2000/src/stub-cache.cc
==============================================================================
--- branches/experimental/regexp2000/src/stub-cache.cc  (original)
+++ branches/experimental/regexp2000/src/stub-cache.cc  Thu Nov 20 01:17:38  
2008
@@ -543,6 +543,17 @@
  }


+Object* StubCache::ComputeCallInitializeInLoop(int argc) {
+  Code::Flags flags =
+      Code::ComputeFlags(Code::CALL_IC, UNINITIALIZED_IN_LOOP, NORMAL,  
argc);
+  Object* probe = ProbeCache(flags);
+  if (!probe->IsUndefined()) return probe;
+  StubCompiler compiler;
+  return FillCache(compiler.CompileCallInitialize(flags));
+}
+
+
+
  Object* StubCache::ComputeCallPreMonomorphic(int argc) {
    Code::Flags flags =
        Code::ComputeFlags(Code::CALL_IC, PREMONOMORPHIC, NORMAL, argc);

Modified: branches/experimental/regexp2000/src/stub-cache.h
==============================================================================
--- branches/experimental/regexp2000/src/stub-cache.h   (original)
+++ branches/experimental/regexp2000/src/stub-cache.h   Thu Nov 20 01:17:38  
2008
@@ -148,6 +148,7 @@
    // ---

    static Object* ComputeCallInitialize(int argc);
+  static Object* ComputeCallInitializeInLoop(int argc);
    static Object* ComputeCallPreMonomorphic(int argc);
    static Object* ComputeCallNormal(int argc);
    static Object* ComputeCallMegamorphic(int argc);

Modified: branches/experimental/regexp2000/src/top.h
==============================================================================
--- branches/experimental/regexp2000/src/top.h  (original)
+++ branches/experimental/regexp2000/src/top.h  Thu Nov 20 01:17:38 2008
@@ -312,6 +312,10 @@
  #endif
        prev_(Top::save_context()) {
      Top::set_save_context(this);
+
+    // If there is no JS frame under the current C frame, use the value 0.
+    JavaScriptFrameIterator it;
+    js_sp_ = it.done() ? 0 : it.frame()->sp();
    }

    ~SaveContext() {
@@ -322,12 +326,18 @@
    Handle<Context> context() { return context_; }
    SaveContext* prev() { return prev_; }

+  // Returns true if this save context is below a given JavaScript frame.
+  bool below(JavaScriptFrame* frame) {
+    return (js_sp_ == 0) || (frame->sp() < js_sp_);
+  }
+
   private:
    Handle<Context> context_;
  #if __GNUC_VERSION__ >= 40100 && __GNUC_VERSION__ < 40300
    Handle<Context> dummy_;
  #endif
    SaveContext* prev_;
+  Address js_sp_;  // The top JS frame's sp when saving context.
  };



Modified: branches/experimental/regexp2000/src/v8natives.js
==============================================================================
--- branches/experimental/regexp2000/src/v8natives.js   (original)
+++ branches/experimental/regexp2000/src/v8natives.js   Thu Nov 20 01:17:38  
2008
@@ -105,6 +105,11 @@
  function GlobalEval(x) {
    if (!IS_STRING(x)) return x;

+  if (this !== %GlobalReceiver(global)) {
+    throw new $EvalError('The "this" object passed to eval must ' +
+                         'be the global object from which eval  
originated');
+  }
+
    var f = %CompileString(x, 0, true);
    if (!IS_FUNCTION(f)) return f;


Modified: branches/experimental/regexp2000/test/cctest/cctest.status
==============================================================================
--- branches/experimental/regexp2000/test/cctest/cctest.status  (original)
+++ branches/experimental/regexp2000/test/cctest/cctest.status  Thu Nov 20  
01:17:38 2008
@@ -34,7 +34,6 @@

  test-debug: SKIP
  test-serialize: SKIP
-test-api: SKIP

  # BUG(113): Test seems flaky on ARM.
  test-spaces/LargeObjectSpace: PASS || FAIL

Modified: branches/experimental/regexp2000/test/cctest/test-api.cc
==============================================================================
--- branches/experimental/regexp2000/test/cctest/test-api.cc    (original)
+++ branches/experimental/regexp2000/test/cctest/test-api.cc    Thu Nov 20  
01:17:38 2008
@@ -4018,6 +4018,30 @@
  }


+THREADED_TEST(Eval) {
+  v8::HandleScope scope;
+  LocalContext current;
+
+  // Test that un-aliased eval uses local context.
+  Local<Script> script =
+      Script::Compile(v8_str("foo = 0;"
+                             "(function() {"
+                             "  var foo = 2;"
+                             "  return eval('foo');"
+                             "})();"));
+  Local<Value> result = script->Run();
+  CHECK_EQ(2, result->Int32Value());
+
+  // Test that un-aliased eval has right this.
+  script =
+      Script::Compile(v8_str("function MyObject() { this.self =  
eval('this'); }"
+                             "var o = new MyObject();"
+                             "o === o.self"));
+  result = script->Run();
+  CHECK(result->IsTrue());
+}
+
+
  THREADED_TEST(CrossEval) {
    v8::HandleScope scope;
    LocalContext other;
@@ -4039,45 +4063,62 @@
    CHECK(!current->Global()->Has(v8_str("foo")));

    // Check that writing to non-existing properties introduces them in
-  // the current context.
+  // the other context.
    script =
        Script::Compile(v8_str("other.eval('na = 1234')"));
    script->Run();
-  CHECK_EQ(1234, current->Global()->Get(v8_str("na"))->Int32Value());
-  CHECK(!other->Global()->Has(v8_str("na")));
+  CHECK_EQ(1234, other->Global()->Get(v8_str("na"))->Int32Value());
+  CHECK(!current->Global()->Has(v8_str("na")));

-  // Check that variables in current context are visible in other
-  // context. This must include local variables.
+  // Check that global variables in current context are not visible in  
other
+  // context.
+  v8::TryCatch try_catch;
    script =
-      Script::Compile(v8_str("var bar = 42;"
-                                      "(function() { "
-                                      "  var baz = 87;"
-                                      "  return other.eval('bar + baz');"
-                                      "})();"));
+      Script::Compile(v8_str("var bar = 42; other.eval('bar');"));
    Local<Value> result = script->Run();
-  CHECK_EQ(42 + 87, result->Int32Value());
+  CHECK(try_catch.HasCaught());
+  try_catch.Reset();
+
+  // Check that local variables in current context are not visible in other
+  // context.
+  script =
+      Script::Compile(v8_str("(function() { "
+                             "  var baz = 87;"
+                             "  return other.eval('baz');"
+                             "})();"));
+  result = script->Run();
+  CHECK(try_catch.HasCaught());
+  try_catch.Reset();

    // Check that global variables in the other environment are visible
    // when evaluting code.
    other->Global()->Set(v8_str("bis"), v8_num(1234));
    script = Script::Compile(v8_str("other.eval('bis')"));
    CHECK_EQ(1234, script->Run()->Int32Value());
+  CHECK(!try_catch.HasCaught());

-  // Check that the 'this' pointer isn't touched as a result of
-  // calling eval across environments.
+  // Check that the 'this' pointer points to the global object evaluating
+  // code.
+  other->Global()->Set(v8_str("t"), other->Global());
+  script = Script::Compile(v8_str("other.eval('this == t')"));
+  result = script->Run();
+  CHECK(result->IsTrue());
+  CHECK(!try_catch.HasCaught());
+
+  // Check that variables introduced in with-statement are not visible in
+  // other context.
    script =
-      Script::Compile(v8_str("var t = this; other.eval('this == t')"));
+      Script::Compile(v8_str("with({x:2}){other.eval('x')}"));
    result = script->Run();
-  CHECK(result->IsBoolean());
-  CHECK(result->BooleanValue());
+  CHECK(try_catch.HasCaught());
+  try_catch.Reset();

-  // Check that doing a cross eval works from within a global
-  // with-statement.
+  // Check that you cannot use 'eval.call' with another object than the
+  // current global object.
    script =
-      Script::Compile(v8_str("other.y = 1;"
-                                      "with({x:2}){other.eval('x+y')}"));
+      Script::Compile(v8_str("other.y = 1; eval.call(other, 'y')"));
    result = script->Run();
-  CHECK_EQ(3, result->Int32Value());
+  CHECK(try_catch.HasCaught());
  }


@@ -5213,4 +5254,70 @@
    context->Global()->Set(v8_str("obj"), instance);
    Local<Value> value = CompileRun("obj.x");
    CHECK(value->BooleanValue());
+}
+
+
+static String::ExternalStringResource* SymbolCallback(const char* chars,
+                                                      size_t length) {
+  uint16_t* buffer = i::NewArray<uint16_t>(length + 1);
+  for (size_t i = 0; i < length; i++) {
+    buffer[i] = chars[i];
+  }
+  buffer[length] = '\0';
+  return new TestResource(buffer);
+}
+
+
+static v8::Handle<Value> ExternalSymbolGetter(Local<String> name,
+                                              const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  CHECK(!name->Equals(v8_str("externalSymbol722")) || name->IsExternal());
+  return v8::True();
+}
+
+
+static void ExternalSymbolSetter(Local<String> name,
+                                 Local<Value> value,
+                                 const AccessorInfo&) {
+  ApiTestFuzzer::Fuzz();
+  CHECK(!name->Equals(v8_str("externalSymbol722")) || name->IsExternal());
+}
+
+
+THREADED_TEST(ExternalSymbols) {
+  TestResource::dispose_count = 0;
+  v8::V8::SetExternalSymbolCallback(SymbolCallback);
+  v8::HandleScope scope;
+  LocalContext context;
+  Local<ObjectTemplate> templ = ObjectTemplate::New();
+  // Use a bizare name so that the name does not clash with names used
+  // in natives files.  If running with snapshots enabled, variable
+  // names used in the native files will be normal symbols instead of
+  // external ones.  Also, make sure that the bizare name is used from
+  // JavaScript code before using it from C++ code.
+  Local<Value> value =
+      CompileRun("var o = { externalSymbol722: 42 }; o.externalSymbol722");
+  CHECK_EQ(42, value->Int32Value());
+  templ->SetAccessor(v8_str("externalSymbol722"),
+                     ExternalSymbolGetter,
+                     ExternalSymbolSetter);
+  context->Global()->Set(v8_str("obj"), templ->NewInstance());
+  value = CompileRun("obj.externalSymbol722");
+  CHECK_EQ(true, value->BooleanValue());
+  value = CompileRun("obj.externalSymbol722 = 42");
+  v8::V8::SetExternalSymbolCallback(NULL);
+}
+
+
+// This test verifies that pre-compilation (aka preparsing) can be called
+// without initializing the whole VM. Thus we cannot run this test in a
+// multi-threaded setup.
+TEST(PreCompile) {
+  // TODO(155): This test would break without the initialization of V8.  
This is
+  // a workaround for now to make this test not fail.
+  v8::V8::Initialize();
+  const char *script = "function foo(a) { return a+1; }";
+  v8::ScriptData *sd = v8::ScriptData::PreCompile(script, strlen(script));
+  CHECK_NE(sd->Length(), 0);
+  CHECK_NE(sd->Data(), NULL);
  }

Modified: branches/experimental/regexp2000/test/mjsunit/mjsunit.status
==============================================================================
--- branches/experimental/regexp2000/test/mjsunit/mjsunit.status        
(original)
+++ branches/experimental/regexp2000/test/mjsunit/mjsunit.status        Thu Nov 
20  
01:17:38 2008
@@ -41,26 +41,21 @@
  debug-scripts-request: PASS, SKIP if $mode == debug

  # Bug number 1020483: Debug tests fail on ARM.
-debug-constructor: CRASH, FAIL if $mode == debug
-debug-continue: CRASH, FAIL if $mode == debug
-debug-backtrace-text: FAIL
-debug-backtrace: CRASH, FAIL if $mode == debug
+debug-constructor: CRASH, FAIL
+debug-continue: CRASH, FAIL
+debug-backtrace: FAIL
  debug-evaluate-recursive: CRASH, FAIL if $mode == debug
  debug-changebreakpoint: CRASH, FAIL if $mode == debug
  debug-clearbreakpoint: CRASH, FAIL if $mode == debug
  debug-conditional-breakpoints: CRASH, FAIL if $mode == debug
-debug-enable-disable-breakpoints: CRASH, FAIL if $mode == debug
  debug-evaluate: CRASH, FAIL if $mode == debug
-debug-event-listener: CRASH, FAIL if $mode == debug
  debug-ignore-breakpoints: CRASH, FAIL if $mode == debug
  debug-multiple-breakpoints: CRASH, FAIL if $mode == debug
  debug-setbreakpoint: CRASH, FAIL if $mode == debug
  debug-step-stub-callfunction: CRASH
-debug-stepin-constructor: CRASH, FAIL if $mode == debug
+debug-stepin-constructor: CRASH, FAIL
  debug-step: CRASH, FAIL if $mode == debug
  debug-breakpoints: PASS || FAIL
-
-regress/regress-998565: CRASH, FAIL if $mode == debug

  # Bug number 130 http://code.google.com/p/v8/issues/detail?id=130
  # Fails on real ARM hardware but not on the simulator.

Modified: branches/experimental/regexp2000/test/mozilla/mozilla.status
==============================================================================
--- branches/experimental/regexp2000/test/mozilla/mozilla.status        
(original)
+++ branches/experimental/regexp2000/test/mozilla/mozilla.status        Thu Nov 
20  
01:17:38 2008
@@ -570,10 +570,7 @@
  js1_5/Regress/regress-303213: FAIL


-# Bug 1193440: Ignore Unicode BOM characters when scanning.
-ecma_3/extensions/regress-368516: FAIL
-
-# Bug 1202592:New ecma_3/String/15.5.4.11 is failing.
+# Bug 1202592: New ecma_3/String/15.5.4.11 is failing.
  ecma_3/String/15.5.4.11: FAIL

  # Bug 1202597: New js1_5/Expressions/regress-394673 is failing.

Modified: branches/experimental/regexp2000/tools/test.py
==============================================================================
--- branches/experimental/regexp2000/tools/test.py      (original)
+++ branches/experimental/regexp2000/tools/test.py      Thu Nov 20 01:17:38 2008
@@ -417,8 +417,12 @@
    if utils.IsWindows():
      popen_args = '"' + subprocess.list2cmdline(args) + '"'
      if context.suppress_dialogs:
-      # Try to change the error mode to avoid dialogs on fatal errors.
-      Win32SetErrorMode(SEM_NOGPFAULTERRORBOX)
+      # Try to change the error mode to avoid dialogs on fatal errors.  
Don't
+      # touch any existing error mode flags by merging the existing error  
mode.
+      # See  
http://blogs.msdn.com/oldnewthing/archive/2004/07/27/198410.aspx.
+      error_mode = SEM_NOGPFAULTERRORBOX;
+      prev_error_mode = Win32SetErrorMode(error_mode);
+      Win32SetErrorMode(error_mode | prev_error_mode);
    process = subprocess.Popen(
      shell = utils.IsWindows(),
      args = popen_args,

--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---

Reply via email to