summaryrefslogtreecommitdiff
path: root/deps/v8/src
diff options
context:
space:
mode:
authorRyan <ry@tinyclouds.org>2009-08-13 15:06:34 +0200
committerRyan <ry@tinyclouds.org>2009-08-13 15:06:34 +0200
commit9dc621f83a6ea79e95b7b9780df164df0b28bac7 (patch)
tree1c6f3984833bca70bf7d7bad9460c744bed16051 /deps/v8/src
parentdd5ae3183b090755feb8fa67c65de25197f3e8e0 (diff)
downloadnode-9dc621f83a6ea79e95b7b9780df164df0b28bac7.tar.gz
Upgrade v8 to 1.3.4
Diffstat (limited to 'deps/v8/src')
-rw-r--r--deps/v8/src/api.cc8
-rw-r--r--deps/v8/src/compiler.cc31
-rw-r--r--deps/v8/src/compiler.h4
-rw-r--r--deps/v8/src/d8.cc20
-rw-r--r--deps/v8/src/d8.h1
-rw-r--r--deps/v8/src/flag-definitions.h3
-rw-r--r--deps/v8/src/heap.cc16
-rw-r--r--deps/v8/src/heap.h6
-rw-r--r--deps/v8/src/messages.js143
-rw-r--r--deps/v8/src/runtime.cc15
-rw-r--r--deps/v8/src/spaces.cc42
-rw-r--r--deps/v8/src/spaces.h24
-rw-r--r--deps/v8/src/uri.js16
-rw-r--r--deps/v8/src/v8.cc9
-rw-r--r--deps/v8/src/v8.h3
-rw-r--r--deps/v8/src/version.cc2
-rw-r--r--deps/v8/src/x64/codegen-x64.cc60
-rw-r--r--deps/v8/src/x64/disasm-x64.cc3
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;