Browse Source

Upgrade V8 to 2.4.8

v0.7.4-release
Ryan Dahl 14 years ago
parent
commit
7fca101338
  1. 8
      deps/v8/ChangeLog
  2. 8
      deps/v8/src/api.cc
  3. 3
      deps/v8/src/arm/ic-arm.cc
  4. 12
      deps/v8/src/compiler.cc
  5. 3
      deps/v8/src/compiler.h
  6. 2
      deps/v8/src/handles.cc
  7. 47
      deps/v8/src/ia32/codegen-ia32.cc
  8. 28
      deps/v8/src/ia32/ic-ia32.cc
  9. 10
      deps/v8/src/ic.cc
  10. 3
      deps/v8/src/ic.h
  11. 4
      deps/v8/src/jsregexp.cc
  12. 13
      deps/v8/src/liveedit.cc
  13. 1
      deps/v8/src/log-utils.h
  14. 6
      deps/v8/src/objects-visiting.h
  15. 5
      deps/v8/src/objects.cc
  16. 2
      deps/v8/src/objects.h
  17. 284
      deps/v8/src/parser.cc
  18. 307
      deps/v8/src/parser.h
  19. 49
      deps/v8/src/profile-generator.cc
  20. 4
      deps/v8/src/profile-generator.h
  21. 2
      deps/v8/src/v8-counters.h
  22. 4
      deps/v8/src/version.cc
  23. 2
      deps/v8/src/x64/builtins-x64.cc
  24. 2
      deps/v8/src/x64/code-stubs-x64.cc
  25. 14
      deps/v8/src/x64/codegen-x64.cc
  26. 8
      deps/v8/src/x64/full-codegen-x64.cc
  27. 5
      deps/v8/src/x64/ic-x64.cc
  28. 10
      deps/v8/src/x64/macro-assembler-x64.cc
  29. 34
      deps/v8/src/x64/macro-assembler-x64.h
  30. 5
      deps/v8/test/cctest/cctest.status
  31. 154
      deps/v8/test/cctest/test-api.cc
  32. 18
      deps/v8/test/cctest/test-heap-profiler.cc
  33. 14
      deps/v8/test/cctest/test-macro-assembler-x64.cc
  34. 12
      deps/v8/test/cctest/test-regexp.cc

8
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

8
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);
}

3
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;
}

12
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) {

3
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 {

2
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;
}

47
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

28
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.

10
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());

3
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;
};

4
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,

13
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) {

1
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;
}

6
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_

5
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);

2
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.

284
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);

307
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

49
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;
}

4
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_;

2
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) \

4
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

2
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.

2
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);

14
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(),

8
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);
}

5
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;
}

10
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;
}

34
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);
}

5
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

154
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);
}
}

18
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 {

14
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

12
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);

Loading…
Cancel
Save