Revision: 2682
Author: [email protected]
Date: Thu Aug 13 05:44:13 2009
Log: Push version 1.3.4 to trunk.

Added a readline() command to the d8 shell.

Fixed bug in json parsing.

Added idle notification to the API and reduced memory on idle notifications.

Review URL: http://codereview.chromium.org/164475
http://code.google.com/p/v8/source/detail?r=2682

Modified:
  /trunk/ChangeLog
  /trunk/include/v8.h
  /trunk/src/api.cc
  /trunk/src/compiler.cc
  /trunk/src/compiler.h
  /trunk/src/d8.cc
  /trunk/src/d8.h
  /trunk/src/flag-definitions.h
  /trunk/src/heap.cc
  /trunk/src/heap.h
  /trunk/src/messages.js
  /trunk/src/runtime.cc
  /trunk/src/spaces.cc
  /trunk/src/spaces.h
  /trunk/src/uri.js
  /trunk/src/v8.cc
  /trunk/src/v8.h
  /trunk/src/version.cc
  /trunk/src/x64/codegen-x64.cc
  /trunk/src/x64/disasm-x64.cc
  /trunk/test/mjsunit/json.js

=======================================
--- /trunk/ChangeLog    Wed Aug 12 07:20:51 2009
+++ /trunk/ChangeLog    Thu Aug 13 05:44:13 2009
@@ -1,3 +1,13 @@
+2009-08-13: Version 1.3.4
+
+        Added a readline() command to the d8 shell.
+
+        Fixed bug in json parsing.
+
+        Added idle notification to the API and reduced memory on idle
+        notifications.
+
+
  2009-08-12: Version 1.3.3

          Fix issue 417: incorrect %t placeholder expansion.
=======================================
--- /trunk/include/v8.h Wed Aug 12 07:20:51 2009
+++ /trunk/include/v8.h Thu Aug 13 05:44:13 2009
@@ -2201,6 +2201,14 @@
     */
    static bool Dispose();

+
+  /**
+   * Optional notification that the embedder is idle.
+   * V8 uses the notification to reduce memory footprint.
+   * \param is_high_priority tells whether the embedder is high priority.
+   */
+  static void IdleNotification(bool is_high_priority);
+
   private:
    V8();

=======================================
--- /trunk/src/api.cc   Wed Aug 12 07:20:51 2009
+++ /trunk/src/api.cc   Thu Aug 13 05:44:13 2009
@@ -2558,6 +2558,10 @@
  }


