diff options
author | Ryan <ry@tinyclouds.org> | 2009-08-13 15:06:34 +0200 |
---|---|---|
committer | Ryan <ry@tinyclouds.org> | 2009-08-13 15:06:34 +0200 |
commit | 9dc621f83a6ea79e95b7b9780df164df0b28bac7 (patch) | |
tree | 1c6f3984833bca70bf7d7bad9460c744bed16051 /deps/v8/src | |
parent | dd5ae3183b090755feb8fa67c65de25197f3e8e0 (diff) | |
download | node-9dc621f83a6ea79e95b7b9780df164df0b28bac7.tar.gz |
Upgrade v8 to 1.3.4
Diffstat (limited to 'deps/v8/src')
-rw-r--r-- | deps/v8/src/api.cc | 8 | ||||
-rw-r--r-- | deps/v8/src/compiler.cc | 31 | ||||
-rw-r--r-- | deps/v8/src/compiler.h | 4 | ||||
-rw-r--r-- | deps/v8/src/d8.cc | 20 | ||||
-rw-r--r-- | deps/v8/src/d8.h | 1 | ||||
-rw-r--r-- | deps/v8/src/flag-definitions.h | 3 | ||||
-rw-r--r-- | deps/v8/src/heap.cc | 16 | ||||
-rw-r--r-- | deps/v8/src/heap.h | 6 | ||||
-rw-r--r-- | deps/v8/src/messages.js | 143 | ||||
-rw-r--r-- | deps/v8/src/runtime.cc | 15 | ||||
-rw-r--r-- | deps/v8/src/spaces.cc | 42 | ||||
-rw-r--r-- | deps/v8/src/spaces.h | 24 | ||||
-rw-r--r-- | deps/v8/src/uri.js | 16 | ||||
-rw-r--r-- | deps/v8/src/v8.cc | 9 | ||||
-rw-r--r-- | deps/v8/src/v8.h | 3 | ||||
-rw-r--r-- | deps/v8/src/version.cc | 2 | ||||
-rw-r--r-- | deps/v8/src/x64/codegen-x64.cc | 60 | ||||
-rw-r--r-- | deps/v8/src/x64/disasm-x64.cc | 3 |
18 files changed, 297 insertions, 109 deletions
diff --git a/deps/v8/src/api.cc b/deps/v8/src/api.cc index d02a2e448..0dc4fd7c7 100644 --- a/deps/v8/src/api.cc +++ b/deps/v8/src/api.cc @@ -2558,6 +2558,10 @@ bool v8::V8::Dispose() { } +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 @@ Persistent<Context> v8::Context::New( 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; diff --git a/deps/v8/src/compiler.cc b/deps/v8/src/compiler.cc index f0d97fecd..5607f2962 100644 --- a/deps/v8/src/compiler.cc +++ b/deps/v8/src/compiler.cc @@ -102,7 +102,7 @@ static Handle<Code> MakeCode(FunctionLiteral* literal, 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 bool IsValidJSON(FunctionLiteral* lit) { 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 @@ static Handle<JSFunction> MakeFunction(bool is_global, 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 @@ static Handle<JSFunction> MakeFunction(bool is_global, // 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 @@ Handle<JSFunction> Compiler::Compile(Handle<String> source, // 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::Compile(Handle<String> source, 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 @@ Handle<JSFunction> Compiler::CompileEval(Handle<String> source, 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); } } diff --git a/deps/v8/src/compiler.h b/deps/v8/src/compiler.h index 9f02a8d3c..579970b3c 100644 --- a/deps/v8/src/compiler.h +++ b/deps/v8/src/compiler.h @@ -48,6 +48,8 @@ namespace internal { 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 @@ class Compiler : public AllStatic { 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 diff --git a/deps/v8/src/d8.cc b/deps/v8/src/d8.cc index be3615b8e..708228085 100644 --- a/deps/v8/src/d8.cc +++ b/deps/v8/src/d8.cc @@ -167,9 +167,6 @@ Handle<Value> Shell::Write(const Arguments& args) { 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")); @@ -182,6 +179,19 @@ Handle<Value> Shell::Read(const Arguments& args) { } +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) { for (int i = 0; i < args.Length(); i++) { HandleScope handle_scope; @@ -404,6 +414,8 @@ void Shell::Initialize() { 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 @@ void ShellThread::Run() { 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"), diff --git a/deps/v8/src/d8.h b/deps/v8/src/d8.h index 1bcc879d2..c93ea461d 100644 --- a/deps/v8/src/d8.h +++ b/deps/v8/src/d8.h @@ -143,6 +143,7 @@ class Shell: public i::AllStatic { 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: diff --git a/deps/v8/src/flag-definitions.h b/deps/v8/src/flag-definitions.h index 3df11f756..c05feb4da 100644 --- a/deps/v8/src/flag-definitions.h +++ b/deps/v8/src/flag-definitions.h @@ -161,6 +161,9 @@ DEFINE_bool(trace_gc_verbose, false, 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") diff --git a/deps/v8/src/heap.cc b/deps/v8/src/heap.cc index 8ea1136aa..f8d22a2e3 100644 --- a/deps/v8/src/heap.cc +++ b/deps/v8/src/heap.cc @@ -425,6 +425,20 @@ static void VerifySymbolTable() { } +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, GarbageCollector collector, GCTracer* tracer) { @@ -433,7 +447,7 @@ void Heap::PerformGarbageCollection(AllocationSpace space, ASSERT(!allocation_allowed_); global_gc_prologue_callback_(); } - + EnsureFromSpaceIsCommitted(); if (collector == MARK_COMPACTOR) { MarkCompact(tracer); diff --git a/deps/v8/src/heap.h b/deps/v8/src/heap.h index 30522dc8d..179f9af10 100644 --- a/deps/v8/src/heap.h +++ b/deps/v8/src/heap.h @@ -280,6 +280,9 @@ class Heap : public AllStatic { 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. static void Protect(); @@ -794,6 +797,9 @@ class Heap : public AllStatic { // 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. // diff --git a/deps/v8/src/messages.js b/deps/v8/src/messages.js index fd505ff67..8328fe5c4 100644 --- a/deps/v8/src/messages.js +++ b/deps/v8/src/messages.js @@ -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; + if (StringCharAt.call(cons, 1) != second) { + vowel_mapping = kCapitalVowelSounds; + } } - var s = mapping[first] ? "an " : "a "; + 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 @@ function MakeGenericError(constructor, type, args) { // 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); diff --git a/deps/v8/src/runtime.cc b/deps/v8/src/runtime.cc index 56e9f85eb..0da4be821 100644 --- a/deps/v8/src/runtime.cc +++ b/deps/v8/src/runtime.cc @@ -4973,10 +4973,12 @@ static Object* Runtime_CompileString(Arguments args) { // 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 @@ static Object* CompileDirectEval(Handle<String> source) { 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 @@ static Object* Runtime_DebugEvaluate(Arguments args) { 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 @@ static Object* Runtime_DebugEvaluateGlobal(Arguments args) { 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, diff --git a/deps/v8/src/spaces.cc b/deps/v8/src/spaces.cc index 6283bbad9..9f266cb0e 100644 --- a/deps/v8/src/spaces.cc +++ b/deps/v8/src/spaces.cc @@ -340,6 +340,17 @@ bool MemoryAllocator::CommitBlock(Address start, 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 @@ void NewSpace::Verify() { #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 @@ bool SemiSpace::Setup(Address start, // 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 @@ void SemiSpace::TearDown() { 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_; } diff --git a/deps/v8/src/spaces.h b/deps/v8/src/spaces.h index 4df3388e9..4760a4240 100644 --- a/deps/v8/src/spaces.h +++ b/deps/v8/src/spaces.h @@ -367,6 +367,13 @@ class MemoryAllocator : public AllStatic { // 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 @@ -1035,6 +1042,10 @@ class SemiSpace : public Space { return 0; } + bool is_committed() { return committed_; } + bool Commit(); + bool Uncommit(); + #ifdef DEBUG virtual void Print(); virtual void Verify(); @@ -1058,6 +1069,8 @@ class SemiSpace : public Space { uintptr_t object_mask_; uintptr_t object_expected_; + bool committed_; + public: TRACK_MEMORY("SemiSpace") }; @@ -1250,6 +1263,17 @@ class NewSpace : public Space { 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. int capacity_; diff --git a/deps/v8/src/uri.js b/deps/v8/src/uri.js index fe659aa1a..0dfe7652a 100644 --- a/deps/v8/src/uri.js +++ b/deps/v8/src/uri.js @@ -39,6 +39,10 @@ function URIAddEncodedOctetToBuffer(octet, result, index) { 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 @@ function URIEncodeComponent(component) { } -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 @@ function HexValueOf(c) { // 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; diff --git a/deps/v8/src/v8.cc b/deps/v8/src/v8.cc index 72f74aa1d..00e0e6e6d 100644 --- a/deps/v8/src/v8.cc +++ b/deps/v8/src/v8.cc @@ -156,6 +156,15 @@ uint32_t V8::Random() { 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() { uint32_t random = Random(); diff --git a/deps/v8/src/v8.h b/deps/v8/src/v8.h index 2cfce3d19..1ca3245b9 100644 --- a/deps/v8/src/v8.h +++ b/deps/v8/src/v8.h @@ -99,6 +99,9 @@ class V8 : public AllStatic { 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_; diff --git a/deps/v8/src/version.cc b/deps/v8/src/version.cc index b141120a7..7bc52a849 100644 --- a/deps/v8/src/version.cc +++ b/deps/v8/src/version.cc @@ -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 diff --git a/deps/v8/src/x64/codegen-x64.cc b/deps/v8/src/x64/codegen-x64.cc index 58c5b4779..b3df929d7 100644 --- a/deps/v8/src/x64/codegen-x64.cc +++ b/deps/v8/src/x64/codegen-x64.cc @@ -5258,6 +5258,58 @@ void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op, } 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 @@ void Reference::SetValue(InitState init_state) { __ 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 @@ void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm) { __ 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 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) { __ 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); diff --git a/deps/v8/src/x64/disasm-x64.cc b/deps/v8/src/x64/disasm-x64.cc index cc8365c9b..d8d6dbb23 100644 --- a/deps/v8/src/x64/disasm-x64.cc +++ b/deps/v8/src/x64/disasm-x64.cc @@ -105,7 +105,6 @@ static ByteMnemonic two_operands_instr[] = { 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 @@ int DisassemblerX64::InstructionDecode(v8::internal::Vector<char> out_buffer, 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; |