Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/deps
diff options
context:
space:
mode:
authorRyan Dahl <ry@tinyclouds.org>2010-10-06 02:25:07 +0400
committerRyan Dahl <ry@tinyclouds.org>2010-10-06 02:25:07 +0400
commit7fca10133861348417f33dac2d656cbfd9d1bb0d (patch)
tree91ce5d67766de7f3ce43c24d552238541f764925 /deps
parentdbf0d6bb70902fba80b10adccf3f54fe9cf5beb7 (diff)
Upgrade V8 to 2.4.8
Diffstat (limited to 'deps')
-rw-r--r--deps/v8/ChangeLog8
-rw-r--r--deps/v8/src/api.cc8
-rw-r--r--deps/v8/src/arm/ic-arm.cc3
-rwxr-xr-xdeps/v8/src/compiler.cc12
-rw-r--r--deps/v8/src/compiler.h3
-rw-r--r--deps/v8/src/handles.cc2
-rw-r--r--deps/v8/src/ia32/codegen-ia32.cc47
-rw-r--r--deps/v8/src/ia32/ic-ia32.cc28
-rw-r--r--deps/v8/src/ic.cc10
-rw-r--r--deps/v8/src/ic.h3
-rw-r--r--deps/v8/src/jsregexp.cc4
-rw-r--r--deps/v8/src/liveedit.cc13
-rw-r--r--deps/v8/src/log-utils.h1
-rw-r--r--deps/v8/src/objects-visiting.h6
-rw-r--r--deps/v8/src/objects.cc5
-rw-r--r--deps/v8/src/objects.h2
-rw-r--r--deps/v8/src/parser.cc284
-rw-r--r--deps/v8/src/parser.h307
-rw-r--r--deps/v8/src/profile-generator.cc49
-rw-r--r--deps/v8/src/profile-generator.h4
-rw-r--r--deps/v8/src/v8-counters.h2
-rw-r--r--deps/v8/src/version.cc4
-rw-r--r--deps/v8/src/x64/builtins-x64.cc2
-rw-r--r--deps/v8/src/x64/code-stubs-x64.cc2
-rw-r--r--deps/v8/src/x64/codegen-x64.cc14
-rw-r--r--deps/v8/src/x64/full-codegen-x64.cc8
-rw-r--r--deps/v8/src/x64/ic-x64.cc5
-rw-r--r--deps/v8/src/x64/macro-assembler-x64.cc10
-rw-r--r--deps/v8/src/x64/macro-assembler-x64.h34
-rw-r--r--deps/v8/test/cctest/cctest.status5
-rw-r--r--deps/v8/test/cctest/test-api.cc154
-rw-r--r--deps/v8/test/cctest/test-heap-profiler.cc18
-rwxr-xr-xdeps/v8/test/cctest/test-macro-assembler-x64.cc14
-rw-r--r--deps/v8/test/cctest/test-regexp.cc12
34 files changed, 652 insertions, 431 deletions
diff --git a/deps/v8/ChangeLog b/deps/v8/ChangeLog
index 134540d3f01..42de2865029 100644
--- a/deps/v8/ChangeLog
+++ b/deps/v8/ChangeLog
@@ -1,3 +1,11 @@
+2010-10-04: Version 2.4.8
+
+ Fixed a bug in ResumeProfilerEx causing it to not always write out the
+ whole snapshot (issue 868).
+
+ Performance improvements on all platforms.
+
+
2010-09-30: Version 2.4.7
Changed the command-line flag --max-new-space-size to be in kB and the
diff --git a/deps/v8/src/api.cc b/deps/v8/src/api.cc
index b7d85c68a11..350410a3cc6 100644
--- a/deps/v8/src/api.cc
+++ b/deps/v8/src/api.cc
@@ -1,4 +1,4 @@
-// Copyright 2009 the V8 project authors. All rights reserved.
+// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@@ -28,6 +28,7 @@
#include "v8.h"
#include "api.h"
+
#include "arguments.h"
#include "bootstrapper.h"
#include "compiler.h"
@@ -36,6 +37,7 @@
#include "global-handles.h"
#include "heap-profiler.h"
#include "messages.h"
+#include "parser.h"
#include "platform.h"
#include "profile-generator-inl.h"
#include "serialize.h"
@@ -1135,13 +1137,13 @@ void ObjectTemplate::SetInternalFieldCount(int value) {
ScriptData* ScriptData::PreCompile(const char* input, int length) {
unibrow::Utf8InputBuffer<> buf(input, length);
- return i::PreParse(i::Handle<i::String>(), &buf, NULL);
+ return i::Parser::PreParse(i::Handle<i::String>(), &buf, NULL);
}
ScriptData* ScriptData::PreCompile(v8::Handle<String> source) {
i::Handle<i::String> str = Utils::OpenHandle(*source);
- return i::PreParse(str, NULL, NULL);
+ return i::Parser::PreParse(str, NULL, NULL);
}
diff --git a/deps/v8/src/arm/ic-arm.cc b/deps/v8/src/arm/ic-arm.cc
index eab4c6e8ed8..7f83d14af90 100644
--- a/deps/v8/src/arm/ic-arm.cc
+++ b/deps/v8/src/arm/ic-arm.cc
@@ -969,7 +969,8 @@ bool LoadIC::PatchInlinedLoad(Address address, Object* map, int offset) {
bool LoadIC::PatchInlinedContextualLoad(Address address,
Object* map,
- Object* cell) {
+ Object* cell,
+ bool is_dont_delete) {
// TODO(<bug#>): implement this.
return false;
}
diff --git a/deps/v8/src/compiler.cc b/deps/v8/src/compiler.cc
index 6ef5a1c50d8..bfb2e21beac 100755
--- a/deps/v8/src/compiler.cc
+++ b/deps/v8/src/compiler.cc
@@ -27,18 +27,20 @@
#include "v8.h"
+#include "compiler.h"
+
#include "bootstrapper.h"
#include "codegen-inl.h"
#include "compilation-cache.h"
-#include "compiler.h"
#include "data-flow.h"
#include "debug.h"
#include "full-codegen.h"
#include "liveedit.h"
#include "oprofile-agent.h"
+#include "parser.h"
#include "rewriter.h"
-#include "scopes.h"
#include "scopeinfo.h"
+#include "scopes.h"
namespace v8 {
namespace internal {
@@ -174,7 +176,7 @@ static Handle<SharedFunctionInfo> MakeFunctionInfo(bool is_global,
// Build AST.
EagerCompilationInfo info(script, is_eval);
FunctionLiteral* lit =
- MakeAST(is_global, script, extension, pre_data, is_json);
+ Parser::MakeAST(is_global, script, extension, pre_data, is_json);
// Check for parse errors.
if (lit == NULL) {
@@ -283,7 +285,7 @@ Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source,
if (pre_data == NULL
&& FLAG_lazy
&& source_length >= FLAG_min_preparse_length) {
- pre_data = PartialPreParse(source, NULL, extension);
+ pre_data = Parser::PartialPreParse(source, NULL, extension);
}
// Create a script object describing the script to be compiled.
@@ -382,7 +384,7 @@ bool Compiler::CompileLazy(CompilationInfo* info) {
// Generate the AST for the lazily compiled function. The AST may be
// NULL in case of parser stack overflow.
- FunctionLiteral* lit = MakeLazyAST(shared);
+ FunctionLiteral* lit = Parser::MakeLazyAST(shared);
// Check for parse errors.
if (lit == NULL) {
diff --git a/deps/v8/src/compiler.h b/deps/v8/src/compiler.h
index ae0d6def6d1..d8eb3a68f40 100644
--- a/deps/v8/src/compiler.h
+++ b/deps/v8/src/compiler.h
@@ -30,13 +30,14 @@
#include "ast.h"
#include "frame-element.h"
-#include "parser.h"
#include "register-allocator.h"
#include "zone.h"
namespace v8 {
namespace internal {
+class ScriptDataImpl;
+
// CompilationInfo encapsulates some information known at compile time. It
// is constructed based on the resources available at compile-time.
class CompilationInfo BASE_EMBEDDED {
diff --git a/deps/v8/src/handles.cc b/deps/v8/src/handles.cc
index 02074925e5b..3fed0bcc0c5 100644
--- a/deps/v8/src/handles.cc
+++ b/deps/v8/src/handles.cc
@@ -175,7 +175,7 @@ static int ExpectedNofPropertiesFromEstimate(int estimate) {
// Inobject slack tracking will reclaim redundant inobject space later,
// so we can afford to adjust the estimate generously.
- return estimate + 6;
+ return estimate + 8;
}
diff --git a/deps/v8/src/ia32/codegen-ia32.cc b/deps/v8/src/ia32/codegen-ia32.cc
index 9c8573cea0c..c006b869514 100644
--- a/deps/v8/src/ia32/codegen-ia32.cc
+++ b/deps/v8/src/ia32/codegen-ia32.cc
@@ -9149,7 +9149,8 @@ class DeferredReferenceGetNamedValue: public DeferredCode {
: dst_(dst),
receiver_(receiver),
name_(name),
- is_contextual_(is_contextual) {
+ is_contextual_(is_contextual),
+ is_dont_delete_(false) {
set_comment(is_contextual
? "[ DeferredReferenceGetNamedValue (contextual)"
: "[ DeferredReferenceGetNamedValue");
@@ -9159,12 +9160,18 @@ class DeferredReferenceGetNamedValue: public DeferredCode {
Label* patch_site() { return &patch_site_; }
+ void set_is_dont_delete(bool value) {
+ ASSERT(is_contextual_);
+ is_dont_delete_ = value;
+ }
+
private:
Label patch_site_;
Register dst_;
Register receiver_;
Handle<String> name_;
bool is_contextual_;
+ bool is_dont_delete_;
};
@@ -9181,8 +9188,8 @@ void DeferredReferenceGetNamedValue::Generate() {
// The call must be followed by:
// - a test eax instruction to indicate that the inobject property
// case was inlined.
- // - a mov ecx instruction to indicate that the contextual property
- // load was inlined.
+ // - a mov ecx or mov edx instruction to indicate that the
+ // contextual property load was inlined.
//
// Store the delta to the map check instruction here in the test
// instruction. Use masm_-> instead of the __ macro since the
@@ -9191,8 +9198,11 @@ void DeferredReferenceGetNamedValue::Generate() {
// Here we use masm_-> instead of the __ macro because this is the
// instruction that gets patched and coverage code gets in the way.
if (is_contextual_) {
- masm_->mov(ecx, -delta_to_patch_site);
+ masm_->mov(is_dont_delete_ ? edx : ecx, -delta_to_patch_site);
__ IncrementCounter(&Counters::named_load_global_inline_miss, 1);
+ if (is_dont_delete_) {
+ __ IncrementCounter(&Counters::dont_delete_hint_miss, 1);
+ }
} else {
masm_->test(eax, Immediate(-delta_to_patch_site));
__ IncrementCounter(&Counters::named_load_inline_miss, 1);
@@ -9436,9 +9446,34 @@ Result CodeGenerator::EmitNamedLoad(Handle<String> name, bool is_contextual) {
}
__ mov(result.reg(),
FieldOperand(result.reg(), JSGlobalPropertyCell::kValueOffset));
- __ cmp(result.reg(), Factory::the_hole_value());
- deferred->Branch(equal);
+ bool is_dont_delete = false;
+ if (!info_->closure().is_null()) {
+ // When doing lazy compilation we can check if the global cell
+ // already exists and use its "don't delete" status as a hint.
+ AssertNoAllocation no_gc;
+ v8::internal::GlobalObject* global_object =
+ info_->closure()->context()->global();
+ LookupResult lookup;
+ global_object->LocalLookupRealNamedProperty(*name, &lookup);
+ if (lookup.IsProperty() && lookup.type() == NORMAL) {
+ ASSERT(lookup.holder() == global_object);
+ ASSERT(global_object->property_dictionary()->ValueAt(
+ lookup.GetDictionaryEntry())->IsJSGlobalPropertyCell());
+ is_dont_delete = lookup.IsDontDelete();
+ }
+ }
+ deferred->set_is_dont_delete(is_dont_delete);
+ if (!is_dont_delete) {
+ __ cmp(result.reg(), Factory::the_hole_value());
+ deferred->Branch(equal);
+ } else if (FLAG_debug_code) {
+ __ cmp(result.reg(), Factory::the_hole_value());
+ __ Check(not_equal, "DontDelete cells can't contain the hole");
+ }
__ IncrementCounter(&Counters::named_load_global_inline, 1);
+ if (is_dont_delete) {
+ __ IncrementCounter(&Counters::dont_delete_hint_hit, 1);
+ }
} else {
// The initial (invalid) offset has to be large enough to force a 32-bit
// instruction encoding to allow patching with an arbitrary offset. Use
diff --git a/deps/v8/src/ia32/ic-ia32.cc b/deps/v8/src/ia32/ic-ia32.cc
index a2990a20e3f..b5f4deefeb9 100644
--- a/deps/v8/src/ia32/ic-ia32.cc
+++ b/deps/v8/src/ia32/ic-ia32.cc
@@ -1662,17 +1662,37 @@ bool LoadIC::PatchInlinedLoad(Address address, Object* map, int offset) {
// One byte opcode for mov ecx,0xXXXXXXXX.
+// Marks inlined contextual loads using all kinds of cells. Generated
+// code has the hole check:
+// mov reg, <cell>
+// mov reg, (<cell>, value offset)
+// cmp reg, <the hole>
+// je slow
+// ;; use reg
static const byte kMovEcxByte = 0xB9;
+// One byte opcode for mov edx,0xXXXXXXXX.
+// Marks inlined contextual loads using only "don't delete"
+// cells. Generated code doesn't have the hole check:
+// mov reg, <cell>
+// mov reg, (<cell>, value offset)
+// ;; use reg
+static const byte kMovEdxByte = 0xBA;
+
bool LoadIC::PatchInlinedContextualLoad(Address address,
Object* map,
- Object* cell) {
+ Object* cell,
+ bool is_dont_delete) {
// The address of the instruction following the call.
Address mov_instruction_address =
address + Assembler::kCallTargetAddressOffset;
- // If the instruction following the call is not a cmp eax, nothing
- // was inlined.
- if (*mov_instruction_address != kMovEcxByte) return false;
+ // If the instruction following the call is not a mov ecx/edx,
+ // nothing was inlined.
+ byte b = *mov_instruction_address;
+ if (b != kMovEcxByte && b != kMovEdxByte) return false;
+ // If we don't have the hole check generated, we can only support
+ // "don't delete" cells.
+ if (b == kMovEdxByte && !is_dont_delete) return false;
Address delta_address = mov_instruction_address + 1;
// The delta to the start of the map check instruction.
diff --git a/deps/v8/src/ic.cc b/deps/v8/src/ic.cc
index a9c2a4837cf..adf365af0fa 100644
--- a/deps/v8/src/ic.cc
+++ b/deps/v8/src/ic.cc
@@ -299,7 +299,10 @@ void LoadIC::ClearInlinedVersion(Address address) {
// present) to guarantee failure by holding an invalid map (the null
// value). The offset can be patched to anything.
PatchInlinedLoad(address, Heap::null_value(), 0);
- PatchInlinedContextualLoad(address, Heap::null_value(), Heap::null_value());
+ PatchInlinedContextualLoad(address,
+ Heap::null_value(),
+ Heap::null_value(),
+ true);
}
@@ -848,7 +851,10 @@ Object* LoadIC::Load(State state, Handle<Object> object, Handle<String> name) {
JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(
lookup.holder()->property_dictionary()->ValueAt(
lookup.GetDictionaryEntry()));
- if (PatchInlinedContextualLoad(address(), map, cell)) {
+ if (PatchInlinedContextualLoad(address(),
+ map,
+ cell,
+ lookup.IsDontDelete())) {
set_target(megamorphic_stub());
TRACE_IC_NAMED("[LoadIC : inline contextual patch %s]\n", name);
ASSERT(cell->value() != Heap::the_hole_value());
diff --git a/deps/v8/src/ic.h b/deps/v8/src/ic.h
index a5fada09f40..437e45a9359 100644
--- a/deps/v8/src/ic.h
+++ b/deps/v8/src/ic.h
@@ -300,7 +300,8 @@ class LoadIC: public IC {
static bool PatchInlinedContextualLoad(Address address,
Object* map,
- Object* cell);
+ Object* cell,
+ bool is_dont_delete);
friend class IC;
};
diff --git a/deps/v8/src/jsregexp.cc b/deps/v8/src/jsregexp.cc
index 30d4dcbf23b..82a370f141f 100644
--- a/deps/v8/src/jsregexp.cc
+++ b/deps/v8/src/jsregexp.cc
@@ -125,7 +125,7 @@ Handle<Object> RegExpImpl::Compile(Handle<JSRegExp> re,
PostponeInterruptsScope postpone;
RegExpCompileData parse_result;
FlatStringReader reader(pattern);
- if (!ParseRegExp(&reader, flags.is_multiline(), &parse_result)) {
+ if (!Parser::ParseRegExp(&reader, flags.is_multiline(), &parse_result)) {
// Throw an exception if we fail to parse the pattern.
ThrowRegExpException(re,
pattern,
@@ -267,7 +267,7 @@ bool RegExpImpl::CompileIrregexp(Handle<JSRegExp> re, bool is_ascii) {
RegExpCompileData compile_data;
FlatStringReader reader(pattern);
- if (!ParseRegExp(&reader, flags.is_multiline(), &compile_data)) {
+ if (!Parser::ParseRegExp(&reader, flags.is_multiline(), &compile_data)) {
// Throw an exception if we fail to parse the pattern.
// THIS SHOULD NOT HAPPEN. We already pre-parsed it successfully once.
ThrowRegExpException(re,
diff --git a/deps/v8/src/liveedit.cc b/deps/v8/src/liveedit.cc
index 2fae3afb1c1..cfd2e357cc6 100644
--- a/deps/v8/src/liveedit.cc
+++ b/deps/v8/src/liveedit.cc
@@ -29,13 +29,15 @@
#include "v8.h"
#include "liveedit.h"
+
#include "compiler.h"
-#include "oprofile-agent.h"
-#include "scopes.h"
-#include "scopeinfo.h"
-#include "global-handles.h"
#include "debug.h"
+#include "global-handles.h"
#include "memory.h"
+#include "oprofile-agent.h"
+#include "parser.h"
+#include "scopeinfo.h"
+#include "scopes.h"
namespace v8 {
namespace internal {
@@ -409,7 +411,8 @@ static void CompileScriptForTracker(Handle<Script> script) {
// Build AST.
ScriptDataImpl* pre_data = NULL;
EagerCompilationInfo info(script, is_eval);
- FunctionLiteral* lit = MakeAST(is_global, script, extension, pre_data);
+ FunctionLiteral* lit =
+ Parser::MakeAST(is_global, script, extension, pre_data);
// Check for parse errors.
if (lit == NULL) {
diff --git a/deps/v8/src/log-utils.h b/deps/v8/src/log-utils.h
index 8889f1b77a3..a4dde213bf4 100644
--- a/deps/v8/src/log-utils.h
+++ b/deps/v8/src/log-utils.h
@@ -132,6 +132,7 @@ class Log : public AllStatic {
size_t rv = fwrite(msg, 1, length, output_handle_);
ASSERT(static_cast<size_t>(length) == rv);
USE(rv);
+ fflush(output_handle_);
return length;
}
diff --git a/deps/v8/src/objects-visiting.h b/deps/v8/src/objects-visiting.h
index a6d6b12c695..90f7ce0b3df 100644
--- a/deps/v8/src/objects-visiting.h
+++ b/deps/v8/src/objects-visiting.h
@@ -25,8 +25,8 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#ifndef V8_OBJECTS_ITERATION_H_
-#define V8_OBJECTS_ITERATION_H_
+#ifndef V8_OBJECTS_VISITING_H_
+#define V8_OBJECTS_VISITING_H_
// This file provides base classes and auxiliary methods for defining
// static object visitors used during GC.
@@ -389,4 +389,4 @@ void Code::CodeIterateBody() {
} } // namespace v8::internal
-#endif // V8_OBJECTS_ITERATION_H_
+#endif // V8_OBJECTS_VISITING_H_
diff --git a/deps/v8/src/objects.cc b/deps/v8/src/objects.cc
index 737bf5726a5..e21de0b1964 100644
--- a/deps/v8/src/objects.cc
+++ b/deps/v8/src/objects.cc
@@ -8719,6 +8719,11 @@ Object* StringDictionary::TransformPropertiesToFastFor(
int inobject_props = obj->map()->inobject_properties();
int number_of_allocated_fields =
number_of_fields + unused_property_fields - inobject_props;
+ if (number_of_allocated_fields < 0) {
+ // There is enough inobject space for all fields (including unused).
+ number_of_allocated_fields = 0;
+ unused_property_fields = inobject_props - number_of_fields;
+ }
// Allocate the fixed array for the fields.
Object* fields = Heap::AllocateFixedArray(number_of_allocated_fields);
diff --git a/deps/v8/src/objects.h b/deps/v8/src/objects.h
index 7f301b5c023..8f79acad24f 100644
--- a/deps/v8/src/objects.h
+++ b/deps/v8/src/objects.h
@@ -3537,7 +3537,7 @@ class SharedFunctionInfo: public HeapObject {
// Important: inobject slack tracking is not attempted during the snapshot
// creation.
- static const int kGenerousAllocationCount = 16;
+ static const int kGenerousAllocationCount = 8;
// [construction_count]: Counter for constructor calls made during
// the tracking phase.
diff --git a/deps/v8/src/parser.cc b/deps/v8/src/parser.cc
index a386848d33d..3d48c9c5855 100644
--- a/deps/v8/src/parser.cc
+++ b/deps/v8/src/parser.cc
@@ -47,14 +47,6 @@
namespace v8 {
namespace internal {
-class ParserFactory;
-class ParserLog;
-class TemporaryScope;
-class Target;
-
-template <typename T> class ZoneListWrapper;
-
-
// PositionStack is used for on-stack allocation of token positions for
// new expressions. Please look at ParseNewExpression.
@@ -95,250 +87,6 @@ class PositionStack {
};
-class Parser {
- public:
- Parser(Handle<Script> script, bool allow_natives_syntax,
- v8::Extension* extension, ParserMode is_pre_parsing,
- ParserFactory* factory, ParserLog* log, ScriptDataImpl* pre_data);
- virtual ~Parser() { }
-
- // Pre-parse the program from the character stream; returns true on
- // success, false if a stack-overflow happened during parsing.
- bool PreParseProgram(Handle<String> source, unibrow::CharacterStream* stream);
-
- void ReportMessage(const char* message, Vector<const char*> args);
- virtual void ReportMessageAt(Scanner::Location loc,
- const char* message,
- Vector<const char*> args) = 0;
-
-
- // Returns NULL if parsing failed.
- FunctionLiteral* ParseProgram(Handle<String> source,
- bool in_global_context);
- FunctionLiteral* ParseLazy(Handle<SharedFunctionInfo> info);
- FunctionLiteral* ParseJson(Handle<String> source);
-
- // The minimum number of contiguous assignment that will
- // be treated as an initialization block. Benchmarks show that
- // the overhead exceeds the savings below this limit.
- static const int kMinInitializationBlock = 3;
-
- protected:
-
- enum Mode {
- PARSE_LAZILY,
- PARSE_EAGERLY
- };
-
- // Report syntax error
- void ReportUnexpectedToken(Token::Value token);
- void ReportInvalidPreparseData(Handle<String> name, bool* ok);
-
- Handle<Script> script_;
- Scanner scanner_;
-
- Scope* top_scope_;
- int with_nesting_level_;
-
- TemporaryScope* temp_scope_;
- Mode mode_;
-
- Target* target_stack_; // for break, continue statements
- bool allow_natives_syntax_;
- v8::Extension* extension_;
- ParserFactory* factory_;
- ParserLog* log_;
- bool is_pre_parsing_;
- ScriptDataImpl* pre_data_;
- FuncNameInferrer* fni_;
-
- bool inside_with() const { return with_nesting_level_ > 0; }
- ParserFactory* factory() const { return factory_; }
- ParserLog* log() const { return log_; }
- Scanner& scanner() { return scanner_; }
- Mode mode() const { return mode_; }
- ScriptDataImpl* pre_data() const { return pre_data_; }
-
- // All ParseXXX functions take as the last argument an *ok parameter
- // which is set to false if parsing failed; it is unchanged otherwise.
- // By making the 'exception handling' explicit, we are forced to check
- // for failure at the call sites.
- void* ParseSourceElements(ZoneListWrapper<Statement>* processor,
- int end_token, bool* ok);
- Statement* ParseStatement(ZoneStringList* labels, bool* ok);
- Statement* ParseFunctionDeclaration(bool* ok);
- Statement* ParseNativeDeclaration(bool* ok);
- Block* ParseBlock(ZoneStringList* labels, bool* ok);
- Block* ParseVariableStatement(bool* ok);
- Block* ParseVariableDeclarations(bool accept_IN, Expression** var, bool* ok);
- Statement* ParseExpressionOrLabelledStatement(ZoneStringList* labels,
- bool* ok);
- IfStatement* ParseIfStatement(ZoneStringList* labels, bool* ok);
- Statement* ParseContinueStatement(bool* ok);
- Statement* ParseBreakStatement(ZoneStringList* labels, bool* ok);
- Statement* ParseReturnStatement(bool* ok);
- Block* WithHelper(Expression* obj,
- ZoneStringList* labels,
- bool is_catch_block,
- bool* ok);
- Statement* ParseWithStatement(ZoneStringList* labels, bool* ok);
- CaseClause* ParseCaseClause(bool* default_seen_ptr, bool* ok);
- SwitchStatement* ParseSwitchStatement(ZoneStringList* labels, bool* ok);
- DoWhileStatement* ParseDoWhileStatement(ZoneStringList* labels, bool* ok);
- WhileStatement* ParseWhileStatement(ZoneStringList* labels, bool* ok);
- Statement* ParseForStatement(ZoneStringList* labels, bool* ok);
- Statement* ParseThrowStatement(bool* ok);
- Expression* MakeCatchContext(Handle<String> id, VariableProxy* value);
- TryStatement* ParseTryStatement(bool* ok);
- DebuggerStatement* ParseDebuggerStatement(bool* ok);
-
- Expression* ParseExpression(bool accept_IN, bool* ok);
- Expression* ParseAssignmentExpression(bool accept_IN, bool* ok);
- Expression* ParseConditionalExpression(bool accept_IN, bool* ok);
- Expression* ParseBinaryExpression(int prec, bool accept_IN, bool* ok);
- Expression* ParseUnaryExpression(bool* ok);
- Expression* ParsePostfixExpression(bool* ok);
- Expression* ParseLeftHandSideExpression(bool* ok);
- Expression* ParseNewExpression(bool* ok);
- Expression* ParseMemberExpression(bool* ok);
- Expression* ParseNewPrefix(PositionStack* stack, bool* ok);
- Expression* ParseMemberWithNewPrefixesExpression(PositionStack* stack,
- bool* ok);
- Expression* ParsePrimaryExpression(bool* ok);
- Expression* ParseArrayLiteral(bool* ok);
- Expression* ParseObjectLiteral(bool* ok);
- ObjectLiteral::Property* ParseObjectLiteralGetSet(bool is_getter, bool* ok);
- Expression* ParseRegExpLiteral(bool seen_equal, bool* ok);
-
- Expression* NewCompareNode(Token::Value op,
- Expression* x,
- Expression* y,
- int position);
-
- // Populate the constant properties fixed array for a materialized object
- // literal.
- void BuildObjectLiteralConstantProperties(
- ZoneList<ObjectLiteral::Property*>* properties,
- Handle<FixedArray> constants,
- bool* is_simple,
- bool* fast_elements,
- int* depth);
-
- // Populate the literals fixed array for a materialized array literal.
- void BuildArrayLiteralBoilerplateLiterals(ZoneList<Expression*>* properties,
- Handle<FixedArray> constants,
- bool* is_simple,
- int* depth);
-
- // Decide if a property should be in the object boilerplate.
- bool IsBoilerplateProperty(ObjectLiteral::Property* property);
- // If the expression is a literal, return the literal value;
- // if the expression is a materialized literal and is simple return a
- // compile time value as encoded by CompileTimeValue::GetValue().
- // Otherwise, return undefined literal as the placeholder
- // in the object literal boilerplate.
- Handle<Object> GetBoilerplateValue(Expression* expression);
-
- enum FunctionLiteralType {
- EXPRESSION,
- DECLARATION,
- NESTED
- };
-
- ZoneList<Expression*>* ParseArguments(bool* ok);
- FunctionLiteral* ParseFunctionLiteral(Handle<String> var_name,
- int function_token_position,
- FunctionLiteralType type,
- bool* ok);
-
-
- // Magical syntax support.
- Expression* ParseV8Intrinsic(bool* ok);
-
- INLINE(Token::Value peek()) { return scanner_.peek(); }
- INLINE(Token::Value Next()) { return scanner_.Next(); }
- INLINE(void Consume(Token::Value token));
- void Expect(Token::Value token, bool* ok);
- bool Check(Token::Value token);
- void ExpectSemicolon(bool* ok);
-
- Handle<String> GetSymbol(bool* ok);
-
- // Get odd-ball literals.
- Literal* GetLiteralUndefined();
- Literal* GetLiteralTheHole();
- Literal* GetLiteralNumber(double value);
-
- Handle<String> ParseIdentifier(bool* ok);
- Handle<String> ParseIdentifierName(bool* ok);
- Handle<String> ParseIdentifierOrGetOrSet(bool* is_get,
- bool* is_set,
- bool* ok);
-
- // Parser support
- virtual VariableProxy* Declare(Handle<String> name, Variable::Mode mode,
- FunctionLiteral* fun,
- bool resolve,
- bool* ok) = 0;
-
- bool TargetStackContainsLabel(Handle<String> label);
- BreakableStatement* LookupBreakTarget(Handle<String> label, bool* ok);
- IterationStatement* LookupContinueTarget(Handle<String> label, bool* ok);
-
- void RegisterTargetUse(BreakTarget* target, Target* stop);
-
- // Create a number literal.
- Literal* NewNumberLiteral(double value);
-
- // Generate AST node that throw a ReferenceError with the given type.
- Expression* NewThrowReferenceError(Handle<String> type);
-
- // Generate AST node that throw a SyntaxError with the given
- // type. The first argument may be null (in the handle sense) in
- // which case no arguments are passed to the constructor.
- Expression* NewThrowSyntaxError(Handle<String> type, Handle<Object> first);
-
- // Generate AST node that throw a TypeError with the given
- // type. Both arguments must be non-null (in the handle sense).
- Expression* NewThrowTypeError(Handle<String> type,
- Handle<Object> first,
- Handle<Object> second);
-
- // Generic AST generator for throwing errors from compiled code.
- Expression* NewThrowError(Handle<String> constructor,
- Handle<String> type,
- Vector< Handle<Object> > arguments);
-
- // JSON is a subset of JavaScript, as specified in, e.g., the ECMAScript 5
- // specification section 15.12.1 (and appendix A.8).
- // The grammar is given section 15.12.1.2 (and appendix A.8.2).
-
- // Parse JSON input as a single JSON value.
- Expression* ParseJson(bool* ok);
-
- // Parse a single JSON value from input (grammar production JSONValue).
- // A JSON value is either a (double-quoted) string literal, a number literal,
- // one of "true", "false", or "null", or an object or array literal.
- Expression* ParseJsonValue(bool* ok);
- // Parse a JSON object literal (grammar production JSONObject).
- // An object literal is a squiggly-braced and comma separated sequence
- // (possibly empty) of key/value pairs, where the key is a JSON string
- // literal, the value is a JSON value, and the two are spearated by a colon.
- // A JavaScript object also allows numbers and identifiers as keys.
- Expression* ParseJsonObject(bool* ok);
- // Parses a JSON array literal (grammar production JSONArray). An array
- // literal is a square-bracketed and comma separated sequence (possibly empty)
- // of JSON values.
- // A JavaScript array allows leaving out values from the sequence.
- Expression* ParseJsonArray(bool* ok);
-
- friend class Target;
- friend class TargetScope;
- friend class LexicalScope;
- friend class TemporaryScope;
-};
-
-
template <typename T, int initial_size>
class BufferedZoneList {
public:
@@ -5501,9 +5249,9 @@ bool ScriptDataImpl::HasError() {
// Preparse, but only collect data that is immediately useful,
// even if the preparser data is only used once.
-ScriptDataImpl* PartialPreParse(Handle<String> source,
- unibrow::CharacterStream* stream,
- v8::Extension* extension) {
+ScriptDataImpl* Parser::PartialPreParse(Handle<String> source,
+ unibrow::CharacterStream* stream,
+ v8::Extension* extension) {
Handle<Script> no_script;
bool allow_natives_syntax =
FLAG_allow_natives_syntax || Bootstrapper::IsActive();
@@ -5559,9 +5307,9 @@ int ScriptDataImpl::ReadNumber(byte** source) {
}
-ScriptDataImpl* PreParse(Handle<String> source,
- unibrow::CharacterStream* stream,
- v8::Extension* extension) {
+ScriptDataImpl* Parser::PreParse(Handle<String> source,
+ unibrow::CharacterStream* stream,
+ v8::Extension* extension) {
Handle<Script> no_script;
bool allow_natives_syntax =
FLAG_allow_natives_syntax || Bootstrapper::IsActive();
@@ -5574,9 +5322,9 @@ ScriptDataImpl* PreParse(Handle<String> source,
}
-bool ParseRegExp(FlatStringReader* input,
- bool multiline,
- RegExpCompileData* result) {
+bool Parser::ParseRegExp(FlatStringReader* input,
+ bool multiline,
+ RegExpCompileData* result) {
ASSERT(result != NULL);
RegExpParser parser(input, &result->error, multiline);
RegExpTree* tree = parser.ParsePattern();
@@ -5596,13 +5344,11 @@ bool ParseRegExp(FlatStringReader* input,
}
-// MakeAST is just a wrapper for the corresponding Parser calls so we don't
-// have to expose the entire Parser class in the .h file.
-FunctionLiteral* MakeAST(bool compile_in_global_context,
- Handle<Script> script,
- v8::Extension* extension,
- ScriptDataImpl* pre_data,
- bool is_json) {
+FunctionLiteral* Parser::MakeAST(bool compile_in_global_context,
+ Handle<Script> script,
+ v8::Extension* extension,
+ ScriptDataImpl* pre_data,
+ bool is_json) {
bool allow_natives_syntax =
FLAG_allow_natives_syntax || Bootstrapper::IsActive();
AstBuildingParser parser(script, allow_natives_syntax, extension, pre_data);
@@ -5630,7 +5376,7 @@ FunctionLiteral* MakeAST(bool compile_in_global_context,
}
-FunctionLiteral* MakeLazyAST(Handle<SharedFunctionInfo> info) {
+FunctionLiteral* Parser::MakeLazyAST(Handle<SharedFunctionInfo> info) {
Handle<Script> script(Script::cast(info->script()));
AstBuildingParser parser(script, true, NULL, NULL);
FunctionLiteral* result = parser.ParseLazy(info);
diff --git a/deps/v8/src/parser.h b/deps/v8/src/parser.h
index 9a8288926c8..99ed22a2f8a 100644
--- a/deps/v8/src/parser.h
+++ b/deps/v8/src/parser.h
@@ -1,4 +1,4 @@
-// Copyright 2006-2010 the V8 project authors. All rights reserved.
+// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@@ -28,12 +28,22 @@
#ifndef V8_PARSER_H_
#define V8_PARSER_H_
-#include "scanner.h"
#include "allocation.h"
+#include "ast.h"
+#include "scanner.h"
namespace v8 {
namespace internal {
+class FuncNameInferrer;
+class ParserFactory;
+class ParserLog;
+class PositionStack;
+class Target;
+class TemporaryScope;
+
+template <typename T> class ZoneListWrapper;
+
class ParserMessage : public Malloced {
public:
@@ -166,34 +176,275 @@ class ScriptDataImpl : public ScriptData {
};
-// The parser: Takes a script and and context information, and builds a
-// FunctionLiteral AST node. Returns NULL and deallocates any allocated
-// AST nodes if parsing failed.
-FunctionLiteral* MakeAST(bool compile_in_global_context,
- Handle<Script> script,
- v8::Extension* extension,
- ScriptDataImpl* pre_data,
- bool is_json = false);
-
-// Generic preparser generating full preparse data.
-ScriptDataImpl* PreParse(Handle<String> source,
- unibrow::CharacterStream* stream,
- v8::Extension* extension);
-
-// Preparser that only does preprocessing that makes sense if only used
-// immediately after.
-ScriptDataImpl* PartialPreParse(Handle<String> source,
- unibrow::CharacterStream* stream,
- v8::Extension* extension);
-
-
-bool ParseRegExp(FlatStringReader* input,
- bool multiline,
- RegExpCompileData* result);
+class Parser {
+ public:
+ Parser(Handle<Script> script, bool allow_natives_syntax,
+ v8::Extension* extension, ParserMode is_pre_parsing,
+ ParserFactory* factory, ParserLog* log, ScriptDataImpl* pre_data);
+ virtual ~Parser() { }
+
+ // Takes a script and and context information, and builds a
+ // FunctionLiteral AST node. Returns NULL and deallocates any allocated
+ // AST nodes if parsing failed.
+ static FunctionLiteral* MakeAST(bool compile_in_global_context,
+ Handle<Script> script,
+ v8::Extension* extension,
+ ScriptDataImpl* pre_data,
+ bool is_json = false);
+
+ // Support for doing lazy compilation.
+ static FunctionLiteral* MakeLazyAST(Handle<SharedFunctionInfo> info);
+
+ // Generic preparser generating full preparse data.
+ static ScriptDataImpl* PreParse(Handle<String> source,
+ unibrow::CharacterStream* stream,
+ v8::Extension* extension);
+
+ // Preparser that only does preprocessing that makes sense if only used
+ // immediately after.
+ static ScriptDataImpl* PartialPreParse(Handle<String> source,
+ unibrow::CharacterStream* stream,
+ v8::Extension* extension);
+
+ static bool ParseRegExp(FlatStringReader* input,
+ bool multiline,
+ RegExpCompileData* result);
+
+ // Pre-parse the program from the character stream; returns true on
+ // success, false if a stack-overflow happened during parsing.
+ bool PreParseProgram(Handle<String> source, unibrow::CharacterStream* stream);
+
+ void ReportMessage(const char* message, Vector<const char*> args);
+ virtual void ReportMessageAt(Scanner::Location loc,
+ const char* message,
+ Vector<const char*> args) = 0;
+
+
+ // Returns NULL if parsing failed.
+ FunctionLiteral* ParseProgram(Handle<String> source,
+ bool in_global_context);
+ FunctionLiteral* ParseLazy(Handle<SharedFunctionInfo> info);
+ FunctionLiteral* ParseJson(Handle<String> source);
+
+ // The minimum number of contiguous assignment that will
+ // be treated as an initialization block. Benchmarks show that
+ // the overhead exceeds the savings below this limit.
+ static const int kMinInitializationBlock = 3;
+
+ protected:
+
+ enum Mode {
+ PARSE_LAZILY,
+ PARSE_EAGERLY
+ };
+ // Report syntax error
+ void ReportUnexpectedToken(Token::Value token);
+ void ReportInvalidPreparseData(Handle<String> name, bool* ok);
+
+ Handle<Script> script_;
+ Scanner scanner_;
+
+ Scope* top_scope_;
+ int with_nesting_level_;
+
+ TemporaryScope* temp_scope_;
+ Mode mode_;
+
+ Target* target_stack_; // for break, continue statements
+ bool allow_natives_syntax_;
+ v8::Extension* extension_;
+ ParserFactory* factory_;
+ ParserLog* log_;
+ bool is_pre_parsing_;
+ ScriptDataImpl* pre_data_;
+ FuncNameInferrer* fni_;
+
+ bool inside_with() const { return with_nesting_level_ > 0; }
+ ParserFactory* factory() const { return factory_; }
+ ParserLog* log() const { return log_; }
+ Scanner& scanner() { return scanner_; }
+ Mode mode() const { return mode_; }
+ ScriptDataImpl* pre_data() const { return pre_data_; }
+
+ // All ParseXXX functions take as the last argument an *ok parameter
+ // which is set to false if parsing failed; it is unchanged otherwise.
+ // By making the 'exception handling' explicit, we are forced to check
+ // for failure at the call sites.
+ void* ParseSourceElements(ZoneListWrapper<Statement>* processor,
+ int end_token, bool* ok);
+ Statement* ParseStatement(ZoneStringList* labels, bool* ok);
+ Statement* ParseFunctionDeclaration(bool* ok);
+ Statement* ParseNativeDeclaration(bool* ok);
+ Block* ParseBlock(ZoneStringList* labels, bool* ok);
+ Block* ParseVariableStatement(bool* ok);
+ Block* ParseVariableDeclarations(bool accept_IN, Expression** var, bool* ok);
+ Statement* ParseExpressionOrLabelledStatement(ZoneStringList* labels,
+ bool* ok);
+ IfStatement* ParseIfStatement(ZoneStringList* labels, bool* ok);
+ Statement* ParseContinueStatement(bool* ok);
+ Statement* ParseBreakStatement(ZoneStringList* labels, bool* ok);
+ Statement* ParseReturnStatement(bool* ok);
+ Block* WithHelper(Expression* obj,
+ ZoneStringList* labels,
+ bool is_catch_block,
+ bool* ok);
+ Statement* ParseWithStatement(ZoneStringList* labels, bool* ok);
+ CaseClause* ParseCaseClause(bool* default_seen_ptr, bool* ok);
+ SwitchStatement* ParseSwitchStatement(ZoneStringList* labels, bool* ok);
+ DoWhileStatement* ParseDoWhileStatement(ZoneStringList* labels, bool* ok);
+ WhileStatement* ParseWhileStatement(ZoneStringList* labels, bool* ok);
+ Statement* ParseForStatement(ZoneStringList* labels, bool* ok);
+ Statement* ParseThrowStatement(bool* ok);
+ Expression* MakeCatchContext(Handle<String> id, VariableProxy* value);
+ TryStatement* ParseTryStatement(bool* ok);
+ DebuggerStatement* ParseDebuggerStatement(bool* ok);
+
+ Expression* ParseExpression(bool accept_IN, bool* ok);
+ Expression* ParseAssignmentExpression(bool accept_IN, bool* ok);
+ Expression* ParseConditionalExpression(bool accept_IN, bool* ok);
+ Expression* ParseBinaryExpression(int prec, bool accept_IN, bool* ok);
+ Expression* ParseUnaryExpression(bool* ok);
+ Expression* ParsePostfixExpression(bool* ok);
+ Expression* ParseLeftHandSideExpression(bool* ok);
+ Expression* ParseNewExpression(bool* ok);
+ Expression* ParseMemberExpression(bool* ok);
+ Expression* ParseNewPrefix(PositionStack* stack, bool* ok);
+ Expression* ParseMemberWithNewPrefixesExpression(PositionStack* stack,
+ bool* ok);
+ Expression* ParsePrimaryExpression(bool* ok);
+ Expression* ParseArrayLiteral(bool* ok);
+ Expression* ParseObjectLiteral(bool* ok);
+ ObjectLiteral::Property* ParseObjectLiteralGetSet(bool is_getter, bool* ok);
+ Expression* ParseRegExpLiteral(bool seen_equal, bool* ok);
+
+ Expression* NewCompareNode(Token::Value op,
+ Expression* x,
+ Expression* y,
+ int position);
+
+ // Populate the constant properties fixed array for a materialized object
+ // literal.
+ void BuildObjectLiteralConstantProperties(
+ ZoneList<ObjectLiteral::Property*>* properties,
+ Handle<FixedArray> constants,
+ bool* is_simple,
+ bool* fast_elements,
+ int* depth);
+
+ // Populate the literals fixed array for a materialized array literal.
+ void BuildArrayLiteralBoilerplateLiterals(ZoneList<Expression*>* properties,
+ Handle<FixedArray> constants,
+ bool* is_simple,
+ int* depth);
+
+ // Decide if a property should be in the object boilerplate.
+ bool IsBoilerplateProperty(ObjectLiteral::Property* property);
+ // If the expression is a literal, return the literal value;
+ // if the expression is a materialized literal and is simple return a
+ // compile time value as encoded by CompileTimeValue::GetValue().
+ // Otherwise, return undefined literal as the placeholder
+ // in the object literal boilerplate.
+ Handle<Object> GetBoilerplateValue(Expression* expression);
+
+ enum FunctionLiteralType {
+ EXPRESSION,
+ DECLARATION,
+ NESTED
+ };
-// Support for doing lazy compilation.
-FunctionLiteral* MakeLazyAST(Handle<SharedFunctionInfo> info);
+ ZoneList<Expression*>* ParseArguments(bool* ok);
+ FunctionLiteral* ParseFunctionLiteral(Handle<String> var_name,
+ int function_token_position,
+ FunctionLiteralType type,
+ bool* ok);
+
+
+ // Magical syntax support.
+ Expression* ParseV8Intrinsic(bool* ok);
+
+ INLINE(Token::Value peek()) { return scanner_.peek(); }
+ INLINE(Token::Value Next()) { return scanner_.Next(); }
+ INLINE(void Consume(Token::Value token));
+ void Expect(Token::Value token, bool* ok);
+ bool Check(Token::Value token);
+ void ExpectSemicolon(bool* ok);
+
+ Handle<String> GetSymbol(bool* ok);
+
+ // Get odd-ball literals.
+ Literal* GetLiteralUndefined();
+ Literal* GetLiteralTheHole();
+ Literal* GetLiteralNumber(double value);
+
+ Handle<String> ParseIdentifier(bool* ok);
+ Handle<String> ParseIdentifierName(bool* ok);
+ Handle<String> ParseIdentifierOrGetOrSet(bool* is_get,
+ bool* is_set,
+ bool* ok);
+
+ // Parser support
+ virtual VariableProxy* Declare(Handle<String> name, Variable::Mode mode,
+ FunctionLiteral* fun,
+ bool resolve,
+ bool* ok) = 0;
+
+ bool TargetStackContainsLabel(Handle<String> label);
+ BreakableStatement* LookupBreakTarget(Handle<String> label, bool* ok);
+ IterationStatement* LookupContinueTarget(Handle<String> label, bool* ok);
+
+ void RegisterTargetUse(BreakTarget* target, Target* stop);
+
+ // Create a number literal.
+ Literal* NewNumberLiteral(double value);
+
+ // Generate AST node that throw a ReferenceError with the given type.
+ Expression* NewThrowReferenceError(Handle<String> type);
+
+ // Generate AST node that throw a SyntaxError with the given
+ // type. The first argument may be null (in the handle sense) in
+ // which case no arguments are passed to the constructor.
+ Expression* NewThrowSyntaxError(Handle<String> type, Handle<Object> first);
+
+ // Generate AST node that throw a TypeError with the given
+ // type. Both arguments must be non-null (in the handle sense).
+ Expression* NewThrowTypeError(Handle<String> type,
+ Handle<Object> first,
+ Handle<Object> second);
+
+ // Generic AST generator for throwing errors from compiled code.
+ Expression* NewThrowError(Handle<String> constructor,
+ Handle<String> type,
+ Vector< Handle<Object> > arguments);
+
+ // JSON is a subset of JavaScript, as specified in, e.g., the ECMAScript 5
+ // specification section 15.12.1 (and appendix A.8).
+ // The grammar is given section 15.12.1.2 (and appendix A.8.2).
+
+ // Parse JSON input as a single JSON value.
+ Expression* ParseJson(bool* ok);
+
+ // Parse a single JSON value from input (grammar production JSONValue).
+ // A JSON value is either a (double-quoted) string literal, a number literal,
+ // one of "true", "false", or "null", or an object or array literal.
+ Expression* ParseJsonValue(bool* ok);
+ // Parse a JSON object literal (grammar production JSONObject).
+ // An object literal is a squiggly-braced and comma separated sequence
+ // (possibly empty) of key/value pairs, where the key is a JSON string
+ // literal, the value is a JSON value, and the two are spearated by a colon.
+ // A JavaScript object also allows numbers and identifiers as keys.
+ Expression* ParseJsonObject(bool* ok);
+ // Parses a JSON array literal (grammar production JSONArray). An array
+ // literal is a square-bracketed and comma separated sequence (possibly empty)
+ // of JSON values.
+ // A JavaScript array allows leaving out values from the sequence.
+ Expression* ParseJsonArray(bool* ok);
+
+ friend class Target;
+ friend class TargetScope;
+ friend class LexicalScope;
+ friend class TemporaryScope;
+};
// Support for handling complex values (array and object literals) that
diff --git a/deps/v8/src/profile-generator.cc b/deps/v8/src/profile-generator.cc
index 525dea2fbaa..08ee046970f 100644
--- a/deps/v8/src/profile-generator.cc
+++ b/deps/v8/src/profile-generator.cc
@@ -952,7 +952,7 @@ void HeapEntry::PaintAllReachable() {
void HeapEntry::Print(int max_depth, int indent) {
- OS::Print("%6d %6d %6d [%ld] ",
+ OS::Print("%6d %6d %6d [%llu] ",
self_size(), ReachableSize(), RetainedSize(), id_);
if (type() != kString) {
OS::Print("%s %.40s\n", TypeAsString(), name_);
@@ -1237,7 +1237,7 @@ HeapSnapshot::HeapSnapshot(HeapSnapshotsCollection* collection,
type_(type),
title_(title),
uid_(uid),
- root_entry_index_(-1),
+ root_entry_(NULL),
raw_entries_(NULL),
entries_sorted_(false) {
STATIC_ASSERT(
@@ -1276,11 +1276,11 @@ HeapEntry* HeapSnapshot::AddEntry(HeapObject* object,
int children_count,
int retainers_count) {
if (object == kInternalRootObject) {
- ASSERT(root_entry_index_ == -1);
- root_entry_index_ = entries_.length();
+ ASSERT(root_entry_ == NULL);
ASSERT(retainers_count == 0);
- return AddEntry(
+ root_entry_ = AddEntry(
HeapEntry::kInternal, "", 0, 0, children_count, retainers_count);
+ return root_entry_;
} else if (object->IsJSFunction()) {
JSFunction* func = JSFunction::cast(object);
SharedFunctionInfo* shared = func->shared();
@@ -2095,6 +2095,11 @@ HeapSnapshotsComparator::~HeapSnapshotsComparator() {
HeapSnapshotsDiff* HeapSnapshotsComparator::Compare(HeapSnapshot* snapshot1,
HeapSnapshot* snapshot2) {
+ snapshot1->ClearPaint();
+ snapshot1->root()->PaintAllReachable();
+ snapshot2->ClearPaint();
+ snapshot2->root()->PaintAllReachable();
+
List<HeapEntry*>* entries1 = snapshot1->GetSortedEntriesList();
List<HeapEntry*>* entries2 = snapshot2->GetSortedEntriesList();
int i = 0, j = 0;
@@ -2103,8 +2108,14 @@ HeapSnapshotsDiff* HeapSnapshotsComparator::Compare(HeapSnapshot* snapshot1,
uint64_t id1 = entries1->at(i)->id();
uint64_t id2 = entries2->at(j)->id();
if (id1 == id2) {
- i++;
- j++;
+ HeapEntry* entry1 = entries1->at(i++);
+ HeapEntry* entry2 = entries2->at(j++);
+ if (entry1->painted_reachable() != entry2->painted_reachable()) {
+ if (entry1->painted_reachable())
+ deleted_entries.Add(entry1);
+ else
+ added_entries.Add(entry2);
+ }
} else if (id1 < id2) {
HeapEntry* entry = entries1->at(i++);
deleted_entries.Add(entry);
@@ -2122,35 +2133,17 @@ HeapSnapshotsDiff* HeapSnapshotsComparator::Compare(HeapSnapshot* snapshot1,
added_entries.Add(entry);
}
- snapshot1->ClearPaint();
- snapshot1->root()->PaintAllReachable();
- snapshot2->ClearPaint();
- snapshot2->root()->PaintAllReachable();
- int reachable_deleted_entries = 0, reachable_added_entries = 0;
- for (int i = 0; i < deleted_entries.length(); ++i) {
- HeapEntry* entry = deleted_entries[i];
- if (entry->painted_reachable()) ++reachable_deleted_entries;
- }
- for (int i = 0; i < added_entries.length(); ++i) {
- HeapEntry* entry = added_entries[i];
- if (entry->painted_reachable()) ++reachable_added_entries;
- }
-
HeapSnapshotsDiff* diff = new HeapSnapshotsDiff(snapshot1, snapshot2);
diffs_.Add(diff);
- diff->CreateRoots(reachable_added_entries, reachable_deleted_entries);
+ diff->CreateRoots(added_entries.length(), deleted_entries.length());
- int del_child_index = 0, deleted_entry_index = 1;
for (int i = 0; i < deleted_entries.length(); ++i) {
HeapEntry* entry = deleted_entries[i];
- if (entry->painted_reachable())
- diff->AddDeletedEntry(del_child_index++, deleted_entry_index++, entry);
+ diff->AddDeletedEntry(i, i + 1, entry);
}
- int add_child_index = 0, added_entry_index = 1;
for (int i = 0; i < added_entries.length(); ++i) {
HeapEntry* entry = added_entries[i];
- if (entry->painted_reachable())
- diff->AddAddedEntry(add_child_index++, added_entry_index++, entry);
+ diff->AddAddedEntry(i, i + 1, entry);
}
return diff;
}
diff --git a/deps/v8/src/profile-generator.h b/deps/v8/src/profile-generator.h
index 1e949a2cfb1..4206d29f0dd 100644
--- a/deps/v8/src/profile-generator.h
+++ b/deps/v8/src/profile-generator.h
@@ -662,7 +662,7 @@ class HeapSnapshot {
Type type() { return type_; }
const char* title() { return title_; }
unsigned uid() { return uid_; }
- HeapEntry* root() { return entries_[root_entry_index_]; }
+ HeapEntry* root() { return root_entry_; }
void AllocateEntries(
int entries_count, int children_count, int retainers_count);
@@ -704,7 +704,7 @@ class HeapSnapshot {
Type type_;
const char* title_;
unsigned uid_;
- int root_entry_index_;
+ HeapEntry* root_entry_;
char* raw_entries_;
List<HeapEntry*> entries_;
bool entries_sorted_;
diff --git a/deps/v8/src/v8-counters.h b/deps/v8/src/v8-counters.h
index a8eb9d2a6bf..c6646383633 100644
--- a/deps/v8/src/v8-counters.h
+++ b/deps/v8/src/v8-counters.h
@@ -161,6 +161,8 @@ namespace internal {
SC(named_load_inline_miss, V8.NamedLoadInlineMiss) \
SC(named_load_global_inline, V8.NamedLoadGlobalInline) \
SC(named_load_global_inline_miss, V8.NamedLoadGlobalInlineMiss) \
+ SC(dont_delete_hint_hit, V8.DontDeleteHintHit) \
+ SC(dont_delete_hint_miss, V8.DontDeleteHintMiss) \
SC(named_load_global_stub, V8.NamedLoadGlobalStub) \
SC(named_load_global_stub_miss, V8.NamedLoadGlobalStubMiss) \
SC(keyed_store_field, V8.KeyedStoreField) \
diff --git a/deps/v8/src/version.cc b/deps/v8/src/version.cc
index 33874aa75ca..461c68841d9 100644
--- a/deps/v8/src/version.cc
+++ b/deps/v8/src/version.cc
@@ -34,8 +34,8 @@
// cannot be changed without changing the SCons build script.
#define MAJOR_VERSION 2
#define MINOR_VERSION 4
-#define BUILD_NUMBER 7
-#define PATCH_LEVEL 1
+#define BUILD_NUMBER 8
+#define PATCH_LEVEL 0
#define CANDIDATE_VERSION false
// Define SONAME to have the SCons build the put a specific SONAME into the
diff --git a/deps/v8/src/x64/builtins-x64.cc b/deps/v8/src/x64/builtins-x64.cc
index 08c19ba6dbb..0dead6b793c 100644
--- a/deps/v8/src/x64/builtins-x64.cc
+++ b/deps/v8/src/x64/builtins-x64.cc
@@ -715,7 +715,7 @@ static void ArrayNativeCode(MacroAssembler* masm,
__ cmpq(rax, Immediate(1));
__ j(not_equal, &argc_two_or_more);
__ movq(rdx, Operand(rsp, kPointerSize)); // Get the argument from the stack.
- __ JumpIfNotPositiveSmi(rdx, call_generic_code);
+ __ JumpUnlessNonNegativeSmi(rdx, call_generic_code);
// Handle construction of an empty array of a certain size. Bail out if size
// is to large to actually allocate an elements array.
diff --git a/deps/v8/src/x64/code-stubs-x64.cc b/deps/v8/src/x64/code-stubs-x64.cc
index 9d82e0e31ab..b050ec85dd3 100644
--- a/deps/v8/src/x64/code-stubs-x64.cc
+++ b/deps/v8/src/x64/code-stubs-x64.cc
@@ -3801,7 +3801,7 @@ void SubStringStub::Generate(MacroAssembler* masm) {
Label result_longer_than_two;
__ movq(rcx, Operand(rsp, kToOffset));
__ movq(rdx, Operand(rsp, kFromOffset));
- __ JumpIfNotBothPositiveSmi(rcx, rdx, &runtime);
+ __ JumpUnlessBothNonNegativeSmi(rcx, rdx, &runtime);
__ SmiSub(rcx, rcx, rdx); // Overflow doesn't happen.
__ cmpq(FieldOperand(rax, String::kLengthOffset), rcx);
diff --git a/deps/v8/src/x64/codegen-x64.cc b/deps/v8/src/x64/codegen-x64.cc
index 0d8b827d8cb..ea5a8818af2 100644
--- a/deps/v8/src/x64/codegen-x64.cc
+++ b/deps/v8/src/x64/codegen-x64.cc
@@ -1884,8 +1884,7 @@ Result CodeGenerator::ConstantSmiBinaryOperation(BinaryOperation* expr,
operand->reg(),
smi_value,
overwrite_mode);
- // Check for negative or non-Smi left hand side.
- __ JumpIfNotPositiveSmi(operand->reg(), deferred->entry_label());
+ __ JumpUnlessNonNegativeSmi(operand->reg(), deferred->entry_label());
if (int_value < 0) int_value = -int_value;
if (int_value == 1) {
__ Move(operand->reg(), Smi::FromInt(0));
@@ -5684,9 +5683,9 @@ void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) {
Result value = frame_->Pop();
value.ToRegister();
ASSERT(value.is_valid());
- Condition positive_smi = masm_->CheckPositiveSmi(value.reg());
+ Condition non_negative_smi = masm_->CheckNonNegativeSmi(value.reg());
value.Unuse();
- destination()->Split(positive_smi);
+ destination()->Split(non_negative_smi);
}
@@ -6911,7 +6910,7 @@ void CodeGenerator::GenerateSwapElements(ZoneList<Expression*>* args) {
deferred->Branch(not_equal);
// Check that both indices are smis.
- Condition both_smi = __ CheckBothSmi(index1.reg(), index2.reg());
+ Condition both_smi = masm()->CheckBothSmi(index1.reg(), index2.reg());
deferred->Branch(NegateCondition(both_smi));
// Bring addresses into index1 and index2.
@@ -8377,7 +8376,7 @@ Result CodeGenerator::EmitNamedStore(Handle<String> name, bool is_contextual) {
}
// Check that the receiver is a heap object.
- Condition is_smi = __ CheckSmi(receiver.reg());
+ Condition is_smi = masm()->CheckSmi(receiver.reg());
slow.Branch(is_smi, &value, &receiver);
// This is the map check instruction that will be patched.
@@ -8506,8 +8505,7 @@ Result CodeGenerator::EmitKeyedLoad() {
kScratchRegister);
deferred->Branch(not_equal);
- // Check that the key is a non-negative smi.
- __ JumpIfNotPositiveSmi(key.reg(), deferred->entry_label());
+ __ JumpUnlessNonNegativeSmi(key.reg(), deferred->entry_label());
// Get the elements array from the receiver.
__ movq(elements.reg(),
diff --git a/deps/v8/src/x64/full-codegen-x64.cc b/deps/v8/src/x64/full-codegen-x64.cc
index c15860c7d9e..22561001c73 100644
--- a/deps/v8/src/x64/full-codegen-x64.cc
+++ b/deps/v8/src/x64/full-codegen-x64.cc
@@ -767,7 +767,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
// Get the current entry of the array into register rbx.
__ movq(rbx, Operand(rsp, 2 * kPointerSize));
- SmiIndex index = __ SmiToIndex(rax, rax, kPointerSizeLog2);
+ SmiIndex index = masm()->SmiToIndex(rax, rax, kPointerSizeLog2);
__ movq(rbx, FieldOperand(rbx,
index.reg,
index.scale,
@@ -1407,7 +1407,7 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(Expression* expr,
Label done, stub_call, smi_case;
__ pop(rdx);
__ movq(rcx, rax);
- Condition smi = __ CheckBothSmi(rdx, rax);
+ Condition smi = masm()->CheckBothSmi(rdx, rax);
__ j(smi, &smi_case);
__ bind(&stub_call);
@@ -1965,8 +1965,8 @@ void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) {
context()->PrepareTest(&materialize_true, &materialize_false,
&if_true, &if_false, &fall_through);
- Condition positive_smi = __ CheckPositiveSmi(rax);
- Split(positive_smi, if_true, if_false, fall_through);
+ Condition non_negative_smi = masm()->CheckNonNegativeSmi(rax);
+ Split(non_negative_smi, if_true, if_false, fall_through);
context()->Plug(if_true, if_false);
}
diff --git a/deps/v8/src/x64/ic-x64.cc b/deps/v8/src/x64/ic-x64.cc
index 814da760c88..1d95b7f663d 100644
--- a/deps/v8/src/x64/ic-x64.cc
+++ b/deps/v8/src/x64/ic-x64.cc
@@ -895,7 +895,7 @@ void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) {
// Check that the key is an array index, that is Uint32.
STATIC_ASSERT(kSmiValueSize <= 32);
- __ JumpIfNotPositiveSmi(rax, &slow);
+ __ JumpUnlessNonNegativeSmi(rax, &slow);
// Get the map of the receiver.
__ movq(rcx, FieldOperand(rdx, HeapObject::kMapOffset));
@@ -1729,7 +1729,8 @@ bool LoadIC::PatchInlinedLoad(Address address, Object* map, int offset) {
bool LoadIC::PatchInlinedContextualLoad(Address address,
Object* map,
- Object* cell) {
+ Object* cell,
+ bool is_dont_delete) {
// TODO(<bug#>): implement this.
return false;
}
diff --git a/deps/v8/src/x64/macro-assembler-x64.cc b/deps/v8/src/x64/macro-assembler-x64.cc
index 869986ebc47..2c946f56b9f 100644
--- a/deps/v8/src/x64/macro-assembler-x64.cc
+++ b/deps/v8/src/x64/macro-assembler-x64.cc
@@ -825,7 +825,7 @@ Condition MacroAssembler::CheckSmi(Register src) {
}
-Condition MacroAssembler::CheckPositiveSmi(Register src) {
+Condition MacroAssembler::CheckNonNegativeSmi(Register src) {
ASSERT_EQ(0, kSmiTag);
// Make mask 0x8000000000000001 and test that both bits are zero.
movq(kScratchRegister, src);
@@ -846,15 +846,15 @@ Condition MacroAssembler::CheckBothSmi(Register first, Register second) {
}
-Condition MacroAssembler::CheckBothPositiveSmi(Register first,
- Register second) {
+Condition MacroAssembler::CheckBothNonNegativeSmi(Register first,
+ Register second) {
if (first.is(second)) {
- return CheckPositiveSmi(first);
+ return CheckNonNegativeSmi(first);
}
movq(kScratchRegister, first);
or_(kScratchRegister, second);
rol(kScratchRegister, Immediate(1));
- testl(kScratchRegister, Immediate(0x03));
+ testl(kScratchRegister, Immediate(3));
return zero;
}
diff --git a/deps/v8/src/x64/macro-assembler-x64.h b/deps/v8/src/x64/macro-assembler-x64.h
index a8ffca918c9..1bd34435912 100644
--- a/deps/v8/src/x64/macro-assembler-x64.h
+++ b/deps/v8/src/x64/macro-assembler-x64.h
@@ -265,14 +265,14 @@ class MacroAssembler: public Assembler {
// Is the value a tagged smi.
Condition CheckSmi(Register src);
- // Is the value a positive tagged smi.
- Condition CheckPositiveSmi(Register src);
+ // Is the value a non-negative tagged smi.
+ Condition CheckNonNegativeSmi(Register src);
// Are both values tagged smis.
Condition CheckBothSmi(Register first, Register second);
- // Are both values tagged smis.
- Condition CheckBothPositiveSmi(Register first, Register second);
+ // Are both values non-negative tagged smis.
+ Condition CheckBothNonNegativeSmi(Register first, Register second);
// Are either value a tagged smi.
Condition CheckEitherSmi(Register first,
@@ -311,9 +311,9 @@ class MacroAssembler: public Assembler {
template <typename LabelType>
void JumpIfNotSmi(Register src, LabelType* on_not_smi);
- // Jump to label if the value is not a positive tagged smi.
+ // Jump to label if the value is not a non-negative tagged smi.
template <typename LabelType>
- void JumpIfNotPositiveSmi(Register src, LabelType* on_not_smi);
+ void JumpUnlessNonNegativeSmi(Register src, LabelType* on_not_smi);
// Jump to label if the value, which must be a tagged smi, has value equal
// to the constant.
@@ -328,10 +328,10 @@ class MacroAssembler: public Assembler {
Register src2,
LabelType* on_not_both_smi);
- // Jump if either or both register are not positive smi values.
+ // Jump if either or both register are not non-negative smi values.
template <typename LabelType>
- void JumpIfNotBothPositiveSmi(Register src1, Register src2,
- LabelType* on_not_both_smi);
+ void JumpUnlessBothNonNegativeSmi(Register src1, Register src2,
+ LabelType* on_not_both_smi);
// Operations on tagged smi values.
@@ -1463,10 +1463,10 @@ void MacroAssembler::JumpIfNotSmi(Register src, LabelType* on_not_smi) {
template <typename LabelType>
-void MacroAssembler::JumpIfNotPositiveSmi(Register src,
- LabelType* on_not_positive_smi) {
- Condition positive_smi = CheckPositiveSmi(src);
- j(NegateCondition(positive_smi), on_not_positive_smi);
+void MacroAssembler::JumpUnlessNonNegativeSmi(
+ Register src, LabelType* on_not_smi_or_negative) {
+ Condition non_negative_smi = CheckNonNegativeSmi(src);
+ j(NegateCondition(non_negative_smi), on_not_smi_or_negative);
}
@@ -1505,10 +1505,10 @@ void MacroAssembler::JumpIfNotBothSmi(Register src1,
template <typename LabelType>
-void MacroAssembler::JumpIfNotBothPositiveSmi(Register src1,
- Register src2,
- LabelType* on_not_both_smi) {
- Condition both_smi = CheckBothPositiveSmi(src1, src2);
+void MacroAssembler::JumpUnlessBothNonNegativeSmi(Register src1,
+ Register src2,
+ LabelType* on_not_both_smi) {
+ Condition both_smi = CheckBothNonNegativeSmi(src1, src2);
j(NegateCondition(both_smi), on_not_both_smi);
}
diff --git a/deps/v8/test/cctest/cctest.status b/deps/v8/test/cctest/cctest.status
index d03f5f7a00c..895e24539ee 100644
--- a/deps/v8/test/cctest/cctest.status
+++ b/deps/v8/test/cctest/cctest.status
@@ -35,11 +35,6 @@ test-debug/DebuggerAgent: PASS, (PASS || FAIL) if $system == linux
# BUG(382): Weird test. Can't guarantee that it never times out.
test-api/ApplyInterruption: PASS || TIMEOUT
-# Bug (484): This test which we thought was originally corrected in r5236
-# is reappering. Disabled until bug in test is fixed. This only fails
-# when snapshot is on, so I am marking it PASS || FAIL
-test-heap-profiler/HeapSnapshotsDiff: PASS || FAIL
-
# These tests always fail. They are here to test test.py. If
# they don't fail then test.py has failed.
test-serialize/TestThatAlwaysFails: FAIL
diff --git a/deps/v8/test/cctest/test-api.cc b/deps/v8/test/cctest/test-api.cc
index 527c9a38cc4..f1a6eada40e 100644
--- a/deps/v8/test/cctest/test-api.cc
+++ b/deps/v8/test/cctest/test-api.cc
@@ -8099,7 +8099,7 @@ static int GetGlobalObjectsCount() {
}
-static int GetSurvivingGlobalObjectsCount() {
+static void CheckSurvivingGlobalObjectsCount(int expected) {
// We need to collect all garbage twice to be sure that everything
// has been collected. This is because inline caches are cleared in
// the first garbage collection but some of the maps have already
@@ -8109,9 +8109,9 @@ static int GetSurvivingGlobalObjectsCount() {
i::Heap::CollectAllGarbage(false);
int count = GetGlobalObjectsCount();
#ifdef DEBUG
- if (count > 0) i::Heap::TracePathToGlobal();
+ if (count != expected) i::Heap::TracePathToGlobal();
#endif
- return count;
+ CHECK_EQ(expected, count);
}
@@ -8120,25 +8120,23 @@ TEST(DontLeakGlobalObjects) {
v8::V8::Initialize();
- int count = GetSurvivingGlobalObjectsCount();
-
for (int i = 0; i < 5; i++) {
{ v8::HandleScope scope;
LocalContext context;
}
- CHECK_EQ(count, GetSurvivingGlobalObjectsCount());
+ CheckSurvivingGlobalObjectsCount(0);
{ v8::HandleScope scope;
LocalContext context;
v8_compile("Date")->Run();
}
- CHECK_EQ(count, GetSurvivingGlobalObjectsCount());
+ CheckSurvivingGlobalObjectsCount(0);
{ v8::HandleScope scope;
LocalContext context;
v8_compile("/aaa/")->Run();
}
- CHECK_EQ(count, GetSurvivingGlobalObjectsCount());
+ CheckSurvivingGlobalObjectsCount(0);
{ v8::HandleScope scope;
const char* extension_list[] = { "v8/gc" };
@@ -8146,7 +8144,7 @@ TEST(DontLeakGlobalObjects) {
LocalContext context(&extensions);
v8_compile("gc();")->Run();
}
- CHECK_EQ(count, GetSurvivingGlobalObjectsCount());
+ CheckSurvivingGlobalObjectsCount(0);
}
}
@@ -11483,3 +11481,141 @@ TEST(BooleanCheckMultipleContexts) {
ExpectString(code, "");
}
}
+
+
+TEST(DontDeleteCellLoadIC) {
+ const char* function_code =
+ "function readCell() { while (true) { return cell; } }";
+
+ {
+ // Run the code twice in the first context to initialize the load
+ // IC for a don't delete cell.
+ v8::HandleScope scope;
+ LocalContext context1;
+ CompileRun("var cell = \"first\";");
+ ExpectBoolean("delete cell", false);
+ CompileRun(function_code);
+ ExpectString("readCell()", "first");
+ ExpectString("readCell()", "first");
+ }
+
+ {
+ // Use a deletable cell in the second context.
+ v8::HandleScope scope;
+ LocalContext context2;
+ CompileRun("cell = \"second\";");
+ CompileRun(function_code);
+ ExpectString("readCell()", "second");
+ ExpectBoolean("delete cell", true);
+ ExpectString("(function() {"
+ " try {"
+ " return readCell();"
+ " } catch(e) {"
+ " return e.toString();"
+ " }"
+ "})()",
+ "ReferenceError: cell is not defined");
+ CompileRun("cell = \"new_second\";");
+ i::Heap::CollectAllGarbage(true);
+ ExpectString("readCell()", "new_second");
+ ExpectString("readCell()", "new_second");
+ }
+}
+
+
+TEST(DontDeleteCellLoadICForceDelete) {
+ const char* function_code =
+ "function readCell() { while (true) { return cell; } }";
+
+ // Run the code twice to initialize the load IC for a don't delete
+ // cell.
+ v8::HandleScope scope;
+ LocalContext context;
+ CompileRun("var cell = \"value\";");
+ ExpectBoolean("delete cell", false);
+ CompileRun(function_code);
+ ExpectString("readCell()", "value");
+ ExpectString("readCell()", "value");
+
+ // Delete the cell using the API and check the inlined code works
+ // correctly.
+ CHECK(context->Global()->ForceDelete(v8_str("cell")));
+ ExpectString("(function() {"
+ " try {"
+ " return readCell();"
+ " } catch(e) {"
+ " return e.toString();"
+ " }"
+ "})()",
+ "ReferenceError: cell is not defined");
+}
+
+
+TEST(DontDeleteCellLoadICAPI) {
+ const char* function_code =
+ "function readCell() { while (true) { return cell; } }";
+
+ // Run the code twice to initialize the load IC for a don't delete
+ // cell created using the API.
+ v8::HandleScope scope;
+ LocalContext context;
+ context->Global()->Set(v8_str("cell"), v8_str("value"), v8::DontDelete);
+ ExpectBoolean("delete cell", false);
+ CompileRun(function_code);
+ ExpectString("readCell()", "value");
+ ExpectString("readCell()", "value");
+
+ // Delete the cell using the API and check the inlined code works
+ // correctly.
+ CHECK(context->Global()->ForceDelete(v8_str("cell")));
+ ExpectString("(function() {"
+ " try {"
+ " return readCell();"
+ " } catch(e) {"
+ " return e.toString();"
+ " }"
+ "})()",
+ "ReferenceError: cell is not defined");
+}
+
+
+TEST(GlobalLoadICGC) {
+ const char* function_code =
+ "function readCell() { while (true) { return cell; } }";
+
+ // Check inline load code for a don't delete cell is cleared during
+ // GC.
+ {
+ v8::HandleScope scope;
+ LocalContext context;
+ CompileRun("var cell = \"value\";");
+ ExpectBoolean("delete cell", false);
+ CompileRun(function_code);
+ ExpectString("readCell()", "value");
+ ExpectString("readCell()", "value");
+ }
+ {
+ v8::HandleScope scope;
+ LocalContext context2;
+ // Hold the code object in the second context.
+ CompileRun(function_code);
+ CheckSurvivingGlobalObjectsCount(1);
+ }
+
+ // Check inline load code for a deletable cell is cleared during GC.
+ {
+ v8::HandleScope scope;
+ LocalContext context;
+ CompileRun("cell = \"value\";");
+ CompileRun(function_code);
+ ExpectString("readCell()", "value");
+ ExpectString("readCell()", "value");
+ }
+ {
+ v8::HandleScope scope;
+ LocalContext context2;
+ // Hold the code object in the second context.
+ CompileRun(function_code);
+ CheckSurvivingGlobalObjectsCount(1);
+ }
+}
diff --git a/deps/v8/test/cctest/test-heap-profiler.cc b/deps/v8/test/cctest/test-heap-profiler.cc
index 5e570f34de3..6340da53d8c 100644
--- a/deps/v8/test/cctest/test-heap-profiler.cc
+++ b/deps/v8/test/cctest/test-heap-profiler.cc
@@ -787,6 +787,7 @@ TEST(HeapSnapshotsDiff) {
CompileAndRunScript(
"function A() {}\n"
"function B(x) { this.x = x; }\n"
+ "function A2(a) { for (var i = 0; i < a; ++i) this[i] = i; }\n"
"var a = new A();\n"
"var b = new B(a);");
const v8::HeapSnapshot* snapshot1 =
@@ -795,7 +796,7 @@ TEST(HeapSnapshotsDiff) {
CompileAndRunScript(
"delete a;\n"
"b.x = null;\n"
- "var a = new A();\n"
+ "var a = new A2(20);\n"
"var b2 = new B(a);");
const v8::HeapSnapshot* snapshot2 =
v8::HeapProfiler::TakeSnapshot(v8::String::New("s2"));
@@ -811,7 +812,7 @@ TEST(HeapSnapshotsDiff) {
const v8::HeapGraphNode* node = prop->GetToNode();
if (node->GetType() == v8::HeapGraphNode::kObject) {
v8::String::AsciiValue node_name(node->GetName());
- if (strcmp(*node_name, "A") == 0) {
+ if (strcmp(*node_name, "A2") == 0) {
CHECK(IsNodeRetainedAs(node, v8::HeapGraphEdge::kProperty, "a"));
CHECK(!found_A);
found_A = true;
@@ -849,6 +850,19 @@ TEST(HeapSnapshotsDiff) {
}
+TEST(HeapSnapshotRootPreservedAfterSorting) {
+ v8::HandleScope scope;
+ LocalContext env;
+ const v8::HeapSnapshot* snapshot =
+ v8::HeapProfiler::TakeSnapshot(v8::String::New("s"));
+ const v8::HeapGraphNode* root1 = snapshot->GetRoot();
+ const_cast<i::HeapSnapshot*>(reinterpret_cast<const i::HeapSnapshot*>(
+ snapshot))->GetSortedEntriesList();
+ const v8::HeapGraphNode* root2 = snapshot->GetRoot();
+ CHECK_EQ(root1, root2);
+}
+
+
namespace v8 {
namespace internal {
diff --git a/deps/v8/test/cctest/test-macro-assembler-x64.cc b/deps/v8/test/cctest/test-macro-assembler-x64.cc
index 3d2b91b544e..9b1fc46eaf6 100755
--- a/deps/v8/test/cctest/test-macro-assembler-x64.cc
+++ b/deps/v8/test/cctest/test-macro-assembler-x64.cc
@@ -519,40 +519,40 @@ TEST(SmiCheck) {
__ incq(rax);
__ movl(rcx, Immediate(0));
__ Integer32ToSmi(rcx, rcx);
- cond = masm->CheckPositiveSmi(rcx); // Zero counts as positive.
+ cond = masm->CheckNonNegativeSmi(rcx);
__ j(NegateCondition(cond), &exit);
__ incq(rax);
__ xor_(rcx, Immediate(kSmiTagMask));
- cond = masm->CheckPositiveSmi(rcx); // "zero" non-smi.
+ cond = masm->CheckNonNegativeSmi(rcx); // "zero" non-smi.
__ j(cond, &exit);
__ incq(rax);
__ movq(rcx, Immediate(-1));
__ Integer32ToSmi(rcx, rcx);
- cond = masm->CheckPositiveSmi(rcx); // Negative smis are not positive.
+ cond = masm->CheckNonNegativeSmi(rcx); // Negative smis are not positive.
__ j(cond, &exit);
__ incq(rax);
__ movq(rcx, Immediate(Smi::kMinValue));
__ Integer32ToSmi(rcx, rcx);
- cond = masm->CheckPositiveSmi(rcx); // Most negative smi is not positive.
+ cond = masm->CheckNonNegativeSmi(rcx); // Most negative smi is not positive.
__ j(cond, &exit);
__ incq(rax);
__ xor_(rcx, Immediate(kSmiTagMask));
- cond = masm->CheckPositiveSmi(rcx); // "Negative" non-smi.
+ cond = masm->CheckNonNegativeSmi(rcx); // "Negative" non-smi.
__ j(cond, &exit);
__ incq(rax);
__ movq(rcx, Immediate(Smi::kMaxValue));
__ Integer32ToSmi(rcx, rcx);
- cond = masm->CheckPositiveSmi(rcx); // Most positive smi is positive.
+ cond = masm->CheckNonNegativeSmi(rcx); // Most positive smi is positive.
__ j(NegateCondition(cond), &exit);
__ incq(rax);
__ xor_(rcx, Immediate(kSmiTagMask));
- cond = masm->CheckPositiveSmi(rcx); // "Positive" non-smi.
+ cond = masm->CheckNonNegativeSmi(rcx); // "Positive" non-smi.
__ j(cond, &exit);
// CheckIsMinSmi
diff --git a/deps/v8/test/cctest/test-regexp.cc b/deps/v8/test/cctest/test-regexp.cc
index 186350be3d0..11a808e3699 100644
--- a/deps/v8/test/cctest/test-regexp.cc
+++ b/deps/v8/test/cctest/test-regexp.cc
@@ -64,7 +64,7 @@ static bool CheckParse(const char* input) {
ZoneScope zone_scope(DELETE_ON_EXIT);
FlatStringReader reader(CStrVector(input));
RegExpCompileData result;
- return v8::internal::ParseRegExp(&reader, false, &result);
+ return v8::internal::Parser::ParseRegExp(&reader, false, &result);
}
@@ -74,7 +74,7 @@ static SmartPointer<const char> Parse(const char* input) {
ZoneScope zone_scope(DELETE_ON_EXIT);
FlatStringReader reader(CStrVector(input));
RegExpCompileData result;
- CHECK(v8::internal::ParseRegExp(&reader, false, &result));
+ CHECK(v8::internal::Parser::ParseRegExp(&reader, false, &result));
CHECK(result.tree != NULL);
CHECK(result.error.is_null());
SmartPointer<const char> output = result.tree->ToString();
@@ -88,7 +88,7 @@ static bool CheckSimple(const char* input) {
ZoneScope zone_scope(DELETE_ON_EXIT);
FlatStringReader reader(CStrVector(input));
RegExpCompileData result;
- CHECK(v8::internal::ParseRegExp(&reader, false, &result));
+ CHECK(v8::internal::Parser::ParseRegExp(&reader, false, &result));
CHECK(result.tree != NULL);
CHECK(result.error.is_null());
return result.simple;
@@ -106,7 +106,7 @@ static MinMaxPair CheckMinMaxMatch(const char* input) {
ZoneScope zone_scope(DELETE_ON_EXIT);
FlatStringReader reader(CStrVector(input));
RegExpCompileData result;
- CHECK(v8::internal::ParseRegExp(&reader, false, &result));
+ CHECK(v8::internal::Parser::ParseRegExp(&reader, false, &result));
CHECK(result.tree != NULL);
CHECK(result.error.is_null());
int min_match = result.tree->min_match();
@@ -365,7 +365,7 @@ static void ExpectError(const char* input,
ZoneScope zone_scope(DELETE_ON_EXIT);
FlatStringReader reader(CStrVector(input));
RegExpCompileData result;
- CHECK_EQ(false, v8::internal::ParseRegExp(&reader, false, &result));
+ CHECK_EQ(false, v8::internal::Parser::ParseRegExp(&reader, false, &result));
CHECK(result.tree == NULL);
CHECK(!result.error.is_null());
SmartPointer<char> str = result.error->ToCString(ALLOW_NULLS);
@@ -473,7 +473,7 @@ static RegExpNode* Compile(const char* input, bool multiline, bool is_ascii) {
V8::Initialize(NULL);
FlatStringReader reader(CStrVector(input));
RegExpCompileData compile_data;
- if (!v8::internal::ParseRegExp(&reader, multiline, &compile_data))
+ if (!v8::internal::Parser::ParseRegExp(&reader, multiline, &compile_data))
return NULL;
Handle<String> pattern = Factory::NewStringFromUtf8(CStrVector(input));
RegExpEngine::Compile(&compile_data, false, multiline, pattern, is_ascii);