+void  v8::V8::IdleNotification(bool is_high_priority) {
+  i::V8::IdleNotification(is_high_priority);
+}
+
  const char* v8::V8::GetVersion() {
    static v8::internal::EmbeddedVector<char, 128> buffer;
    v8::internal::Version::GetString(buffer);
@@ -2589,12 +2593,8 @@
    i::Handle<i::Context> env;
    {
      ENTER_V8;
-#if defined(ANDROID)
-    // On mobile devices, full GC is expensive.
-#else
      // Give the heap a chance to cleanup if we've disposed contexts.
      i::Heap::CollectAllGarbageIfContextDisposed();
-#endif
      v8::Handle<ObjectTemplate> proxy_template = global_template;
      i::Handle<i::FunctionTemplateInfo> proxy_constructor;
      i::Handle<i::FunctionTemplateInfo> global_constructor;
=======================================
--- /trunk/src/compiler.cc      Wed Aug  5 01:38:10 2009
+++ /trunk/src/compiler.cc      Thu Aug 13 05:44:13 2009
@@ -102,7 +102,7 @@


  static bool IsValidJSON(FunctionLiteral* lit) {
-  if (!lit->body()->length() == 1)
+  if (lit->body()->length() != 1)
      return false;
    Statement* stmt = lit->body()->at(0);
    if (stmt->AsExpressionStatement() == NULL)
@@ -114,7 +114,7 @@

  static Handle<JSFunction> MakeFunction(bool is_global,
                                         bool is_eval,
-                                       bool is_json,
+                                       Compiler::ValidationState validate,
                                         Handle<Script> script,
                                         Handle<Context> context,
                                         v8::Extension* extension,
@@ -129,6 +129,7 @@
    script->set_context_data((*i::Top::global_context())->data());

  #ifdef ENABLE_DEBUGGER_SUPPORT
+  bool is_json = (validate == Compiler::VALIDATE_JSON);
    if (is_eval || is_json) {
      script->set_compilation_type(
          is_json ? Smi::FromInt(Script::COMPILATION_TYPE_JSON) :
@@ -162,7 +163,7 @@
    // When parsing JSON we do an ordinary parse and then afterwards
    // check the AST to ensure it was well-formed.  If not we give a
    // syntax error.
-  if (is_json && !IsValidJSON(lit)) {
+  if (validate == Compiler::VALIDATE_JSON && !IsValidJSON(lit)) {
      HandleScope scope;
      Handle<JSArray> args = Factory::NewJSArray(1);
      Handle<Object> source(script->source());
@@ -282,7 +283,7 @@
      // Compile the function and add it to the cache.
      result = MakeFunction(true,
                            false,
-                          false,
+                          DONT_VALIDATE_JSON,
                            script,
                            Handle<Context>::null(),
                            extension,
@@ -305,7 +306,11 @@
  Handle<JSFunction> Compiler::CompileEval(Handle<String> source,
                                           Handle<Context> context,
                                           bool is_global,
-                                         bool is_json) {
+                                         ValidationState validate) {
+  // Note that if validation is required then no path through this
+  // function is allowed to return a value without validating that
+  // the input is legal json.
+
    int source_length = source->length();
    Counters::total_eval_size.Increment(source_length);
    Counters::total_compile_size.Increment(source_length);
@@ -314,20 +319,26 @@
    VMState state(COMPILER);

    // Do a lookup in the compilation cache; if the entry is not there,
-  // invoke the compiler and add the result to the cache.
-  Handle<JSFunction> result =
-      CompilationCache::LookupEval(source, context, is_global);
+  // invoke the compiler and add the result to the cache.  If we're
+  // evaluating json we bypass the cache since we can't be sure a
+  // potential value in the cache has been validated.
+  Handle<JSFunction> result;
+  if (validate == DONT_VALIDATE_JSON)
+    result = CompilationCache::LookupEval(source, context, is_global);
+
    if (result.is_null()) {
      // Create a script object describing the script to be compiled.
      Handle<Script> script = Factory::NewScript(source);
      result = MakeFunction(is_global,
                            true,
-                          is_json,
+                          validate,
                            script,
                            context,
                            NULL,
                            NULL);
-    if (!result.is_null()) {
+    if (!result.is_null() && validate != VALIDATE_JSON) {
+      // For json it's unlikely that we'll ever see exactly the same
+      // string again so we don't use the compilation cache.
        CompilationCache::PutEval(source, context, is_global, result);
      }
    }
=======================================
--- /trunk/src/compiler.h       Mon May 25 22:44:31 2009
+++ /trunk/src/compiler.h       Thu Aug 13 05:44:13 2009
@@ -48,6 +48,8 @@

  class Compiler : public AllStatic {
   public:
+  enum ValidationState { VALIDATE_JSON, DONT_VALIDATE_JSON };
+
    // All routines return a JSFunction.
    // If an error occurs an exception is raised and
    // the return handle contains NULL.
@@ -63,7 +65,7 @@
    static Handle<JSFunction> CompileEval(Handle<String> source,
                                          Handle<Context> context,
                                          bool is_global,
-                                        bool is_json);
+                                        ValidationState validation);

    // Compile from function info (used for lazy compilation). Returns
    // true on success and false if the compilation resulted in a stack
=======================================
--- /trunk/src/d8.cc    Wed Aug 12 07:20:51 2009
+++ /trunk/src/d8.cc    Thu Aug 13 05:44:13 2009
@@ -167,9 +167,6 @@


  Handle<Value> Shell::Read(const Arguments& args) {
-  if (args.Length() != 1) {
-    return ThrowException(String::New("Bad parameters"));
-  }
    String::Utf8Value file(args[0]);
    if (*file == NULL) {
      return ThrowException(String::New("Error loading file"));
@@ -180,6 +177,19 @@
    }
    return source;
  }
+
+
+Handle<Value> Shell::ReadLine(const Arguments& args) {
+  char line_buf[256];
+  if (fgets(line_buf, sizeof(line_buf), stdin) == NULL) {
+    return ThrowException(String::New("Error reading line"));
+  }
+  int len = strlen(line_buf);
+  if (line_buf[len - 1] == '\n') {
+    --len;
+  }
+  return String::New(line_buf, len);
+}


  Handle<Value> Shell::Load(const Arguments& args) {
@@ -404,6 +414,8 @@
    global_template->Set(String::New("print"), FunctionTemplate::New(Print));
    global_template->Set(String::New("write"), FunctionTemplate::New(Write));
    global_template->Set(String::New("read"), FunctionTemplate::New(Read));
+  global_template->Set(String::New("readline"),
+                       FunctionTemplate::New(ReadLine));
    global_template->Set(String::New("load"), FunctionTemplate::New(Load));
    global_template->Set(String::New("quit"), FunctionTemplate::New(Quit));
    global_template->Set(String::New("version"),  
FunctionTemplate::New(Version));
@@ -596,6 +608,8 @@
                         FunctionTemplate::New(Shell::Write));
    global_template->Set(String::New("read"),
                         FunctionTemplate::New(Shell::Read));
+  global_template->Set(String::New("readline"),
+                       FunctionTemplate::New(Shell::ReadLine));
    global_template->Set(String::New("load"),
                         FunctionTemplate::New(Shell::Load));
    global_template->Set(String::New("yield"),
=======================================
--- /trunk/src/d8.h     Wed Aug 12 07:20:51 2009
+++ /trunk/src/d8.h     Thu Aug 13 05:44:13 2009
@@ -143,6 +143,7 @@
    static Handle<Value> Quit(const Arguments& args);
    static Handle<Value> Version(const Arguments& args);
    static Handle<Value> Read(const Arguments& args);
+  static Handle<Value> ReadLine(const Arguments& args);
    static Handle<Value> Load(const Arguments& args);
    // The OS object on the global object contains methods for performing
    // operating system calls:
=======================================
--- /trunk/src/flag-definitions.h       Wed Aug  5 01:38:10 2009
+++ /trunk/src/flag-definitions.h       Thu Aug 13 05:44:13 2009
@@ -161,6 +161,9 @@
  DEFINE_bool(collect_maps, true,
              "garbage collect maps from which no objects can be reached")

+// v8.cc
+DEFINE_bool(use_idle_notification, true,
+            "Use idle notification to reduce memory footprint.")
  // ic.cc
  DEFINE_bool(use_ic, true, "use inline caching")

=======================================
--- /trunk/src/heap.cc  Wed Aug 12 07:20:51 2009
+++ /trunk/src/heap.cc  Thu Aug 13 05:44:13 2009
@@ -423,6 +423,20 @@
    Heap::symbol_table()->IterateElements(&verifier);
  #endif  // DEBUG
  }
+
+
+void Heap::EnsureFromSpaceIsCommitted() {
+  if (new_space_.CommitFromSpaceIfNeeded()) return;
+
+  // Committing memory to from space failed.
+  // Try shrinking and try again.
+  Shrink();
+  if (new_space_.CommitFromSpaceIfNeeded()) return;
+
+  // Committing memory to from space failed again.
+  // Memory is exhausted and we will die.
+  V8::FatalProcessOutOfMemory("Committing semi space failed.");
+}


  void Heap::PerformGarbageCollection(AllocationSpace space,
@@ -433,7 +447,7 @@
      ASSERT(!allocation_allowed_);
      global_gc_prologue_callback_();
    }
-
+  EnsureFromSpaceIsCommitted();
    if (collector == MARK_COMPACTOR) {
      MarkCompact(tracer);

=======================================
--- /trunk/src/heap.h   Wed Aug  5 01:38:10 2009
+++ /trunk/src/heap.h   Thu Aug 13 05:44:13 2009
@@ -279,6 +279,9 @@
    static Address* NewSpaceAllocationLimitAddress() {
      return new_space_.allocation_limit_address();
    }
+
+  // Uncommit unused semi space.
+  static bool UncommitFromSpace() { return new_space_.UncommitFromSpace();  
}

  #ifdef ENABLE_HEAP_PROTECTION
    // Protect/unprotect the heap by marking all spaces read-only/writable.
@@ -794,6 +797,9 @@
    // Rebuild remembered set in old and map spaces.
    static void RebuildRSets();

+  // Commits from space if it is uncommitted.
+  static void EnsureFromSpaceIsCommitted();
+
    //
    // Support for the API.
    //
=======================================
--- /trunk/src/messages.js      Thu Jul 30 07:48:31 2009
+++ /trunk/src/messages.js      Thu Aug 13 05:44:13 2009
@@ -28,88 +28,36 @@

  // -------------------------------------------------------------------

-const kVowelSounds = {a: true, e: true, i: true, o: true, u: true, y:  
true};
-const kCapitalVowelSounds = {a: true, e: true, i: true, o: true, u: true,
-    h: true, f: true, l: true, m: true, n: true, r: true, s: true, x: true,
-    y: true};
+// Lazily initialized.
+var kVowelSounds = 0;
+var kCapitalVowelSounds = 0;
+

  function GetInstanceName(cons) {
    if (cons.length == 0) {
      return "";
    }
    var first = %StringToLowerCase(StringCharAt.call(cons, 0));
-  var mapping = kVowelSounds;
+  if (kVowelSounds === 0) {
+    kVowelSounds = {a: true, e: true, i: true, o: true, u: true, y: true};
+    kCapitalVowelSounds = {a: true, e: true, i: true, o: true, u: true, h:  
true,
+        f: true, l: true, m: true, n: true, r: true, s: true, x: true, y:  
true};
+  }
+  var vowel_mapping = kVowelSounds;
    if (cons.length > 1 && (StringCharAt.call(cons, 0) != first)) {
      // First char is upper case
      var second = %StringToLowerCase(StringCharAt.call(cons, 1));
      // Second char is upper case
-    if (StringCharAt.call(cons, 1) != second)
-      mapping = kCapitalVowelSounds;
-  }
-  var s = mapping[first] ? "an " : "a ";
+    if (StringCharAt.call(cons, 1) != second) {
+      vowel_mapping = kCapitalVowelSounds;
+    }
+  }
+  var s = vowel_mapping[first] ? "an " : "a ";
    return s + cons;
  }


-const kMessages = {
-  // Error
-  cyclic_proto:                 "Cyclic __proto__ value",
-  // TypeError
-  unexpected_token:             "Unexpected token %0",
-  unexpected_token_number:      "Unexpected number",
-  unexpected_token_string:      "Unexpected string",
-  unexpected_token_identifier:  "Unexpected identifier",
-  unexpected_eos:               "Unexpected end of input",
-  malformed_regexp:             "Invalid regular expression: /%0/: %1",
-  unterminated_regexp:          "Invalid regular expression: missing /",
-  regexp_flags:                 "Cannot supply flags when constructing one  
RegExp from another",
-  invalid_lhs_in_assignment:    "Invalid left-hand side in assignment",
-  invalid_lhs_in_for_in:        "Invalid left-hand side in for-in",
-  invalid_lhs_in_postfix_op:    "Invalid left-hand side expression in  
postfix operation",
-  invalid_lhs_in_prefix_op:     "Invalid left-hand side expression in  
prefix operation",
-  multiple_defaults_in_switch:  "More than one default clause in switch  
statement",
-  newline_after_throw:          "Illegal newline after throw",
-  redeclaration:                "%0 '%1' has already been declared",
-  no_catch_or_finally:          "Missing catch or finally after try",
-  unknown_label:                "Undefined label '%0'",
-  uncaught_exception:           "Uncaught %0",
-  stack_trace:                  "Stack Trace:\n%0",
-  called_non_callable:          "%0 is not a function",
-  undefined_method:             "Object %1 has no method '%0'",
-  property_not_function:        "Property '%0' of object %1 is not a  
function",
-  cannot_convert_to_primitive:  "Cannot convert object to primitive value",
-  not_constructor:              "%0 is not a constructor",
-  not_defined:                  "%0 is not defined",
-  non_object_property_load:     "Cannot read property '%0' of %1",
-  non_object_property_store:    "Cannot set property '%0' of %1",
-  non_object_property_call:     "Cannot call method '%0' of %1",
-  with_expression:              "%0 has no properties",
-  illegal_invocation:           "Illegal invocation",
-  no_setter_in_callback:        "Cannot set property %0 of %1 which has  
only a getter",
-  apply_non_function:           "Function.prototype.apply was called  
on %0, which is a %1 and not a function",
-  apply_wrong_args:             "Function.prototype.apply: Arguments list  
has wrong type",
-  invalid_in_operator_use:      "Cannot use 'in' operator to search  
for '%0' in %1",
-  instanceof_function_expected: "Expecting a function in instanceof check,  
but got %0",
-  instanceof_nonobject_proto:   "Function has non-object prototype '%0' in  
instanceof check",
-  null_to_object:               "Cannot convert null to object",
-  reduce_no_initial:            "Reduce of empty array with no initial  
value",
-  // RangeError
-  invalid_array_length:         "Invalid array length",
-  stack_overflow:               "Maximum call stack size exceeded",
-  apply_overflow:               "Function.prototype.apply cannot  
support %0 arguments",
-  // SyntaxError
-  unable_to_parse:              "Parse error",
-  duplicate_regexp_flag:        "Duplicate RegExp flag %0",
-  invalid_regexp:               "Invalid RegExp pattern /%0/",
-  illegal_break:                "Illegal break statement",
-  illegal_continue:             "Illegal continue statement",
-  illegal_return:               "Illegal return statement",
-  error_loading_debugger:       "Error loading debugger %0",
-  no_input_to_regexp:           "No input to %0",
-  result_not_primitive:         "Result of %0 must be a primitive, was %1",
-  invalid_json:                 "String '%0' is not valid JSON",
-  circular_structure:           "Converting circular structure to JSON"
-};
+var kMessages = 0;


  function FormatString(format, args) {
@@ -161,6 +109,67 @@

  // Helper functions; called from the runtime system.
  function FormatMessage(message) {
+  if (kMessages === 0) {
+    kMessages = {
+      // Error
+      cyclic_proto:                 "Cyclic __proto__ value",
+      // TypeError
+      unexpected_token:             "Unexpected token %0",
+      unexpected_token_number:      "Unexpected number",
+      unexpected_token_string:      "Unexpected string",
+      unexpected_token_identifier:  "Unexpected identifier",
+      unexpected_eos:               "Unexpected end of input",
+      malformed_regexp:             "Invalid regular expression: /%0/: %1",
+      unterminated_regexp:          "Invalid regular expression: missing  
/",
+      regexp_flags:                 "Cannot supply flags when constructing  
one RegExp from another",
+      invalid_lhs_in_assignment:    "Invalid left-hand side in assignment",
+      invalid_lhs_in_for_in:        "Invalid left-hand side in for-in",
+      invalid_lhs_in_postfix_op:    "Invalid left-hand side expression in  
postfix operation",
+      invalid_lhs_in_prefix_op:     "Invalid left-hand side expression in  
prefix operation",
+      multiple_defaults_in_switch:  "More than one default clause in  
switch statement",
+      newline_after_throw:          "Illegal newline after throw",
+      redeclaration:                "%0 '%1' has already been declared",
+      no_catch_or_finally:          "Missing catch or finally after try",
+      unknown_label:                "Undefined label '%0'",
+      uncaught_exception:           "Uncaught %0",
+      stack_trace:                  "Stack Trace:\n%0",
+      called_non_callable:          "%0 is not a function",
+      undefined_method:             "Object %1 has no method '%0'",
+      property_not_function:        "Property '%0' of object %1 is not a  
function",
+      cannot_convert_to_primitive:  "Cannot convert object to primitive  
value",
+      not_constructor:              "%0 is not a constructor",
+      not_defined:                  "%0 is not defined",
+      non_object_property_load:     "Cannot read property '%0' of %1",
+      non_object_property_store:    "Cannot set property '%0' of %1",
+      non_object_property_call:     "Cannot call method '%0' of %1",
+      with_expression:              "%0 has no properties",
+      illegal_invocation:           "Illegal invocation",
+      no_setter_in_callback:        "Cannot set property %0 of %1 which  
has only a getter",
+      apply_non_function:           "Function.prototype.apply was called  
on %0, which is a %1 and not a function",
+      apply_wrong_args:             "Function.prototype.apply: Arguments  
list has wrong type",
+      invalid_in_operator_use:      "Cannot use 'in' operator to search  
for '%0' in %1",
+      instanceof_function_expected: "Expecting a function in instanceof  
check, but got %0",
+      instanceof_nonobject_proto:   "Function has non-object  
prototype '%0' in instanceof check",
+      null_to_object:               "Cannot convert null to object",
+      reduce_no_initial:            "Reduce of empty array with no initial  
value",
+      // RangeError
+      invalid_array_length:         "Invalid array length",
+      stack_overflow:               "Maximum call stack size exceeded",
+      apply_overflow:               "Function.prototype.apply cannot  
support %0 arguments",
+      // SyntaxError
+      unable_to_parse:              "Parse error",
+      duplicate_regexp_flag:        "Duplicate RegExp flag %0",
+      invalid_regexp:               "Invalid RegExp pattern /%0/",
+      illegal_break:                "Illegal break statement",
+      illegal_continue:             "Illegal continue statement",
+      illegal_return:               "Illegal return statement",
+      error_loading_debugger:       "Error loading debugger %0",
+      no_input_to_regexp:           "No input to %0",
+      result_not_primitive:         "Result of %0 must be a primitive,  
was %1",
+      invalid_json:                 "String '%0' is not valid JSON",
+      circular_structure:           "Converting circular structure to JSON"
+    };
+  }
    var format = kMessages[message.type];
    if (!format) return "<unknown message " + message.type + ">";
    return FormatString(format, message.args);
=======================================
--- /trunk/src/runtime.cc       Wed Aug  5 01:38:10 2009
+++ /trunk/src/runtime.cc       Thu Aug 13 05:44:13 2009
@@ -4973,10 +4973,12 @@

    // Compile source string in the global context.
    Handle<Context> context(Top::context()->global_context());
+  Compiler::ValidationState validate = (is_json->IsTrue())
+    ? Compiler::VALIDATE_JSON : Compiler::DONT_VALIDATE_JSON;
    Handle<JSFunction> boilerplate = Compiler::CompileEval(source,
                                                           context,
                                                           true,
-                                                          
is_json->IsTrue());
+                                                         validate);
    if (boilerplate.is_null()) return Failure::Exception();
    Handle<JSFunction> fun =
        Factory::NewFunctionFromBoilerplate(boilerplate, context);
@@ -5000,8 +5002,11 @@
    bool is_global = context->IsGlobalContext();

    // Compile source string in the current context.
-  Handle<JSFunction> boilerplate =
-      Compiler::CompileEval(source, context, is_global, false);
+  Handle<JSFunction> boilerplate = Compiler::CompileEval(
+      source,
+      context,
+      is_global,
+      Compiler::DONT_VALIDATE_JSON);
    if (boilerplate.is_null()) return Failure::Exception();
    Handle<JSFunction> fun =
      Factory::NewFunctionFromBoilerplate(boilerplate, context);
@@ -7043,7 +7048,7 @@
        Compiler::CompileEval(function_source,
                              context,
                              context->IsGlobalContext(),
-                            false);
+                            Compiler::DONT_VALIDATE_JSON);
    if (boilerplate.is_null()) return Failure::Exception();
    Handle<JSFunction> compiled_function =
        Factory::NewFunctionFromBoilerplate(boilerplate, context);
@@ -7111,7 +7116,7 @@
        Handle<JSFunction>(Compiler::CompileEval(source,
                                                 context,
                                                 true,
-                                               false));
+                                                
Compiler::DONT_VALIDATE_JSON));
    if (boilerplate.is_null()) return Failure::Exception();
    Handle<JSFunction> compiled_function =
        Handle<JSFunction>(Factory::NewFunctionFromBoilerplate(boilerplate,
=======================================
--- /trunk/src/spaces.cc        Wed Aug 12 07:20:51 2009
+++ /trunk/src/spaces.cc        Thu Aug 13 05:44:13 2009
@@ -340,6 +340,17 @@
    return true;
  }

+bool MemoryAllocator::UncommitBlock(Address start, size_t size) {
+  ASSERT(start != NULL);
+  ASSERT(size > 0);
+  ASSERT(initial_chunk_ != NULL);
+  ASSERT(InInitialChunk(start));
+  ASSERT(InInitialChunk(start + size - 1));
+
+  if (!initial_chunk_->Uncommit(start, size)) return false;
+  Counters::memory_allocated.Decrement(size);
+  return true;
+}

  Page* MemoryAllocator::InitializePagesInChunk(int chunk_id, int  
pages_in_chunk,
                                                PagedSpace* owner) {
@@ -1039,6 +1050,26 @@
  #endif


+bool SemiSpace::Commit() {
+  ASSERT(!is_committed());
+  if (!MemoryAllocator::CommitBlock(start_, capacity_, executable())) {
+    return false;
+  }
+  committed_ = true;
+  return true;
+}
+
+
+bool SemiSpace::Uncommit() {
+  ASSERT(is_committed());
+  if (!MemoryAllocator::UncommitBlock(start_, capacity_)) {
+    return false;
+  }
+  committed_ = false;
+  return true;
+}
+
+
  //  
-----------------------------------------------------------------------------
  // SemiSpace implementation

@@ -1053,18 +1084,15 @@
    // addresses.
    capacity_ = initial_capacity;
    maximum_capacity_ = maximum_capacity;
-
-  if (!MemoryAllocator::CommitBlock(start, capacity_, executable())) {
-    return false;
-  }
+  committed_ = false;

    start_ = start;
    address_mask_ = ~(maximum_capacity - 1);
    object_mask_ = address_mask_ | kHeapObjectTag;
    object_expected_ = reinterpret_cast<uintptr_t>(start) | kHeapObjectTag;
-
    age_mark_ = start_;
-  return true;
+
+  return Commit();
  }


@@ -1076,7 +1104,7 @@

  bool SemiSpace::Grow() {
    // Commit 50% extra space but only up to maximum capacity.
-  int extra = capacity_/2;
+  int extra = RoundUp(capacity_ / 2, OS::AllocateAlignment());
    if (capacity_ + extra > maximum_capacity_) {
      extra = maximum_capacity_ - capacity_;
    }
=======================================
--- /trunk/src/spaces.h Wed Aug 12 07:20:51 2009
+++ /trunk/src/spaces.h Thu Aug 13 05:44:13 2009
@@ -367,6 +367,13 @@
    // and false otherwise.
    static bool CommitBlock(Address start, size_t size, Executability  
executable);

+
+  // Uncommit a contiguous block of memory [start..(start+size)[.
+  // start is not NULL, the size is greater than zero, and the
+  // block is contained in the initial chunk.  Returns true if it succeeded
+  // and false otherwise.
+  static bool UncommitBlock(Address start, size_t size);
+
    // Attempts to allocate the requested (non-zero) number of pages from the
    // OS.  Fewer pages might be allocated than requested. If it fails to
    // allocate memory for the OS or cannot allocate a single page, this
@@ -1034,6 +1041,10 @@
      UNREACHABLE();
      return 0;
    }
+
+  bool is_committed() { return committed_; }
+  bool Commit();
+  bool Uncommit();

  #ifdef DEBUG
    virtual void Print();
@@ -1058,6 +1069,8 @@
    uintptr_t object_mask_;
    uintptr_t object_expected_;

+  bool committed_;
+
   public:
    TRACK_MEMORY("SemiSpace")
  };
@@ -1249,6 +1262,17 @@
    void RecordAllocation(HeapObject* obj);
    void RecordPromotion(HeapObject* obj);
  #endif
+
+  // Return whether the operation succeded.
+  bool CommitFromSpaceIfNeeded() {
+    if (from_space_.is_committed()) return true;
+    return from_space_.Commit();
+  }
+
+  bool UncommitFromSpace() {
+    if (!from_space_.is_committed()) return true;
+    return from_space_.Uncommit();
+  }

   private:
    // The current and maximum capacities of a semispace.
=======================================
--- /trunk/src/uri.js   Thu Mar 12 00:19:55 2009
+++ /trunk/src/uri.js   Thu Aug 13 05:44:13 2009
@@ -39,6 +39,10 @@


  function URIEncodeOctets(octets, result, index) {
+  if (hexCharCodeArray === 0) {
+    hexCharCodeArray = [48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+                        65, 66, 67, 68, 69, 70];
+  }
    index = URIAddEncodedOctetToBuffer(octets[0], result, index);
    if (octets[1]) index = URIAddEncodedOctetToBuffer(octets[1], result,  
index);
    if (octets[2]) index = URIAddEncodedOctetToBuffer(octets[2], result,  
index);
@@ -316,11 +320,9 @@
  }


-const hexCharArray = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
-                      "A", "B", "C", "D", "E", "F"];
-
-const hexCharCodeArray = [48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
-                          65, 66, 67, 68, 69, 70];
+// Lazily initialized.
+var hexCharArray = 0;
+var hexCharCodeArray = 0;


  function HexValueOf(c) {
@@ -341,6 +343,10 @@
  // 64 -> 0040, 62234 -> F31A.
  function CharCodeToHex4Str(cc) {
    var r = "";
+  if (hexCharArray === 0) {
+    hexCharArray = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
+                    "A", "B", "C", "D", "E", "F"];
+  }
    for (var i = 0; i < 4; ++i) {
      var c = hexCharArray[cc & 0x0F];
      r = c + r;
=======================================
--- /trunk/src/v8.cc    Tue Jun 16 02:43:10 2009
+++ /trunk/src/v8.cc    Thu Aug 13 05:44:13 2009
@@ -155,6 +155,15 @@
    lo = 18273 * (lo & 0xFFFF) + (lo >> 16);
    return (hi << 16) + (lo & 0xFFFF);
  }
+
+void V8::IdleNotification(bool is_high_priority) {
+  if (!FLAG_use_idle_notification) return;
+  // Ignore high priority instances of V8.
+  if (is_high_priority) return;
+
+  // Uncommit unused memory in new space.
+  Heap::UncommitFromSpace();
+}


  Smi* V8::RandomPositiveSmi() {
=======================================
--- /trunk/src/v8.h     Mon Jun 29 01:26:34 2009
+++ /trunk/src/v8.h     Thu Aug 13 05:44:13 2009
@@ -99,6 +99,9 @@
    static uint32_t Random();
    static Smi* RandomPositiveSmi();

+  // Idle notification directly from the API.
+  static void IdleNotification(bool is_high_priority);
+
   private:
    // True if engine is currently running
    static bool is_running_;
=======================================
--- /trunk/src/version.cc       Wed Aug 12 07:20:51 2009
+++ /trunk/src/version.cc       Thu Aug 13 05:44:13 2009
@@ -34,7 +34,7 @@
  // cannot be changed without changing the SCons build script.
  #define MAJOR_VERSION     1
  #define MINOR_VERSION     3
-#define BUILD_NUMBER      3
+#define BUILD_NUMBER      4
  #define PATCH_LEVEL       0
  #define CANDIDATE_VERSION false

=======================================
--- /trunk/src/x64/codegen-x64.cc       Wed Aug 12 07:20:51 2009
+++ /trunk/src/x64/codegen-x64.cc       Thu Aug 13 05:44:13 2009
@@ -5258,6 +5258,58 @@
        }
        break;

+    case Token::SHL:
+      if (reversed) {
+        Result constant_operand(value);
+        LikelySmiBinaryOperation(op, &constant_operand, operand,
+                                 overwrite_mode);
+      } else {
+        // Only the least significant 5 bits of the shift value are used.
+        // In the slow case, this masking is done inside the runtime call.
+        int shift_value = int_value & 0x1f;
+        operand->ToRegister();
+        if (shift_value == 0) {
+          // Spill operand so it can be overwritten in the slow case.
+          frame_->Spill(operand->reg());
+          DeferredInlineSmiOperation* deferred =
+              new DeferredInlineSmiOperation(op,
+                                             operand->reg(),
+                                             operand->reg(),
+                                             smi_value,
+                                             overwrite_mode);
+          __ testl(operand->reg(), Immediate(kSmiTagMask));
+          deferred->Branch(not_zero);
+          deferred->BindExit();
+          frame_->Push(operand);
+        } else {
+          // Use a fresh temporary for nonzero shift values.
+          Result answer = allocator()->Allocate();
+          ASSERT(answer.is_valid());
+          DeferredInlineSmiOperation* deferred =
+              new DeferredInlineSmiOperation(op,
+                                             answer.reg(),
+                                             operand->reg(),
+                                             smi_value,
+                                             overwrite_mode);
+          __ testl(operand->reg(), Immediate(kSmiTagMask));
+          deferred->Branch(not_zero);
+          __ movl(answer.reg(), operand->reg());
+          ASSERT(kSmiTag == 0);  // adjust code if not the case
+          // We do no shifts, only the Smi conversion, if shift_value is 1.
+          if (shift_value > 1) {
+            __ shll(answer.reg(), Immediate(shift_value - 1));
+          }
+          // Convert int result to Smi, checking that it is in int range.
+          ASSERT(kSmiTagSize == 1);  // adjust code if not the case
+          __ addl(answer.reg(), answer.reg());
+          deferred->Branch(overflow);
+          deferred->BindExit();
+          operand->Unuse();
+          frame_->Push(&answer);
+        }
+      }
+      break;
+
      case Token::BIT_OR:
      case Token::BIT_XOR:
      case Token::BIT_AND: {
@@ -6013,6 +6065,8 @@
          __ testl(key.reg(),
                   Immediate(static_cast<uint32_t>(kSmiTagMask |  
0x80000000U)));
          deferred->Branch(not_zero);
+        // Ensure that the smi is zero-extended.  This is not guaranteed.
+        __ movl(key.reg(), key.reg());

          // Check that the receiver is not a smi.
          __ testl(receiver.reg(), Immediate(kSmiTagMask));
@@ -7172,14 +7226,14 @@
    __ jmp(&done);

    __ bind(&load_smi_1);
-  __ sar(kScratchRegister, Immediate(kSmiTagSize));
+  __ sarl(kScratchRegister, Immediate(kSmiTagSize));
    __ push(kScratchRegister);
    __ fild_s(Operand(rsp, 0));
    __ pop(kScratchRegister);
    __ jmp(&done_load_1);

    __ bind(&load_smi_2);
-  __ sar(kScratchRegister, Immediate(kSmiTagSize));
+  __ sarl(kScratchRegister, Immediate(kSmiTagSize));
    __ push(kScratchRegister);
    __ fild_s(Operand(rsp, 0));
    __ pop(kScratchRegister);
@@ -7534,7 +7588,7 @@
          __ j(negative, &non_smi_result);
        }
        // Tag smi result and return.
-      ASSERT(kSmiTagSize == times_2);  // adjust code if not the case
+      ASSERT(kSmiTagSize == 1);  // adjust code if not the case
        __ lea(rax, Operand(rax, rax, times_1, kSmiTag));
        __ ret(2 * kPointerSize);

=======================================
--- /trunk/src/x64/disasm-x64.cc        Wed Aug  5 01:38:10 2009
+++ /trunk/src/x64/disasm-x64.cc        Thu Aug 13 05:44:13 2009
@@ -105,7 +105,6 @@
  static ByteMnemonic zero_operands_instr[] = {
    { 0xC3, UNSET_OP_ORDER, "ret" },
    { 0xC9, UNSET_OP_ORDER, "leave" },
-  { 0x90, UNSET_OP_ORDER, "nop" },
    { 0xF4, UNSET_OP_ORDER, "hlt" },
    { 0xCC, UNSET_OP_ORDER, "int3" },
    { 0x60, UNSET_OP_ORDER, "pushad" },
@@ -1425,7 +1424,7 @@
            default:
              UNREACHABLE();
          }
-        AppendToBuffer("test%c rax,0x%"V8_PTR_PREFIX"ux",
+        AppendToBuffer("test%c rax,0x%"V8_PTR_PREFIX"x",
                         operand_size_code(),
                         value);
          break;
=======================================
--- /trunk/test/mjsunit/json.js Mon Apr 27 02:26:21 2009
+++ /trunk/test/mjsunit/json.js Thu Aug 13 05:44:13 2009
@@ -195,3 +195,13 @@

  assertEquals(undefined, JSON.stringify(undefined));
  assertEquals(undefined, JSON.stringify(function () { }));
+
+function checkIllegal(str) {
+  assertThrows(function () { JSON.parse(str); }, SyntaxError);
+}
+
+checkIllegal('1); throw "foo"; (1');
+
+var x = 0;
+eval("(1); x++; (1)");
+checkIllegal('1); x++; (1');

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

Reply via email to