diff options
author | Ryan Dahl <ry@tinyclouds.org> | 2010-10-06 02:25:07 +0400 |
---|---|---|
committer | Ryan Dahl <ry@tinyclouds.org> | 2010-10-06 02:25:07 +0400 |
commit | 7fca10133861348417f33dac2d656cbfd9d1bb0d (patch) | |
tree | 91ce5d67766de7f3ce43c24d552238541f764925 /deps | |
parent | dbf0d6bb70902fba80b10adccf3f54fe9cf5beb7 (diff) |
Upgrade V8 to 2.4.8
Diffstat (limited to 'deps')
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); |