diff options
author | Ryan Dahl <ry@tinyclouds.org> | 2010-12-14 09:03:33 +0300 |
---|---|---|
committer | Ryan Dahl <ry@tinyclouds.org> | 2010-12-14 09:12:14 +0300 |
commit | 1d78159e8f8ad7f41167a38ebfa973ed055bc7b6 (patch) | |
tree | bb05356b1eee2278149dfb3d52c34272ef30f149 /deps | |
parent | 3d0627dc6aae4937c7542243535cade959ced2ee (diff) |
Upgrade V8 to 3.0.1
Diffstat (limited to 'deps')
98 files changed, 7902 insertions, 6595 deletions
diff --git a/deps/v8/ChangeLog b/deps/v8/ChangeLog index 91b583fd0dc..2debaa09fc5 100644 --- a/deps/v8/ChangeLog +++ b/deps/v8/ChangeLog @@ -1,3 +1,26 @@ +2010-12-13: Version 3.0.1 + + Added support for an experimental internationalization API as an + extension. This extension is disabled by default but can be enabled + when building V8. The ECMAScript internationalization strawman is + at http://wiki.ecmascript.org/doku.php?id=strawman:i18n_api. + + Made RegExp character class parsing stricter. This mirrors a change + to RegExp parsing in WebKit. + + Fixed a bug in Object.defineProperty when used to change attributes + of an existing property. It incorrectly set the property value to + undefined (issue 965). + + Fixed several different compilation failures on various platforms + caused by the 3.0.0 release. + + Optimized Math.pow so it can work on unboxed doubles. + + Sped up quoting of JSON strings by removing one traversal of the + string. + + 2010-12-07: Version 3.0.0 Improved performance by (partially) addressing issue 957 on @@ -132,7 +155,7 @@ Added USE_SIMULATOR macro that explicitly indicates that we wish to use the simulator as the execution engine (by Mark Lam <mark.lam@palm.com> - from Hewlett-Packard Development Company, LP). + from Hewlett-Packard Development Company, LP). Fixed compilation error on ARM with gcc 4.4 (issue 894). diff --git a/deps/v8/include/v8-preparser.h b/deps/v8/include/v8-preparser.h index 68ce50223ec..9425f7d4672 100644 --- a/deps/v8/include/v8-preparser.h +++ b/deps/v8/include/v8-preparser.h @@ -99,13 +99,6 @@ class UnicodeInputStream { // Returns the next Unicode code-point in the input, or a negative value when // there is no more input in the stream. virtual int32_t Next() = 0; - - // Pushes a read character back into the stream, so that it will be the next - // to be read by Advance(). The character pushed back must be the most - // recently read character that hasn't already been pushed back (i.e., if - // pushing back more than one character, they must occur in the opposite order - // of the one they were read in). - virtual void PushBack(int32_t ch) = 0; }; diff --git a/deps/v8/include/v8-profiler.h b/deps/v8/include/v8-profiler.h index 08f47ca36e6..675a229854e 100644 --- a/deps/v8/include/v8-profiler.h +++ b/deps/v8/include/v8-profiler.h @@ -245,7 +245,6 @@ class V8EXPORT HeapGraphPath { class V8EXPORT HeapGraphNode { public: enum Type { - kInternal = 0, // For compatibility, will be removed. kHidden = 0, // Hidden node, may be filtered when shown to user. kArray = 1, // An array of elements. kString = 2, // A string. @@ -413,7 +412,8 @@ class V8EXPORT HeapProfiler { */ static const HeapSnapshot* TakeSnapshot( Handle<String> title, - HeapSnapshot::Type type = HeapSnapshot::kFull); + HeapSnapshot::Type type = HeapSnapshot::kFull, + ActivityControl* control = NULL); }; diff --git a/deps/v8/include/v8.h b/deps/v8/include/v8.h index 8ecf63aebd6..7fd063197e8 100644 --- a/deps/v8/include/v8.h +++ b/deps/v8/include/v8.h @@ -3281,6 +3281,24 @@ class V8EXPORT OutputStream { // NOLINT }; +/** + * An interface for reporting progress and controlling long-running + * activities. + */ +class V8EXPORT ActivityControl { // NOLINT + public: + enum ControlOption { + kContinue = 0, + kAbort = 1 + }; + virtual ~ActivityControl() {} + /** + * Notify about current progress. The activity can be stopped by + * returning kAbort as the callback result. + */ + virtual ControlOption ReportProgressValue(int done, int total) = 0; +}; + // --- I m p l e m e n t a t i o n --- diff --git a/deps/v8/preparser/preparser-process.cc b/deps/v8/preparser/preparser-process.cc index 80e83508e42..26dfc42b53a 100644 --- a/deps/v8/preparser/preparser-process.cc +++ b/deps/v8/preparser/preparser-process.cc @@ -127,7 +127,7 @@ uint32_t ReadUInt32(FILE* source, bool* ok) { bool ReadBuffer(FILE* source, void* buffer, size_t length) { - size_t actually_read = fread(buffer, 1, length, stdin); + size_t actually_read = fread(buffer, 1, length, source); return (actually_read == length); } @@ -150,22 +150,25 @@ class ScopedPointer { }; -// Preparse stdin and output result on stdout. -int PreParseIO() { +// Preparse input and output result on stdout. +int PreParseIO(FILE* input) { fprintf(stderr, "LOG: Enter parsing loop\n"); bool ok = true; - uint32_t length = ReadUInt32(stdin, &ok); + uint32_t length = ReadUInt32(input, &ok); + fprintf(stderr, "LOG: Input length: %d\n", length); if (!ok) return kErrorReading; ScopedPointer<uint8_t> buffer(new uint8_t[length]); - if (!ReadBuffer(stdin, *buffer, length)) { + if (!ReadBuffer(input, *buffer, length)) { return kErrorReading; } UTF8InputStream input_buffer(*buffer, static_cast<size_t>(length)); v8::PreParserData data = - v8::Preparse(&input_buffer, 64 * sizeof(void*)); // NOLINT + v8::Preparse(&input_buffer, 64 * 1024 * sizeof(void*)); // NOLINT if (data.stack_overflow()) { + fprintf(stderr, "LOG: Stack overflow\n"); + fflush(stderr); // Report stack overflow error/no-preparser-data. WriteUInt32(stdout, 0, &ok); if (!ok) return kErrorWriting; @@ -173,6 +176,8 @@ int PreParseIO() { } uint32_t size = data.size(); + fprintf(stderr, "LOG: Success, data size: %u\n", size); + fflush(stderr); WriteUInt32(stdout, size, &ok); if (!ok) return kErrorWriting; if (!WriteBuffer(stdout, data.data(), size)) { @@ -185,10 +190,17 @@ int PreParseIO() { int main(int argc, char* argv[]) { + FILE* input = stdin; + if (argc > 1) { + char* arg = argv[1]; + input = fopen(arg, "rb"); + if (input == NULL) return EXIT_FAILURE; + } int status = 0; do { - status = v8::internal::PreParseIO(); + status = v8::internal::PreParseIO(input); } while (status == 0); fprintf(stderr, "EXIT: Failure %d\n", status); + fflush(stderr); return EXIT_FAILURE; } diff --git a/deps/v8/samples/shell.cc b/deps/v8/samples/shell.cc index 460457552c5..6b67df6c6c5 100644 --- a/deps/v8/samples/shell.cc +++ b/deps/v8/samples/shell.cc @@ -45,7 +45,6 @@ v8::Handle<v8::Value> Quit(const v8::Arguments& args); v8::Handle<v8::Value> Version(const v8::Arguments& args); v8::Handle<v8::String> ReadFile(const char* name); void ReportException(v8::TryCatch* handler); -void SetFlagsFromString(const char* flags); int RunMain(int argc, char* argv[]) { @@ -345,8 +344,3 @@ void ReportException(v8::TryCatch* try_catch) { } } } - - -void SetFlagsFromString(const char* flags) { - v8::V8::SetFlagsFromString(flags, strlen(flags)); -} diff --git a/deps/v8/src/api.cc b/deps/v8/src/api.cc index 0ec8cf123e4..e169bd08a09 100644 --- a/deps/v8/src/api.cc +++ b/deps/v8/src/api.cc @@ -1165,14 +1165,22 @@ void ObjectTemplate::SetInternalFieldCount(int value) { ScriptData* ScriptData::PreCompile(const char* input, int length) { - unibrow::Utf8InputBuffer<> buf(input, length); - return i::ParserApi::PreParse(i::Handle<i::String>(), &buf, NULL); + i::Utf8ToUC16CharacterStream stream( + reinterpret_cast<const unsigned char*>(input), length); + return i::ParserApi::PreParse(&stream, NULL); } ScriptData* ScriptData::PreCompile(v8::Handle<String> source) { i::Handle<i::String> str = Utils::OpenHandle(*source); - return i::ParserApi::PreParse(str, NULL, NULL); + if (str->IsExternalTwoByteString()) { + i::ExternalTwoByteStringUC16CharacterStream stream( + i::Handle<i::ExternalTwoByteString>::cast(str), 0, str->length()); + return i::ParserApi::PreParse(&stream, NULL); + } else { + i::GenericStringUC16CharacterStream stream(str, 0, str->length()); + return i::ParserApi::PreParse(&stream, NULL); + } } @@ -4939,7 +4947,8 @@ const HeapSnapshot* HeapProfiler::FindSnapshot(unsigned uid) { const HeapSnapshot* HeapProfiler::TakeSnapshot(Handle<String> title, - HeapSnapshot::Type type) { + HeapSnapshot::Type type, + ActivityControl* control) { IsDeadCheck("v8::HeapProfiler::TakeSnapshot"); i::HeapSnapshot::Type internal_type = i::HeapSnapshot::kFull; switch (type) { @@ -4953,7 +4962,8 @@ const HeapSnapshot* HeapProfiler::TakeSnapshot(Handle<String> title, UNREACHABLE(); } return reinterpret_cast<const HeapSnapshot*>( - i::HeapProfiler::TakeSnapshot(*Utils::OpenHandle(*title), internal_type)); + i::HeapProfiler::TakeSnapshot( + *Utils::OpenHandle(*title), internal_type, control)); } #endif // ENABLE_LOGGING_AND_PROFILING diff --git a/deps/v8/src/arm/full-codegen-arm.cc b/deps/v8/src/arm/full-codegen-arm.cc index 7e4a28042fc..921629d6f23 100644 --- a/deps/v8/src/arm/full-codegen-arm.cc +++ b/deps/v8/src/arm/full-codegen-arm.cc @@ -890,7 +890,9 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { __ bind(&update_each); __ mov(result_register(), r3); // Perform the assignment as if via '='. - EmitAssignment(stmt->each()); + { EffectContext context(this); + EmitAssignment(stmt->each(), stmt->AssignmentId()); + } // Generate code for the body of the loop. Visit(stmt->body()); @@ -1444,7 +1446,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { // For property compound assignments we need another deoptimization // point after the property load. if (property != NULL) { - PrepareForBailoutForId(expr->compound_bailout_id(), TOS_REG); + PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG); } Token::Value op = expr->binary_op(); @@ -1536,7 +1538,7 @@ void FullCodeGenerator::EmitBinaryOp(Token::Value op, } -void FullCodeGenerator::EmitAssignment(Expression* expr) { +void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) { // Invalid left-hand sides are rewritten to have a 'throw // ReferenceError' on the left-hand side. if (!expr->IsValidLeftHandSide()) { @@ -1584,6 +1586,8 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) { break; } } + PrepareForBailoutForId(bailout_ast_id, TOS_REG); + context()->Plug(r0); } @@ -1657,8 +1661,6 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, } __ bind(&done); } - - context()->Plug(result_register()); } @@ -1701,10 +1703,10 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { __ push(ip); __ CallRuntime(Runtime::kToFastProperties, 1); __ pop(r0); - context()->DropAndPlug(1, r0); - } else { - context()->Plug(r0); + __ Drop(1); } + PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); + context()->Plug(r0); } @@ -1745,10 +1747,10 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { __ push(ip); __ CallRuntime(Runtime::kToFastProperties, 1); __ pop(r0); - context()->DropAndPlug(1, r0); - } else { - context()->Plug(r0); + __ Drop(1); } + PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); + context()->Plug(r0); } @@ -3200,6 +3202,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { { EffectContext context(this); EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), Token::ASSIGN); + PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); + context.Plug(r0); } // For all contexts except EffectConstant We have the result on // top of the stack. @@ -3209,6 +3213,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { } else { EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), Token::ASSIGN); + PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); + context()->Plug(r0); } break; case NAMED_PROPERTY: { @@ -3216,6 +3222,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { __ pop(r1); Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); EmitCallIC(ic, RelocInfo::CODE_TARGET); + PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); if (expr->is_postfix()) { if (!context()->IsEffect()) { context()->PlugTOS(); @@ -3230,6 +3237,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { __ pop(r2); // Receiver. Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); EmitCallIC(ic, RelocInfo::CODE_TARGET); + PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); if (expr->is_postfix()) { if (!context()->IsEffect()) { context()->PlugTOS(); diff --git a/deps/v8/src/arm/lithium-arm.cc b/deps/v8/src/arm/lithium-arm.cc index 682c448fd53..ef982f1076e 100644 --- a/deps/v8/src/arm/lithium-arm.cc +++ b/deps/v8/src/arm/lithium-arm.cc @@ -460,12 +460,6 @@ int LChunk::NearestGapPos(int index) const { } -int LChunk::NearestNextGapPos(int index) const { - while (!IsGapAt(index)) index++; - return index; -} - - void LChunk::AddGapMove(int index, LOperand* from, LOperand* to) { GetGapAt(index)->GetOrCreateParallelMove(LGap::START)->AddMove(from, to); } @@ -1357,6 +1351,9 @@ LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) { return AssignEnvironment(DefineAsRegister(result)); case kMathSqrt: return DefineSameAsFirst(result); + case kMathPowHalf: + Abort("MathPowHalf LUnaryMathOperation not implemented"); + return NULL; default: UNREACHABLE(); return NULL; @@ -1554,6 +1551,12 @@ LInstruction* LChunkBuilder::DoAdd(HAdd* instr) { } +LInstruction* LChunkBuilder::DoPower(HPower* instr) { + Abort("LPower instruction not implemented on ARM"); + return NULL; +} + + LInstruction* LChunkBuilder::DoCompare(HCompare* instr) { Token::Value op = instr->token(); if (instr->left()->representation().IsInteger32()) { @@ -1688,11 +1691,13 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) { } else if (from.IsDouble()) { if (to.IsTagged()) { LOperand* value = UseRegister(instr->value()); - LOperand* temp = TempRegister(); + LOperand* temp1 = TempRegister(); + LOperand* temp2 = TempRegister(); - // Make sure that temp and result_temp are different registers. + // Make sure that the temp and result_temp registers are + // different. LUnallocated* result_temp = TempRegister(); - LInstruction* result = new LNumberTagD(value, temp); + LInstruction* result = new LNumberTagD(value, temp1, temp2); Define(result, result_temp); return AssignPointerMap(result); } else { diff --git a/deps/v8/src/arm/lithium-arm.h b/deps/v8/src/arm/lithium-arm.h index 0d5ba0f73f0..048d4fc80b6 100644 --- a/deps/v8/src/arm/lithium-arm.h +++ b/deps/v8/src/arm/lithium-arm.h @@ -1395,15 +1395,17 @@ class LNumberTagI: public LUnaryOperation { class LNumberTagD: public LUnaryOperation { public: - explicit LNumberTagD(LOperand* value, LOperand* temp) - : LUnaryOperation(value), temp_(temp) { } + LNumberTagD(LOperand* value, LOperand* temp1, LOperand* temp2) + : LUnaryOperation(value), temp1_(temp1), temp2_(temp2) { } DECLARE_CONCRETE_INSTRUCTION(NumberTagD, "number-tag-d") - LOperand* temp() const { return temp_; } + LOperand* temp1() const { return temp1_; } + LOperand* temp2() const { return temp2_; } private: - LOperand* temp_; + LOperand* temp1_; + LOperand* temp2_; }; @@ -1887,7 +1889,6 @@ class LChunk: public ZoneObject { LGap* GetGapAt(int index) const; bool IsGapAt(int index) const; int NearestGapPos(int index) const; - int NearestNextGapPos(int index) const; void MarkEmptyBlocks(); const ZoneList<LPointerMap*>* pointer_maps() const { return &pointer_maps_; } LLabel* GetLabel(int block_id) const { diff --git a/deps/v8/src/arm/lithium-codegen-arm.cc b/deps/v8/src/arm/lithium-codegen-arm.cc index db8037a62d7..5b3f23bb022 100644 --- a/deps/v8/src/arm/lithium-codegen-arm.cc +++ b/deps/v8/src/arm/lithium-codegen-arm.cc @@ -136,7 +136,7 @@ bool LCodeGen::GeneratePrologue() { Label loop; __ bind(&loop); __ push(r2); - __ sub(r0, r0, Operand(1)); + __ sub(r0, r0, Operand(1), SetCC); __ b(ne, &loop); } else { __ sub(sp, sp, Operand(slots * kPointerSize)); @@ -1733,13 +1733,14 @@ void LCodeGen::DoNumberTagD(LNumberTagD* instr) { DoubleRegister input_reg = ToDoubleRegister(instr->input()); Register reg = ToRegister(instr->result()); - Register tmp = ToRegister(instr->temp()); + Register temp1 = ToRegister(instr->temp1()); + Register temp2 = ToRegister(instr->temp2()); Register scratch = r9; DeferredNumberTagD* deferred = new DeferredNumberTagD(this, instr); if (FLAG_inline_new) { __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex); - __ AllocateHeapNumber(reg, tmp, ip, scratch, deferred->entry()); + __ AllocateHeapNumber(reg, temp1, temp2, scratch, deferred->entry()); } else { __ jmp(deferred->entry()); } diff --git a/deps/v8/src/arm/macro-assembler-arm.cc b/deps/v8/src/arm/macro-assembler-arm.cc index 6ad8918f176..6effec1e319 100644 --- a/deps/v8/src/arm/macro-assembler-arm.cc +++ b/deps/v8/src/arm/macro-assembler-arm.cc @@ -1060,9 +1060,14 @@ void MacroAssembler::AllocateInNewSpace(Register object_size, return; } + // Assert that the register arguments are different and that none of + // them are ip. ip is used explicitly in the code generated below. ASSERT(!result.is(scratch1)); ASSERT(!result.is(scratch2)); ASSERT(!scratch1.is(scratch2)); + ASSERT(!result.is(ip)); + ASSERT(!scratch1.is(ip)); + ASSERT(!scratch2.is(ip)); // Check relative positions of allocation top and limit addresses. // The values must be adjacent in memory to allow the use of LDM. diff --git a/deps/v8/src/array.js b/deps/v8/src/array.js index c5ff505c1dc..a805157b13b 100644 --- a/deps/v8/src/array.js +++ b/deps/v8/src/array.js @@ -159,9 +159,11 @@ function Join(array, length, separator, convert) { } -function ConvertToString(e) { - if (e == null) return ''; - else return ToString(e); +function ConvertToString(x) { + if (IS_STRING(x)) return x; + if (IS_NUMBER(x)) return %_NumberToString(x); + if (IS_BOOLEAN(x)) return x ? 'true' : 'false'; + return (IS_NULL_OR_UNDEFINED(x)) ? '' : %ToString(%DefaultString(x)); } @@ -365,14 +367,13 @@ function ArrayJoin(separator) { if (IS_UNDEFINED(separator)) { separator = ','; } else if (!IS_STRING(separator)) { - separator = ToString(separator); + separator = NonStringToString(separator); } var result = %_FastAsciiArrayJoin(this, separator); if (!IS_UNDEFINED(result)) return result; - var length = TO_UINT32(this.length); - return Join(this, length, separator, ConvertToString); + return Join(this, TO_UINT32(this.length), separator, ConvertToString); } diff --git a/deps/v8/src/assembler.cc b/deps/v8/src/assembler.cc index d71a35a4a54..3b44efa9c02 100644 --- a/deps/v8/src/assembler.cc +++ b/deps/v8/src/assembler.cc @@ -66,6 +66,7 @@ namespace internal { const double DoubleConstant::min_int = kMinInt; const double DoubleConstant::one_half = 0.5; +const double DoubleConstant::negative_infinity = -V8_INFINITY; // ----------------------------------------------------------------------------- @@ -722,6 +723,12 @@ ExternalReference ExternalReference::address_of_one_half() { } +ExternalReference ExternalReference::address_of_negative_infinity() { + return ExternalReference(reinterpret_cast<void*>( + const_cast<double*>(&DoubleConstant::negative_infinity))); +} + + #ifndef V8_INTERPRETED_REGEXP ExternalReference ExternalReference::re_check_stack_guard_state() { @@ -793,6 +800,51 @@ static double mod_two_doubles(double x, double y) { } +// Helper function to compute x^y, where y is known to be an +// integer. Uses binary decomposition to limit the number of +// multiplications; see the discussion in "Hacker's Delight" by Henry +// S. Warren, Jr., figure 11-6, page 213. +double power_double_int(double x, int y) { + double m = (y < 0) ? 1 / x : x; + unsigned n = (y < 0) ? -y : y; + double p = 1; + while (n != 0) { + if ((n & 1) != 0) p *= m; + m *= m; + if ((n & 2) != 0) p *= m; + m *= m; + n >>= 2; + } + return p; +} + + +double power_double_double(double x, double y) { + int y_int = static_cast<int>(y); + if (y == y_int) { + return power_double_int(x, y_int); // Returns 1.0 for exponent 0. + } + if (!isinf(x)) { + if (y == 0.5) return sqrt(x); + if (y == -0.5) return 1.0 / sqrt(x); + } + if (isnan(y) || ((x == 1 || x == -1) && isinf(y))) { + return OS::nan_value(); + } + return pow(x, y); +} + + +ExternalReference ExternalReference::power_double_double_function() { + return ExternalReference(Redirect(FUNCTION_ADDR(power_double_double))); +} + + +ExternalReference ExternalReference::power_double_int_function() { + return ExternalReference(Redirect(FUNCTION_ADDR(power_double_int))); +} + + static int native_compare_doubles(double y, double x) { if (x == y) return EQUAL; return x < y ? LESS : GREATER; diff --git a/deps/v8/src/assembler.h b/deps/v8/src/assembler.h index 82c9fc24c5c..72a9b15380b 100644 --- a/deps/v8/src/assembler.h +++ b/deps/v8/src/assembler.h @@ -50,6 +50,7 @@ class DoubleConstant: public AllStatic { public: static const double min_int; static const double one_half; + static const double negative_infinity; }; @@ -539,6 +540,8 @@ class ExternalReference BASE_EMBEDDED { static ExternalReference double_fp_operation(Token::Value operation); static ExternalReference compare_doubles(); + static ExternalReference power_double_double_function(); + static ExternalReference power_double_int_function(); static ExternalReference handle_scope_next_address(); static ExternalReference handle_scope_limit_address(); @@ -549,6 +552,7 @@ class ExternalReference BASE_EMBEDDED { // Static variables containing common double constants. static ExternalReference address_of_min_int(); static ExternalReference address_of_one_half(); + static ExternalReference address_of_negative_infinity(); Address address() const {return reinterpret_cast<Address>(address_);} @@ -710,6 +714,10 @@ static inline int NumberOfBitsSet(uint32_t x) { return num_bits_set; } +// Computes pow(x, y) with the special cases in the spec for Math.pow. +double power_double_int(double x, int y); +double power_double_double(double x, double y); + } } // namespace v8::internal #endif // V8_ASSEMBLER_H_ diff --git a/deps/v8/src/ast-inl.h b/deps/v8/src/ast-inl.h index e88156d6e41..d1017121da2 100644 --- a/deps/v8/src/ast-inl.h +++ b/deps/v8/src/ast-inl.h @@ -94,7 +94,8 @@ ForStatement::ForStatement(ZoneStringList* labels) ForInStatement::ForInStatement(ZoneStringList* labels) - : IterationStatement(labels), each_(NULL), enumerable_(NULL) { + : IterationStatement(labels), each_(NULL), enumerable_(NULL), + assignment_id_(GetNextId()) { } diff --git a/deps/v8/src/ast.cc b/deps/v8/src/ast.cc index c1ea0a8b3df..7ddb01e3e4d 100644 --- a/deps/v8/src/ast.cc +++ b/deps/v8/src/ast.cc @@ -125,17 +125,18 @@ Assignment::Assignment(Token::Value op, target_(target), value_(value), pos_(pos), - compound_bailout_id_(kNoNumber), + binary_operation_(NULL), + compound_load_id_(kNoNumber), + assignment_id_(GetNextId()), block_start_(false), block_end_(false), is_monomorphic_(false), receiver_types_(NULL) { ASSERT(Token::IsAssignmentOp(op)); - binary_operation_ = is_compound() - ? new BinaryOperation(binary_op(), target, value, pos + 1) - : NULL; if (is_compound()) { - compound_bailout_id_ = GetNextId(); + binary_operation_ = + new BinaryOperation(binary_op(), target, value, pos + 1); + compound_load_id_ = GetNextId(); } } diff --git a/deps/v8/src/ast.h b/deps/v8/src/ast.h index cdf456f67b6..c33838e0118 100644 --- a/deps/v8/src/ast.h +++ b/deps/v8/src/ast.h @@ -435,7 +435,6 @@ class IterationStatement: public BreakableStatement { virtual IterationStatement* AsIterationStatement() { return this; } Statement* body() const { return body_; } - void set_body(Statement* stmt) { body_ = stmt; } // Bailout support. int OsrEntryId() const { return osr_entry_id_; } @@ -532,11 +531,8 @@ class ForStatement: public IterationStatement { } Statement* init() const { return init_; } - void set_init(Statement* stmt) { init_ = stmt; } Expression* cond() const { return cond_; } - void set_cond(Expression* expr) { cond_ = expr; } Statement* next() const { return next_; } - void set_next(Statement* stmt) { next_ = stmt; } bool may_have_function_literal() const { return may_have_function_literal_; @@ -579,11 +575,13 @@ class ForInStatement: public IterationStatement { Expression* enumerable() const { return enumerable_; } // Bailout support. + int AssignmentId() const { return assignment_id_; } virtual int ContinueId() const { return EntryId(); } private: Expression* each_; Expression* enumerable_; + int assignment_id_; }; @@ -748,9 +746,7 @@ class IfStatement: public Statement { Expression* condition() const { return condition_; } Statement* then_statement() const { return then_statement_; } - void set_then_statement(Statement* stmt) { then_statement_ = stmt; } Statement* else_statement() const { return else_statement_; } - void set_else_statement(Statement* stmt) { else_statement_ = stmt; } private: Expression* condition_; @@ -1432,7 +1428,9 @@ class IncrementOperation: public Expression { class CountOperation: public Expression { public: CountOperation(bool is_prefix, IncrementOperation* increment, int pos) - : is_prefix_(is_prefix), increment_(increment), pos_(pos) { } + : is_prefix_(is_prefix), increment_(increment), pos_(pos), + assignment_id_(GetNextId()) { + } DECLARE_NODE_TYPE(CountOperation) @@ -1452,10 +1450,14 @@ class CountOperation: public Expression { virtual bool IsInlineable() const; + // Bailout support. + int AssignmentId() const { return assignment_id_; } + private: bool is_prefix_; IncrementOperation* increment_; int pos_; + int assignment_id_; }; @@ -1585,7 +1587,8 @@ class Assignment: public Expression { } // Bailout support. - int compound_bailout_id() const { return compound_bailout_id_; } + int CompoundLoadId() const { return compound_load_id_; } + int AssignmentId() const { return assignment_id_; } private: Token::Value op_; @@ -1593,7 +1596,8 @@ class Assignment: public Expression { Expression* value_; int pos_; BinaryOperation* binary_operation_; - int compound_bailout_id_; + int compound_load_id_; + int assignment_id_; bool block_start_; bool block_end_; diff --git a/deps/v8/src/checks.h b/deps/v8/src/checks.h index aa557f00bcf..8d13d65f6ed 100644 --- a/deps/v8/src/checks.h +++ b/deps/v8/src/checks.h @@ -231,6 +231,8 @@ static inline void CheckNonEqualsHelper(const char* file, #define CHECK_GT(a, b) CHECK((a) > (b)) #define CHECK_GE(a, b) CHECK((a) >= (b)) +#define CHECK_LT(a, b) CHECK((a) < (b)) +#define CHECK_LE(a, b) CHECK((a) <= (b)) // This is inspired by the static assertion facility in boost. This diff --git a/deps/v8/src/compiler.cc b/deps/v8/src/compiler.cc index 59a684c69f6..e4864e48015 100755 --- a/deps/v8/src/compiler.cc +++ b/deps/v8/src/compiler.cc @@ -116,13 +116,26 @@ static bool AlwaysFullCompiler() { static void FinishOptimization(Handle<JSFunction> function, int64_t start) { int opt_count = function->shared()->opt_count(); function->shared()->set_opt_count(opt_count + 1); - if (!FLAG_trace_opt) return; - double ms = static_cast<double>(OS::Ticks() - start) / 1000; - PrintF("[optimizing: "); - function->PrintName(); - PrintF(" / %" V8PRIxPTR, reinterpret_cast<intptr_t>(*function)); - PrintF(" - took %0.3f ms]\n", ms); + if (FLAG_trace_opt) { + PrintF("[optimizing: "); + function->PrintName(); + PrintF(" / %" V8PRIxPTR, reinterpret_cast<intptr_t>(*function)); + PrintF(" - took %0.3f ms]\n", ms); + } + if (FLAG_trace_opt_stats) { + static double compilation_time = 0.0; + static int compiled_functions = 0; + static int code_size = 0; + + compilation_time += ms; + compiled_functions++; + code_size += function->shared()->SourceSize(); + PrintF("Compiled: %d functions with %d byte source size in %fms.\n", + compiled_functions, + code_size, + compilation_time); + } } @@ -461,7 +474,14 @@ Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source, ScriptDataImpl* pre_data = input_pre_data; if (pre_data == NULL && source_length >= FLAG_min_preparse_length) { - pre_data = ParserApi::PartialPreParse(source, NULL, extension); + if (source->IsExternalTwoByteString()) { + ExternalTwoByteStringUC16CharacterStream stream( + Handle<ExternalTwoByteString>::cast(source), 0, source->length()); + pre_data = ParserApi::PartialPreParse(&stream, extension); + } else { + GenericStringUC16CharacterStream stream(source, 0, source->length()); + pre_data = ParserApi::PartialPreParse(&stream, extension); + } } // Create a script object describing the script to be compiled. diff --git a/deps/v8/src/extensions/experimental/i18n-extension.cc b/deps/v8/src/extensions/experimental/i18n-extension.cc new file mode 100644 index 00000000000..22a1c912d0f --- /dev/null +++ b/deps/v8/src/extensions/experimental/i18n-extension.cc @@ -0,0 +1,263 @@ +// 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: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "i18n-extension.h" + +#include <algorithm> +#include <string> + +#include "unicode/locid.h" +#include "unicode/uloc.h" + +namespace v8 { +namespace internal { + +I18NExtension* I18NExtension::extension_ = NULL; + +// TODO(cira): maybe move JS code to a .js file and generata cc files from it? +const char* const I18NExtension::kSource = + "Locale = function(optLocale) {" + " native function NativeJSLocale();" + " var properties = NativeJSLocale(optLocale);" + " this.locale = properties.locale;" + " this.language = properties.language;" + " this.script = properties.script;" + " this.region = properties.region;" + "};" + "Locale.availableLocales = function() {" + " native function NativeJSAvailableLocales();" + " return NativeJSAvailableLocales();" + "};" + "Locale.prototype.maximizedLocale = function() {" + " native function NativeJSMaximizedLocale();" + " return new Locale(NativeJSMaximizedLocale(this.locale));" + "};" + "Locale.prototype.minimizedLocale = function() {" + " native function NativeJSMinimizedLocale();" + " return new Locale(NativeJSMinimizedLocale(this.locale));" + "};" + "Locale.prototype.displayLocale_ = function(displayLocale) {" + " var result = this.locale;" + " if (displayLocale !== undefined) {" + " result = displayLocale.locale;" + " }" + " return result;" + "};" + "Locale.prototype.displayLanguage = function(optDisplayLocale) {" + " var displayLocale = this.displayLocale_(optDisplayLocale);" + " native function NativeJSDisplayLanguage();" + " return NativeJSDisplayLanguage(this.locale, displayLocale);" + "};" + "Locale.prototype.displayScript = function(optDisplayLocale) {" + " var displayLocale = this.displayLocale_(optDisplayLocale);" + " native function NativeJSDisplayScript();" + " return NativeJSDisplayScript(this.locale, displayLocale);" + "};" + "Locale.prototype.displayRegion = function(optDisplayLocale) {" + " var displayLocale = this.displayLocale_(optDisplayLocale);" + " native function NativeJSDisplayRegion();" + " return NativeJSDisplayRegion(this.locale, displayLocale);" + "};" + "Locale.prototype.displayName = function(optDisplayLocale) {" + " var displayLocale = this.displayLocale_(optDisplayLocale);" + " native function NativeJSDisplayName();" + " return NativeJSDisplayName(this.locale, displayLocale);" + "};"; + +v8::Handle<v8::FunctionTemplate> I18NExtension::GetNativeFunction( + v8::Handle<v8::String> name) { + if (name->Equals(v8::String::New("NativeJSLocale"))) { + return v8::FunctionTemplate::New(JSLocale); + } else if (name->Equals(v8::String::New("NativeJSAvailableLocales"))) { + return v8::FunctionTemplate::New(JSAvailableLocales); + } else if (name->Equals(v8::String::New("NativeJSMaximizedLocale"))) { + return v8::FunctionTemplate::New(JSMaximizedLocale); + } else if (name->Equals(v8::String::New("NativeJSMinimizedLocale"))) { + return v8::FunctionTemplate::New(JSMinimizedLocale); + } else if (name->Equals(v8::String::New("NativeJSDisplayLanguage"))) { + return v8::FunctionTemplate::New(JSDisplayLanguage); + } else if (name->Equals(v8::String::New("NativeJSDisplayScript"))) { + return v8::FunctionTemplate::New(JSDisplayScript); + } else if (name->Equals(v8::String::New("NativeJSDisplayRegion"))) { + return v8::FunctionTemplate::New(JSDisplayRegion); + } else if (name->Equals(v8::String::New("NativeJSDisplayName"))) { + return v8::FunctionTemplate::New(JSDisplayName); + } + + return v8::Handle<v8::FunctionTemplate>(); +} + +v8::Handle<v8::Value> I18NExtension::JSLocale(const v8::Arguments& args) { + // TODO(cira): Fetch browser locale. Accept en-US as good default for now. + // We could possibly pass browser locale as a parameter in the constructor. + std::string locale_name("en-US"); + if (args.Length() == 1 && args[0]->IsString()) { + locale_name = *v8::String::Utf8Value(args[0]->ToString()); + } + + v8::Local<v8::Object> locale = v8::Object::New(); + locale->Set(v8::String::New("locale"), v8::String::New(locale_name.c_str())); + + icu::Locale icu_locale(locale_name.c_str()); + + const char* language = icu_locale.getLanguage(); + locale->Set(v8::String::New("language"), v8::String::New(language)); + + const char* script = icu_locale.getScript(); + if (strlen(script)) { + locale->Set(v8::String::New("script"), v8::String::New(script)); + } + + const char* region = icu_locale.getCountry(); + if (strlen(region)) { + locale->Set(v8::String::New("region"), v8::String::New(region)); + } + + return locale; +} + +// TODO(cira): Filter out locales that Chrome doesn't support. +v8::Handle<v8::Value> I18NExtension::JSAvailableLocales( + const v8::Arguments& args) { + v8::Local<v8::Array> all_locales = v8::Array::New(); + + int count = 0; + const Locale* icu_locales = icu::Locale::getAvailableLocales(count); + for (int i = 0; i < count; ++i) { + all_locales->Set(i, v8::String::New(icu_locales[i].getName())); + } + + return all_locales; +} + +// Use - as tag separator, not _ that ICU uses. +static std::string NormalizeLocale(const std::string& locale) { + std::string result(locale); + // TODO(cira): remove STL dependency. + std::replace(result.begin(), result.end(), '_', '-'); + return result; +} + +v8::Handle<v8::Value> I18NExtension::JSMaximizedLocale( + const v8::Arguments& args) { + if (!args.Length() || !args[0]->IsString()) { + return v8::Undefined(); + } + + UErrorCode status = U_ZERO_ERROR; + std::string locale_name = *v8::String::Utf8Value(args[0]->ToString()); + char max_locale[ULOC_FULLNAME_CAPACITY]; + uloc_addLikelySubtags(locale_name.c_str(), max_locale, + sizeof(max_locale), &status); + if (U_FAILURE(status)) { + return v8::Undefined(); + } + + return v8::String::New(NormalizeLocale(max_locale).c_str()); +} + +v8::Handle<v8::Value> I18NExtension::JSMinimizedLocale( + const v8::Arguments& args) { + if (!args.Length() || !args[0]->IsString()) { + return v8::Undefined(); + } + + UErrorCode status = U_ZERO_ERROR; + std::string locale_name = *v8::String::Utf8Value(args[0]->ToString()); + char min_locale[ULOC_FULLNAME_CAPACITY]; + uloc_minimizeSubtags(locale_name.c_str(), min_locale, + sizeof(min_locale), &status); + if (U_FAILURE(status)) { + return v8::Undefined(); + } + + return v8::String::New(NormalizeLocale(min_locale).c_str()); +} + +// Common code for JSDisplayXXX methods. +static v8::Handle<v8::Value> GetDisplayItem(const v8::Arguments& args, + const std::string& item) { + if (args.Length() != 2 || !args[0]->IsString() || !args[1]->IsString()) { + return v8::Undefined(); + } + + std::string base_locale = *v8::String::Utf8Value(args[0]->ToString()); + icu::Locale icu_locale(base_locale.c_str()); + icu::Locale display_locale = + icu::Locale(*v8::String::Utf8Value(args[1]->ToString())); + UnicodeString result; + if (item == "language") { + icu_locale.getDisplayLanguage(display_locale, result); + } else if (item == "script") { + icu_locale.getDisplayScript(display_locale, result); + } else if (item == "region") { + icu_locale.getDisplayCountry(display_locale, result); + } else if (item == "name") { + icu_locale.getDisplayName(display_locale, result); + } else { + return v8::Undefined(); + } + + if (result.length()) { + return v8::String::New( + reinterpret_cast<const uint16_t*>(result.getBuffer()), result.length()); + } + + return v8::Undefined(); +} + +v8::Handle<v8::Value> I18NExtension::JSDisplayLanguage( + const v8::Arguments& args) { + return GetDisplayItem(args, "language"); +} + +v8::Handle<v8::Value> I18NExtension::JSDisplayScript( + const v8::Arguments& args) { + return GetDisplayItem(args, "script"); +} + +v8::Handle<v8::Value> I18NExtension::JSDisplayRegion( + const v8::Arguments& args) { + return GetDisplayItem(args, "region"); +} + +v8::Handle<v8::Value> I18NExtension::JSDisplayName(const v8::Arguments& args) { + return GetDisplayItem(args, "name"); +} + +I18NExtension* I18NExtension::get() { + if (!extension_) { + extension_ = new I18NExtension(); + } + return extension_; +} + +void I18NExtension::Register() { + static v8::DeclareExtension i18n_extension_declaration(I18NExtension::get()); +} + +} } // namespace v8::internal diff --git a/deps/v8/src/extensions/experimental/i18n-extension.h b/deps/v8/src/extensions/experimental/i18n-extension.h new file mode 100644 index 00000000000..629332babbc --- /dev/null +++ b/deps/v8/src/extensions/experimental/i18n-extension.h @@ -0,0 +1,64 @@ +// 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: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (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_EXTENSIONS_EXPERIMENTAL_I18N_EXTENSION_H_ +#define V8_EXTENSIONS_EXPERIMENTAL_I18N_EXTENSION_H_ + +#include <v8.h> + +namespace v8 { +namespace internal { + + +class I18NExtension : public v8::Extension { + public: + I18NExtension() : v8::Extension("v8/i18n", kSource) {} + virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( + v8::Handle<v8::String> name); + + // Implementations of window.Locale methods. + static v8::Handle<v8::Value> JSLocale(const v8::Arguments& args); + static v8::Handle<v8::Value> JSAvailableLocales(const v8::Arguments& args); + static v8::Handle<v8::Value> JSMaximizedLocale(const v8::Arguments& args); + static v8::Handle<v8::Value> JSMinimizedLocale(const v8::Arguments& args); + static v8::Handle<v8::Value> JSDisplayLanguage(const v8::Arguments& args); + static v8::Handle<v8::Value> JSDisplayScript(const v8::Arguments& args); + static v8::Handle<v8::Value> JSDisplayRegion(const v8::Arguments& args); + static v8::Handle<v8::Value> JSDisplayName(const v8::Arguments& args); + + // V8 code prefers Register, while Chrome and WebKit use get kind of methods. + static void Register(); + static I18NExtension* get(); + + private: + static const char* const kSource; + static I18NExtension* extension_; +}; + +} } // namespace v8::internal + +#endif // V8_EXTENSIONS_EXPERIMENTAL_I18N_EXTENSION_H_ diff --git a/deps/v8/src/flag-definitions.h b/deps/v8/src/flag-definitions.h index 37653a4a158..fc5fe1ee0fc 100644 --- a/deps/v8/src/flag-definitions.h +++ b/deps/v8/src/flag-definitions.h @@ -194,6 +194,7 @@ DEFINE_bool(mask_constants_with_cookie, // codegen.cc DEFINE_bool(lazy, true, "use lazy compilation") DEFINE_bool(trace_opt, false, "trace lazy optimization") +DEFINE_bool(trace_opt_stats, false, "trace lazy optimization statistics") DEFINE_bool(opt, true, "use adaptive optimizations") DEFINE_bool(opt_eagerly, false, "be more eager when adaptively optimizing") DEFINE_bool(always_opt, false, "always try to optimize functions") @@ -456,8 +457,6 @@ DEFINE_bool(log_snapshot_positions, false, "log positions of (de)serialized objects in the snapshot.") DEFINE_bool(log_suspect, false, "Log suspect operations.") DEFINE_bool(log_producers, false, "Log stack traces of JS objects allocations.") -DEFINE_bool(compress_log, false, - "Compress log to save space (makes log less human-readable).") DEFINE_bool(prof, false, "Log statistical profiling information (implies --log-code).") DEFINE_bool(prof_auto, true, diff --git a/deps/v8/src/full-codegen.h b/deps/v8/src/full-codegen.h index 8d9fe2d3322..e0fd192a219 100644 --- a/deps/v8/src/full-codegen.h +++ b/deps/v8/src/full-codegen.h @@ -481,7 +481,7 @@ class FullCodeGenerator: public AstVisitor { // Assign to the given expression as if via '='. The right-hand-side value // is expected in the accumulator. - void EmitAssignment(Expression* expr); + void EmitAssignment(Expression* expr, int bailout_ast_id); // Complete a variable assignment. The right-hand-side value is expected // in the accumulator. diff --git a/deps/v8/src/heap-profiler.cc b/deps/v8/src/heap-profiler.cc index 91ac9867a28..6700d38b250 100644 --- a/deps/v8/src/heap-profiler.cc +++ b/deps/v8/src/heap-profiler.cc @@ -348,27 +348,34 @@ void HeapProfiler::TearDown() { #ifdef ENABLE_LOGGING_AND_PROFILING -HeapSnapshot* HeapProfiler::TakeSnapshot(const char* name, int type) { +HeapSnapshot* HeapProfiler::TakeSnapshot(const char* name, + int type, + v8::ActivityControl* control) { ASSERT(singleton_ != NULL); - return singleton_->TakeSnapshotImpl(name, type); + return singleton_->TakeSnapshotImpl(name, type, control); } -HeapSnapshot* HeapProfiler::TakeSnapshot(String* name, int type) { +HeapSnapshot* HeapProfiler::TakeSnapshot(String* name, + int type, + v8::ActivityControl* control) { ASSERT(singleton_ != NULL); - return singleton_->TakeSnapshotImpl(name, type); + return singleton_->TakeSnapshotImpl(name, type, control); } -HeapSnapshot* HeapProfiler::TakeSnapshotImpl(const char* name, int type) { +HeapSnapshot* HeapProfiler::TakeSnapshotImpl(const char* name, + int type, + v8::ActivityControl* control) { Heap::CollectAllGarbage(true); HeapSnapshot::Type s_type = static_cast<HeapSnapshot::Type>(type); HeapSnapshot* result = snapshots_->NewSnapshot(s_type, name, next_snapshot_uid_++); + bool generation_completed = true; switch (s_type) { case HeapSnapshot::kFull: { - HeapSnapshotGenerator generator(result); - generator.GenerateSnapshot(); + HeapSnapshotGenerator generator(result, control); + generation_completed = generator.GenerateSnapshot(); break; } case HeapSnapshot::kAggregated: { @@ -381,13 +388,19 @@ HeapSnapshot* HeapProfiler::TakeSnapshotImpl(const char* name, int type) { default: UNREACHABLE(); } - snapshots_->SnapshotGenerationFinished(); + if (!generation_completed) { + delete result; + result = NULL; + } + snapshots_->SnapshotGenerationFinished(result); return result; } -HeapSnapshot* HeapProfiler::TakeSnapshotImpl(String* name, int type) { - return TakeSnapshotImpl(snapshots_->GetName(name), type); +HeapSnapshot* HeapProfiler::TakeSnapshotImpl(String* name, + int type, + v8::ActivityControl* control) { + return TakeSnapshotImpl(snapshots_->GetName(name), type, control); } diff --git a/deps/v8/src/heap-profiler.h b/deps/v8/src/heap-profiler.h index 2ef081ee299..31d0aff02f8 100644 --- a/deps/v8/src/heap-profiler.h +++ b/deps/v8/src/heap-profiler.h @@ -56,8 +56,12 @@ class HeapProfiler { static void TearDown(); #ifdef ENABLE_LOGGING_AND_PROFILING - static HeapSnapshot* TakeSnapshot(const char* name, int type); - static HeapSnapshot* TakeSnapshot(String* name, int type); + static HeapSnapshot* TakeSnapshot(const char* name, + int type, + v8::ActivityControl* control); + static HeapSnapshot* TakeSnapshot(String* name, + int type, + v8::ActivityControl* control); static int GetSnapshotsCount(); static HeapSnapshot* GetSnapshot(int index); static HeapSnapshot* FindSnapshot(unsigned uid); @@ -75,8 +79,12 @@ class HeapProfiler { private: HeapProfiler(); ~HeapProfiler(); - HeapSnapshot* TakeSnapshotImpl(const char* name, int type); - HeapSnapshot* TakeSnapshotImpl(String* name, int type); + HeapSnapshot* TakeSnapshotImpl(const char* name, + int type, + v8::ActivityControl* control); + HeapSnapshot* TakeSnapshotImpl(String* name, + int type, + v8::ActivityControl* control); HeapSnapshotsCollection* snapshots_; unsigned next_snapshot_uid_; diff --git a/deps/v8/src/heap.cc b/deps/v8/src/heap.cc index 0497ad5f6a3..ccf9b47a35c 100644 --- a/deps/v8/src/heap.cc +++ b/deps/v8/src/heap.cc @@ -3757,14 +3757,21 @@ bool Heap::IdleNotification() { static const int kIdlesBeforeScavenge = 4; static const int kIdlesBeforeMarkSweep = 7; static const int kIdlesBeforeMarkCompact = 8; + static const int kMaxIdleCount = kIdlesBeforeMarkCompact + 1; + static const int kGCsBetweenCleanup = 4; static int number_idle_notifications = 0; static int last_gc_count = gc_count_; bool uncommit = true; bool finished = false; - if (last_gc_count == gc_count_) { - number_idle_notifications++; + // Reset the number of idle notifications received when a number of + // GCs have taken place. This allows another round of cleanup based + // on idle notifications if enough work has been carried out to + // provoke a number of garbage collections. + if (gc_count_ < last_gc_count + kGCsBetweenCleanup) { + number_idle_notifications = + Min(number_idle_notifications + 1, kMaxIdleCount); } else { number_idle_notifications = 0; last_gc_count = gc_count_; @@ -3779,7 +3786,6 @@ bool Heap::IdleNotification() { } new_space_.Shrink(); last_gc_count = gc_count_; - } else if (number_idle_notifications == kIdlesBeforeMarkSweep) { // Before doing the mark-sweep collections we clear the // compilation cache to avoid hanging on to source code and @@ -3794,7 +3800,6 @@ bool Heap::IdleNotification() { CollectAllGarbage(true); new_space_.Shrink(); last_gc_count = gc_count_; - number_idle_notifications = 0; finished = true; } else if (contexts_disposed_ > 0) { @@ -3813,6 +3818,11 @@ bool Heap::IdleNotification() { number_idle_notifications = 0; uncommit = false; } + } else if (number_idle_notifications > kIdlesBeforeMarkCompact) { + // If we have received more than kIdlesBeforeMarkCompact idle + // notifications we do not perform any cleanup because we don't + // expect to gain much by doing so. + finished = true; } // Make sure that we have no pending context disposals and diff --git a/deps/v8/src/heap.h b/deps/v8/src/heap.h index e4dcb4ad7d3..06b3ee46890 100644 --- a/deps/v8/src/heap.h +++ b/deps/v8/src/heap.h @@ -1119,9 +1119,9 @@ class Heap : public AllStatic { static int contexts_disposed_; #if defined(V8_TARGET_ARCH_X64) - static const int kMaxObjectSizeInNewSpace = 512*KB; + static const int kMaxObjectSizeInNewSpace = 1024*KB; #else - static const int kMaxObjectSizeInNewSpace = 256*KB; + static const int kMaxObjectSizeInNewSpace = 512*KB; #endif static NewSpace new_space_; diff --git a/deps/v8/src/hydrogen-instructions.h b/deps/v8/src/hydrogen-instructions.h index ff1ab1a36e5..34316319aa3 100644 --- a/deps/v8/src/hydrogen-instructions.h +++ b/deps/v8/src/hydrogen-instructions.h @@ -77,6 +77,7 @@ class LChunkBuilder; // HLoadKeyedFastElement // HLoadKeyedGeneric // HLoadNamedGeneric +// HPower // HStoreNamed // HStoreNamedField // HStoreNamedGeneric @@ -223,6 +224,7 @@ class LChunkBuilder; V(ObjectLiteral) \ V(OsrEntry) \ V(Parameter) \ + V(Power) \ V(PushArgument) \ V(RegExpLiteral) \ V(Return) \ @@ -1377,6 +1379,7 @@ class HUnaryMathOperation: public HUnaryOperation { SetFlag(kFlexibleRepresentation); break; case kMathSqrt: + case kMathPowHalf: default: set_representation(Representation::Double()); } @@ -1395,6 +1398,7 @@ class HUnaryMathOperation: public HUnaryOperation { case kMathRound: case kMathCeil: case kMathSqrt: + case kMathPowHalf: return Representation::Double(); break; case kMathAbs: @@ -2184,6 +2188,22 @@ class HInstanceOf: public HBinaryOperation { }; +class HPower: public HBinaryOperation { + public: + HPower(HValue* left, HValue* right) + : HBinaryOperation(left, right) { + set_representation(Representation::Double()); + SetFlag(kUseGVN); + } + + virtual Representation RequiredInputRepresentation(int index) const { + return (index == 1) ? Representation::None() : Representation::Double(); + } + + DECLARE_CONCRETE_INSTRUCTION(Power, "power") +}; + + class HAdd: public HArithmeticBinaryOperation { public: HAdd(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) { diff --git a/deps/v8/src/hydrogen.cc b/deps/v8/src/hydrogen.cc index 0e8c4760dd3..bc49f06a20b 100644 --- a/deps/v8/src/hydrogen.cc +++ b/deps/v8/src/hydrogen.cc @@ -1983,6 +1983,9 @@ void HGraph::InsertRepresentationChanges() { AstContext::AstContext(HGraphBuilder* owner, Expression::Context kind) : owner_(owner), kind_(kind), outer_(owner->ast_context()) { owner->set_ast_context(this); // Push. +#ifdef DEBUG + original_count_ = owner->environment()->total_count(); +#endif } @@ -1991,6 +1994,101 @@ AstContext::~AstContext() { } +EffectContext::~EffectContext() { + ASSERT(owner()->HasStackOverflow() || + !owner()->subgraph()->HasExit() || + owner()->environment()->total_count() == original_count_); +} + + +ValueContext::~ValueContext() { + ASSERT(owner()->HasStackOverflow() || + !owner()->subgraph()->HasExit() || + owner()->environment()->total_count() == original_count_ + 1); +} + + +void EffectContext::ReturnValue(HValue* value) { + // The value is simply ignored. +} + + +void ValueContext::ReturnValue(HValue* value) { + // The value is tracked in the bailout environment, and communicated + // through the environment as the result of the expression. + owner()->Push(value); +} + + +void TestContext::ReturnValue(HValue* value) { + BuildBranch(value); +} + + +void EffectContext::ReturnInstruction(HInstruction* instr, int ast_id) { + owner()->AddInstruction(instr); + if (instr->HasSideEffects()) owner()->AddSimulate(ast_id); +} + + +void ValueContext::ReturnInstruction(HInstruction* instr, int ast_id) { + owner()->AddInstruction(instr); + owner()->Push(instr); + if (instr->HasSideEffects()) owner()->AddSimulate(ast_id); +} + + +void TestContext::ReturnInstruction(HInstruction* instr, int ast_id) { + HGraphBuilder* builder = owner(); + builder->AddInstruction(instr); + // We expect a simulate after every expression with side effects, though + // this one isn't actually needed (and wouldn't work if it were targeted). + if (instr->HasSideEffects()) { + builder->Push(instr); + builder->AddSimulate(ast_id); + builder->Pop(); + } + BuildBranch(instr); +} + + +void TestContext::BuildBranch(HValue* value) { + HGraphBuilder* builder = owner(); + HBasicBlock* materialize_true = builder->graph()->CreateBasicBlock(); + HBasicBlock* materialize_false = builder->graph()->CreateBasicBlock(); + HBranch* branch = new HBranch(materialize_true, materialize_false, value); + builder->CurrentBlock()->Finish(branch); + + HBasicBlock* true_block = if_true(); + HValue* true_value = invert_true() + ? builder->graph()->GetConstantFalse() + : builder->graph()->GetConstantTrue(); + materialize_true->set_inverted(invert_true()); + true_block->set_deopt_predecessor(materialize_true); + + if (true_block->IsInlineReturnTarget()) { + materialize_true->AddLeaveInlined(true_value, true_block); + } else { + materialize_true->last_environment()->Push(true_value); + materialize_true->Goto(true_block); + } + + HBasicBlock* false_block = if_false(); + HValue* false_value = invert_false() + ? builder->graph()->GetConstantTrue() + : builder->graph()->GetConstantFalse(); + materialize_false->set_inverted(invert_false()); + false_block->set_deopt_predecessor(materialize_false); + + if (false_block->IsInlineReturnTarget()) { + materialize_false->AddLeaveInlined(false_value, false_block); + } else { + materialize_false->last_environment()->Push(false_value); + materialize_false->Goto(false_block); + } + builder->subgraph()->set_exit_block(NULL); +} + // HGraphBuilder infrastructure for bailing out and checking bailouts. #define BAILOUT(reason) \ @@ -2061,55 +2159,14 @@ void HGraphBuilder::Bailout(const char* reason) { void HGraphBuilder::VisitForEffect(Expression* expr) { -#ifdef DEBUG - int original_count = environment()->total_count(); -#endif - BinaryOperation* binary_op = expr->AsBinaryOperation(); - - // We use special casing for expression types not handled properly by our - // usual trick of pretending they're in a value context and cleaning up - // later. - if (binary_op != NULL && binary_op->op() == Token::COMMA) { - VISIT_FOR_EFFECT(binary_op->left()); - VISIT_FOR_EFFECT(binary_op->right()); - } else { - { EffectContext for_effect(this); - Visit(expr); - } - if (HasStackOverflow() || !subgraph()->HasExit()) return; - // Discard return value. - Pop(); - // TODO(kasperl): Try to improve the way we compute the last added - // instruction. The NULL check makes me uncomfortable. - HValue* last = subgraph()->exit_block()->GetLastInstruction(); - // We need to ensure we emit a simulate after inlined functions in an - // effect context, to avoid having a bailout target the fictional - // environment with the return value on top. - if ((last != NULL && last->HasSideEffects()) || - subgraph()->exit_block()->IsInlineReturnTarget()) { - AddSimulate(expr->id()); - } - } - - ASSERT(environment()->total_count() == original_count); + EffectContext for_effect(this); + Visit(expr); } void HGraphBuilder::VisitForValue(Expression* expr) { -#ifdef DEBUG - int original_height = environment()->values()->length(); -#endif - { ValueContext for_value(this); - Visit(expr); - } - if (HasStackOverflow() || !subgraph()->HasExit()) return; - // TODO(kasperl): Try to improve the way we compute the last added - // instruction. The NULL check makes me uncomfortable. - HValue* last = subgraph()->exit_block()->GetLastInstruction(); - if (last != NULL && last->HasSideEffects()) { - AddSimulate(expr->id()); - } - ASSERT(environment()->values()->length() == original_height + 1); + ValueContext for_value(this); + Visit(expr); } @@ -2244,99 +2301,7 @@ void HGraphBuilder::VisitForControl(Expression* expr, bool invert_false) { TestContext for_test(this, true_block, false_block, invert_true, invert_false); - BinaryOperation* binary_op = expr->AsBinaryOperation(); - UnaryOperation* unary_op = expr->AsUnaryOperation(); - - if (unary_op != NULL && unary_op->op() == Token::NOT) { - VisitForControl(unary_op->expression(), - false_block, - true_block, - !invert_false, - !invert_true); - } else if (binary_op != NULL && binary_op->op() == Token::AND) { - // Translate left subexpression. - HBasicBlock* eval_right = graph()->CreateBasicBlock(); - VisitForControl(binary_op->left(), - eval_right, - false_block, - false, - invert_false); - if (HasStackOverflow()) return; - eval_right->SetJoinId(binary_op->left()->id()); - - // Translate right subexpression. - eval_right->last_environment()->Pop(); - subgraph()->set_exit_block(eval_right); - VisitForControl(binary_op->right(), - true_block, - false_block, - invert_true, - invert_false); - } else if (binary_op != NULL && binary_op->op() == Token::OR) { - // Translate left subexpression. - HBasicBlock* eval_right = graph()->CreateBasicBlock(); - VisitForControl(binary_op->left(), - true_block, - eval_right, - invert_true, - false); - if (HasStackOverflow()) return; - eval_right->SetJoinId(binary_op->left()->id()); - - // Translate right subexpression - eval_right->last_environment()->Pop(); - subgraph()->set_exit_block(eval_right); - VisitForControl(binary_op->right(), - true_block, - false_block, - invert_true, - invert_false); - } else { -#ifdef DEBUG - int original_length = environment()->values()->length(); -#endif - // TODO(kmillikin): Refactor to avoid. This code is duplicated from - // VisitForValue, except without pushing a value context on the - // expression context stack. - Visit(expr); - if (HasStackOverflow() || !subgraph()->HasExit()) return; - HValue* last = subgraph()->exit_block()->GetLastInstruction(); - if (last != NULL && last->HasSideEffects()) { - AddSimulate(expr->id()); - } - ASSERT(environment()->values()->length() == original_length + 1); - HValue* value = Pop(); - HBasicBlock* materialize_true = graph()->CreateBasicBlock(); - HBasicBlock* materialize_false = graph()->CreateBasicBlock(); - CurrentBlock()->Finish(new HBranch(materialize_true, - materialize_false, - value)); - HValue* true_value = invert_true - ? graph()->GetConstantFalse() - : graph()->GetConstantTrue(); - materialize_true->set_inverted(invert_true); - true_block->set_deopt_predecessor(materialize_true); - - if (true_block->IsInlineReturnTarget()) { - materialize_true->AddLeaveInlined(true_value, true_block); - } else { - materialize_true->last_environment()->Push(true_value); - materialize_true->Goto(true_block); - } - HValue* false_value = invert_false - ? graph()->GetConstantTrue() - : graph()->GetConstantFalse(); - materialize_false->set_inverted(invert_false); - false_block->set_deopt_predecessor(materialize_false); - - if (false_block->IsInlineReturnTarget()) { - materialize_false->AddLeaveInlined(false_value, false_block); - } else { - materialize_false->last_environment()->Push(false_value); - materialize_false->Goto(false_block); - } - subgraph()->set_exit_block(NULL); - } + Visit(expr); } @@ -2372,12 +2337,6 @@ void HGraphBuilder::PushAndAdd(HInstruction* instr) { } -void HGraphBuilder::PushAndAdd(HInstruction* instr, int position) { - instr->set_position(position); - PushAndAdd(instr); -} - - void HGraphBuilder::PushArgumentsForStubCall(int argument_count) { const int kMaxStubArguments = 4; ASSERT_GE(kMaxStubArguments, argument_count); @@ -2392,7 +2351,7 @@ void HGraphBuilder::PushArgumentsForStubCall(int argument_count) { } -void HGraphBuilder::ProcessCall(HCall* call, int source_position) { +void HGraphBuilder::ProcessCall(HCall* call) { for (int i = call->argument_count() - 1; i >= 0; --i) { HValue* value = Pop(); HPushArgument* push = new HPushArgument(value); @@ -2402,8 +2361,6 @@ void HGraphBuilder::ProcessCall(HCall* call, int source_position) { for (int i = 0; i < call->argument_count(); ++i) { AddInstruction(call->PushArgumentAt(i)); } - - PushAndAdd(call, source_position); } @@ -2914,7 +2871,9 @@ void HGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) { Handle<SharedFunctionInfo> shared_info = Compiler::BuildFunctionInfo(expr, graph_->info()->script()); CHECK_BAILOUT; - PushAndAdd(new HFunctionLiteral(shared_info, expr->pretenure())); + HFunctionLiteral* instr = + new HFunctionLiteral(shared_info, expr->pretenure()); + ast_context()->ReturnInstruction(instr, expr->id()); } @@ -2935,20 +2894,21 @@ void HGraphBuilder::VisitConditional(Conditional* expr) { ADD_TO_SUBGRAPH(then_graph, expr->then_expression()); ADD_TO_SUBGRAPH(else_graph, expr->else_expression()); current_subgraph_->AppendJoin(then_graph, else_graph, expr); + ast_context()->ReturnValue(Pop()); } -void HGraphBuilder::LookupGlobalPropertyCell(VariableProxy* expr, +void HGraphBuilder::LookupGlobalPropertyCell(Variable* var, LookupResult* lookup, bool is_store) { - if (expr->is_this()) { + if (var->is_this()) { BAILOUT("global this reference"); } if (!graph()->info()->has_global_object()) { BAILOUT("no global object to optimize VariableProxy"); } Handle<GlobalObject> global(graph()->info()->global_object()); - global->Lookup(*expr->name(), lookup); + global->Lookup(*var->name(), lookup); if (!lookup->IsProperty()) { BAILOUT("global variable cell not yet introduced"); } @@ -2961,23 +2921,6 @@ void HGraphBuilder::LookupGlobalPropertyCell(VariableProxy* expr, } -void HGraphBuilder::HandleGlobalVariableLoad(VariableProxy* expr) { - LookupResult lookup; - LookupGlobalPropertyCell(expr, &lookup, false); - CHECK_BAILOUT; - - Handle<GlobalObject> global(graph()->info()->global_object()); - // TODO(3039103): Handle global property load through an IC call when access - // checks are enabled. - if (global->IsAccessCheckNeeded()) { - BAILOUT("global object requires access check"); - } - Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); - bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly(); - PushAndAdd(new HLoadGlobal(cell, check_hole)); -} - - void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) { Variable* variable = expr->AsVariable(); if (variable == NULL) { @@ -2986,9 +2929,22 @@ void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) { if (environment()->Lookup(variable)->CheckFlag(HValue::kIsArguments)) { BAILOUT("unsupported context for arguments object"); } - Push(environment()->Lookup(variable)); + ast_context()->ReturnValue(environment()->Lookup(variable)); } else if (variable->is_global()) { - HandleGlobalVariableLoad(expr); + LookupResult lookup; + LookupGlobalPropertyCell(variable, &lookup, false); + CHECK_BAILOUT; + + Handle<GlobalObject> global(graph()->info()->global_object()); + // TODO(3039103): Handle global property load through an IC call when access + // checks are enabled. + if (global->IsAccessCheckNeeded()) { + BAILOUT("global object requires access check"); + } + Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); + bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly(); + HLoadGlobal* instr = new HLoadGlobal(cell, check_hole); + ast_context()->ReturnInstruction(instr, expr->id()); } else { BAILOUT("reference to non-stack-allocated/non-global variable"); } @@ -2996,14 +2952,16 @@ void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) { void HGraphBuilder::VisitLiteral(Literal* expr) { - PushAndAdd(new HConstant(expr->handle(), Representation::Tagged())); + HConstant* instr = new HConstant(expr->handle(), Representation::Tagged()); + ast_context()->ReturnInstruction(instr, expr->id()); } void HGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { - PushAndAdd(new HRegExpLiteral(expr->pattern(), - expr->flags(), - expr->literal_index())); + HRegExpLiteral* instr = new HRegExpLiteral(expr->pattern(), + expr->flags(), + expr->literal_index()); + ast_context()->ReturnInstruction(instr, expr->id()); } @@ -3012,6 +2970,8 @@ void HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { expr->fast_elements(), expr->literal_index(), expr->depth())); + // The object is expected in the bailout environment during computation + // of the property values and is the value of the entire expression. PushAndAdd(literal); expr->CalculateEmitStore(); @@ -3048,6 +3008,7 @@ void HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { default: UNREACHABLE(); } } + ast_context()->ReturnValue(Pop()); } @@ -3059,6 +3020,8 @@ void HGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { length, expr->literal_index(), expr->depth()); + // The array is expected in the bailout environment during computation + // of the property values and is the value of the entire expression. PushAndAdd(literal); HValue* elements = AddInstruction(new HLoadElements(literal)); @@ -3076,6 +3039,7 @@ void HGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { AddInstruction(new HStoreKeyedFastElement(elements, key, value)); AddSimulate(expr->GetIdForElement(i)); } + ast_context()->ReturnValue(Pop()); } @@ -3257,27 +3221,29 @@ void HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr, Push(value); instr->set_position(expr->position()); AddInstruction(instr); - return; - } - - // Build subgraph for generic store through IC. - { - HSubgraph* subgraph = CreateBranchSubgraph(environment()); - SubgraphScope scope(this, subgraph); - if (!needs_generic && FLAG_deoptimize_uncommon_cases) { - subgraph->FinishExit(new HDeoptimize()); - } else { - HInstruction* instr = new HStoreNamedGeneric(object, name, value); - Push(value); - instr->set_position(expr->position()); - AddInstruction(instr); + if (instr->HasSideEffects()) AddSimulate(expr->id()); + } else { + // Build subgraph for generic store through IC. + { + HSubgraph* subgraph = CreateBranchSubgraph(environment()); + SubgraphScope scope(this, subgraph); + if (!needs_generic && FLAG_deoptimize_uncommon_cases) { + subgraph->FinishExit(new HDeoptimize()); + } else { + HInstruction* instr = new HStoreNamedGeneric(object, name, value); + Push(value); + instr->set_position(expr->position()); + AddInstruction(instr); + } + subgraphs.Add(subgraph); } - subgraphs.Add(subgraph); + + HBasicBlock* new_exit_block = + BuildTypeSwitch(&maps, &subgraphs, object, expr->id()); + subgraph()->set_exit_block(new_exit_block); } - HBasicBlock* new_exit_block = - BuildTypeSwitch(&maps, &subgraphs, object, expr->id()); - current_subgraph_->set_exit_block(new_exit_block); + if (subgraph()->HasExit()) ast_context()->ReturnValue(Pop()); } @@ -3333,14 +3299,20 @@ void HGraphBuilder::HandlePropertyAssignment(Assignment* expr) { Push(value); instr->set_position(expr->position()); AddInstruction(instr); + if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); + ast_context()->ReturnValue(Pop()); } -void HGraphBuilder::HandleGlobalVariableAssignment(VariableProxy* proxy, +// Because not every expression has a position and there is not common +// superclass of Assignment and CountOperation, we cannot just pass the +// owning expression instead of position and ast_id separately. +void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var, HValue* value, - int position) { + int position, + int ast_id) { LookupResult lookup; - LookupGlobalPropertyCell(proxy, &lookup, true); + LookupGlobalPropertyCell(var, &lookup, true); CHECK_BAILOUT; Handle<GlobalObject> global(graph()->info()->global_object()); @@ -3348,6 +3320,7 @@ void HGraphBuilder::HandleGlobalVariableAssignment(VariableProxy* proxy, HInstruction* instr = new HStoreGlobal(value, cell); instr->set_position(position); AddInstruction(instr); + if (instr->HasSideEffects()) AddSimulate(ast_id); } @@ -3371,10 +3344,15 @@ void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) { VISIT_FOR_VALUE(operation); if (var->is_global()) { - HandleGlobalVariableAssignment(proxy, Top(), expr->position()); + HandleGlobalVariableAssignment(var, + Top(), + expr->position(), + expr->AssignmentId()); } else { Bind(var, Top()); } + ast_context()->ReturnValue(Pop()); + } else if (prop != NULL) { prop->RecordTypeFeedback(oracle()); @@ -3392,9 +3370,7 @@ void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) { load = BuildLoadNamedGeneric(obj, prop); } PushAndAdd(load); - if (load->HasSideEffects()) { - AddSimulate(expr->compound_bailout_id()); - } + if (load->HasSideEffects()) AddSimulate(expr->CompoundLoadId()); VISIT_FOR_VALUE(expr->value()); HValue* right = Pop(); @@ -3406,10 +3382,11 @@ void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) { HInstruction* store = BuildStoreNamed(obj, instr, prop); AddInstruction(store); - - // Drop the simulated receiver and value and put back the value. + // Drop the simulated receiver and value. Return the value. Drop(2); Push(instr); + if (store->HasSideEffects()) AddSimulate(expr->AssignmentId()); + ast_context()->ReturnValue(Pop()); } else { // Keyed property. @@ -3425,9 +3402,7 @@ void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) { ? BuildLoadKeyedFastElement(obj, key, prop) : BuildLoadKeyedGeneric(obj, key); PushAndAdd(load); - if (load->HasSideEffects()) { - AddSimulate(expr->compound_bailout_id()); - } + if (load->HasSideEffects()) AddSimulate(expr->CompoundLoadId()); VISIT_FOR_VALUE(expr->value()); HValue* right = Pop(); @@ -3441,11 +3416,13 @@ void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) { ? BuildStoreKeyedFastElement(obj, key, instr, prop) : BuildStoreKeyedGeneric(obj, key, instr); AddInstruction(store); - - // Drop the simulated receiver, key and value and put back the value. + // Drop the simulated receiver, key, and value. Return the value. Drop(3); Push(instr); + if (store->HasSideEffects()) AddSimulate(expr->AssignmentId()); + ast_context()->ReturnValue(Pop()); } + } else { BAILOUT("invalid lhs in compound assignment"); } @@ -3465,9 +3442,14 @@ void HGraphBuilder::VisitAssignment(Assignment* expr) { if (var != NULL) { if (proxy->IsArguments()) BAILOUT("assignment to arguments"); + + // Handle the assignment. if (var->is_global()) { VISIT_FOR_VALUE(expr->value()); - HandleGlobalVariableAssignment(proxy, Top(), expr->position()); + HandleGlobalVariableAssignment(var, + Top(), + expr->position(), + expr->AssignmentId()); } else { // We allow reference to the arguments object only in assignemtns // to local variables to make sure that the arguments object does @@ -3480,9 +3462,11 @@ void HGraphBuilder::VisitAssignment(Assignment* expr) { } else { VISIT_FOR_VALUE(expr->value()); } - Bind(proxy->var(), Top()); } + // Return the value. + ast_context()->ReturnValue(Pop()); + } else if (prop != NULL) { HandlePropertyAssignment(expr); } else { @@ -3492,6 +3476,10 @@ void HGraphBuilder::VisitAssignment(Assignment* expr) { void HGraphBuilder::VisitThrow(Throw* expr) { + // We don't optimize functions with invalid left-hand sides in + // assignments, count operations, or for-in. Consequently throw can + // currently only occur in an effect context. + ASSERT(ast_context()->IsEffect()); VISIT_FOR_VALUE(expr->exception()); HValue* value = environment()->Pop(); @@ -3525,7 +3513,8 @@ void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr, SubgraphScope scope(this, subgraph); HInstruction* instr = BuildLoadNamedField(object, expr, map, &lookup, false); - PushAndAdd(instr, expr->position()); + instr->set_position(expr->position()); + PushAndAdd(instr); subgraphs.Add(subgraph); } else { needs_generic = true; @@ -3536,26 +3525,30 @@ void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr, // generic load. if (maps.length() == 0) { HInstruction* instr = BuildLoadNamedGeneric(object, expr); - PushAndAdd(instr, expr->position()); - return; - } - - // Build subgraph for generic load through IC. - { - HSubgraph* subgraph = CreateBranchSubgraph(environment()); - SubgraphScope scope(this, subgraph); - if (!needs_generic && FLAG_deoptimize_uncommon_cases) { - subgraph->FinishExit(new HDeoptimize()); - } else { - HInstruction* instr = BuildLoadNamedGeneric(object, expr); - PushAndAdd(instr, expr->position()); + instr->set_position(expr->position()); + PushAndAdd(instr); + if (instr->HasSideEffects()) AddSimulate(expr->id()); + } else { + // Build subgraph for generic load through IC. + { + HSubgraph* subgraph = CreateBranchSubgraph(environment()); + SubgraphScope scope(this, subgraph); + if (!needs_generic && FLAG_deoptimize_uncommon_cases) { + subgraph->FinishExit(new HDeoptimize()); + } else { + HInstruction* instr = BuildLoadNamedGeneric(object, expr); + instr->set_position(expr->position()); + PushAndAdd(instr); + } + subgraphs.Add(subgraph); } - subgraphs.Add(subgraph); + + HBasicBlock* new_exit_block = + BuildTypeSwitch(&maps, &subgraphs, object, expr->id()); + subgraph()->set_exit_block(new_exit_block); } - HBasicBlock* new_exit_block = - BuildTypeSwitch(&maps, &subgraphs, object, expr->id()); - current_subgraph_->set_exit_block(new_exit_block); + if (subgraph()->HasExit()) ast_context()->ReturnValue(Pop()); } @@ -3668,11 +3661,12 @@ bool HGraphBuilder::TryArgumentsAccess(Property* expr) { return false; } + HInstruction* result = NULL; if (expr->key()->IsPropertyName()) { Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); if (!name->IsEqualTo(CStrVector("length"))) return false; HInstruction* elements = AddInstruction(new HArgumentsElements); - PushAndAdd(new HArgumentsLength(elements)); + result = new HArgumentsLength(elements); } else { VisitForValue(expr->key()); if (HasStackOverflow()) return false; @@ -3680,8 +3674,9 @@ bool HGraphBuilder::TryArgumentsAccess(Property* expr) { HInstruction* elements = AddInstruction(new HArgumentsElements); HInstruction* length = AddInstruction(new HArgumentsLength(elements)); AddInstruction(new HBoundsCheck(key, length)); - PushAndAdd(new HAccessArgumentsAt(elements, length, key)); + result = new HAccessArgumentsAt(elements, length, key); } + ast_context()->ReturnInstruction(result, expr->id()); return true; } @@ -3728,7 +3723,8 @@ void HGraphBuilder::VisitProperty(Property* expr) { ? BuildLoadKeyedFastElement(obj, key, expr) : BuildLoadKeyedGeneric(obj, key); } - PushAndAdd(instr, expr->position()); + instr->set_position(expr->position()); + ast_context()->ReturnInstruction(instr, expr->id()); } @@ -3763,9 +3759,9 @@ void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr, // Build subgraphs for each of the specific maps. // - // TODO(ager): We should recognize when the prototype chains for - // different maps are identical. In that case we can avoid - // repeatedly generating the same prototype map checks. + // TODO(ager): We should recognize when the prototype chains for different + // maps are identical. In that case we can avoid repeatedly generating the + // same prototype map checks. for (int i = 0; i < number_of_types; ++i) { Handle<Map> map = types->at(i); if (expr->ComputeTarget(map, name)) { @@ -3782,7 +3778,9 @@ void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr, // during hydrogen processing. CHECK_BAILOUT; HCall* call = new HCallConstantFunction(expr->target(), argument_count); - ProcessCall(call, expr->position()); + call->set_position(expr->position()); + ProcessCall(call); + PushAndAdd(call); } subgraphs.Add(subgraph); } else { @@ -3790,30 +3788,34 @@ void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr, } } - // If we couldn't compute the target for any of the maps just - // perform an IC call. + // If we couldn't compute the target for any of the maps just perform an + // IC call. if (maps.length() == 0) { HCall* call = new HCallNamed(name, argument_count); - ProcessCall(call, expr->position()); - return; - } - - // Build subgraph for generic call through IC. - { - HSubgraph* subgraph = CreateBranchSubgraph(environment()); - SubgraphScope scope(this, subgraph); - if (!needs_generic && FLAG_deoptimize_uncommon_cases) { - subgraph->FinishExit(new HDeoptimize()); - } else { - HCall* call = new HCallNamed(name, argument_count); - ProcessCall(call, expr->position()); + call->set_position(expr->position()); + ProcessCall(call); + ast_context()->ReturnInstruction(call, expr->id()); + } else { + // Build subgraph for generic call through IC. + { + HSubgraph* subgraph = CreateBranchSubgraph(environment()); + SubgraphScope scope(this, subgraph); + if (!needs_generic && FLAG_deoptimize_uncommon_cases) { + subgraph->FinishExit(new HDeoptimize()); + } else { + HCall* call = new HCallNamed(name, argument_count); + call->set_position(expr->position()); + ProcessCall(call); + PushAndAdd(call); + } + subgraphs.Add(subgraph); } - subgraphs.Add(subgraph); - } - HBasicBlock* new_exit_block = - BuildTypeSwitch(&maps, &subgraphs, receiver, expr->id()); - current_subgraph_->set_exit_block(new_exit_block); + HBasicBlock* new_exit_block = + BuildTypeSwitch(&maps, &subgraphs, receiver, expr->id()); + subgraph()->set_exit_block(new_exit_block); + if (new_exit_block != NULL) ast_context()->ReturnValue(Pop()); + } } @@ -4061,6 +4063,7 @@ bool HGraphBuilder::TryInline(Call* expr) { function_return_ = saved_function_return; oracle_ = saved_oracle; graph()->info()->SetOsrAstId(saved_osr_ast_id); + return true; } @@ -4086,10 +4089,55 @@ bool HGraphBuilder::TryMathFunctionInline(Call* expr) { case kMathSqrt: if (argument_count == 2) { HValue* argument = Pop(); - // Pop receiver. - Pop(); + Drop(1); // Receiver. HUnaryMathOperation* op = new HUnaryMathOperation(argument, id); - PushAndAdd(op, expr->position()); + op->set_position(expr->position()); + ast_context()->ReturnInstruction(op, expr->id()); + return true; + } + break; + case kMathPow: + if (argument_count == 3) { + HValue* right = Pop(); + HValue* left = Pop(); + Pop(); // Pop receiver. + HInstruction* result = NULL; + // Use sqrt() if exponent is 0.5 or -0.5. + if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) { + double exponent = HConstant::cast(right)->DoubleValue(); + if (exponent == 0.5) { + result = new HUnaryMathOperation(left, kMathPowHalf); + ast_context()->ReturnInstruction(result, expr->id()); + return true; + } else if (exponent == -0.5) { + HConstant* double_one = + new HConstant(Handle<Object>(Smi::FromInt(1)), + Representation::Double()); + AddInstruction(double_one); + HUnaryMathOperation* square_root = + new HUnaryMathOperation(left, kMathPowHalf); + AddInstruction(square_root); + // MathPowHalf doesn't have side effects so there's no need for + // an environment simulation here. + ASSERT(!square_root->HasSideEffects()); + result = new HDiv(double_one, square_root); + ast_context()->ReturnInstruction(result, expr->id()); + return true; + } else if (exponent == 2.0) { + result = new HMul(left, left); + ast_context()->ReturnInstruction(result, expr->id()); + return true; + } + } else if (right->IsConstant() && + HConstant::cast(right)->HasInteger32Value() && + HConstant::cast(right)->Integer32Value() == 2) { + result = new HMul(left, left); + ast_context()->ReturnInstruction(result, expr->id()); + return true; + } + + result = new HPower(left, right); + ast_context()->ReturnInstruction(result, expr->id()); return true; } break; @@ -4134,8 +4182,10 @@ bool HGraphBuilder::TryCallApply(Call* expr) { function, expr->GetReceiverTypes()->first(), true); - PushAndAdd(new HApplyArguments(function, receiver, length, elements), - expr->position()); + HInstruction* result = + new HApplyArguments(function, receiver, length, elements); + result->set_position(expr->position()); + ast_context()->ReturnInstruction(result, expr->id()); return true; } @@ -4163,12 +4213,10 @@ void HGraphBuilder::VisitCall(Call* expr) { CHECK_BAILOUT; call = new HCallKeyed(key, argument_count); - ProcessCall(call, expr->position()); - HValue* result = Pop(); - // Drop the receiver from the environment and put back the result of - // the call. - Drop(1); - Push(result); + call->set_position(expr->position()); + ProcessCall(call); + Drop(1); // Key. + ast_context()->ReturnInstruction(call, expr->id()); return; } @@ -4191,7 +4239,19 @@ void HGraphBuilder::VisitCall(Call* expr) { if (expr->IsMonomorphic()) { AddCheckConstantFunction(expr, receiver, types->first(), true); - if (TryMathFunctionInline(expr) || TryInline(expr)) { + if (TryMathFunctionInline(expr)) { + return; + } else if (TryInline(expr)) { + if (subgraph()->HasExit()) { + HValue* return_value = Pop(); + // If we inlined a function in a test context then we need to emit + // a simulate here to shadow the ones at the end of the + // predecessor blocks. Those environments contain the return + // value on top and do not correspond to any actual state of the + // unoptimized code. + if (ast_context()->IsEffect()) AddSimulate(expr->id()); + ast_context()->ReturnValue(return_value); + } return; } else { // Check for bailout, as the TryInline call in the if condition above @@ -4199,6 +4259,7 @@ void HGraphBuilder::VisitCall(Call* expr) { CHECK_BAILOUT; call = new HCallConstantFunction(expr->target(), argument_count); } + } else if (types != NULL && types->length() > 1) { HandlePolymorphicCallNamed(expr, receiver, types, name); return; @@ -4246,7 +4307,19 @@ void HGraphBuilder::VisitCall(Call* expr) { IsGlobalObject()); environment()->SetExpressionStackAt(receiver_index, global_receiver); - if (TryInline(expr)) return; + if (TryInline(expr)) { + if (subgraph()->HasExit()) { + HValue* return_value = Pop(); + // If we inlined a function in a test context then we need to + // emit a simulate here to shadow the ones at the end of the + // predecessor blocks. Those environments contain the return + // value on top and do not correspond to any actual state of the + // unoptimized code. + if (ast_context()->IsEffect()) AddSimulate(expr->id()); + ast_context()->ReturnValue(return_value); + } + return; + } // Check for bailout, as trying to inline might fail due to bailout // during hydrogen processing. CHECK_BAILOUT; @@ -4269,7 +4342,9 @@ void HGraphBuilder::VisitCall(Call* expr) { } } - ProcessCall(call, expr->position()); + call->set_position(expr->position()); + ProcessCall(call); + ast_context()->ReturnInstruction(call, expr->id()); } @@ -4283,8 +4358,9 @@ void HGraphBuilder::VisitCallNew(CallNew* expr) { int argument_count = expr->arguments()->length() + 1; // Plus constructor. HCall* call = new HCallNew(argument_count); - - ProcessCall(call, expr->position()); + call->set_position(expr->position()); + ProcessCall(call); + ast_context()->ReturnInstruction(call, expr->id()); } @@ -4292,7 +4368,7 @@ void HGraphBuilder::VisitCallNew(CallNew* expr) { // Lookup table for generators for runtime calls that are generated inline. // Elements of the table are member pointers to functions of HGraphBuilder. -#define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \ +#define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \ &HGraphBuilder::Generate##Name, const HGraphBuilder::InlineFunctionGenerator @@ -4306,7 +4382,7 @@ const HGraphBuilder::InlineFunctionGenerator void HGraphBuilder::VisitCallRuntime(CallRuntime* expr) { Handle<String> name = expr->name(); if (name->IsEqualTo(CStrVector("_Log"))) { - Push(graph()->GetConstantUndefined()); + ast_context()->ReturnValue(graph()->GetConstantUndefined()); return; } @@ -4332,11 +4408,13 @@ void HGraphBuilder::VisitCallRuntime(CallRuntime* expr) { InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index]; // Call the inline code generator using the pointer-to-member. - (this->*generator)(argument_count); + (this->*generator)(argument_count, expr->id()); } else { ASSERT(function->intrinsic_type == Runtime::RUNTIME); HCall* call = new HCallRuntime(name, expr->function(), argument_count); - ProcessCall(call, RelocInfo::kNoPosition); + call->set_position(RelocInfo::kNoPosition); + ProcessCall(call); + ast_context()->ReturnInstruction(call, expr->id()); } } @@ -4345,7 +4423,7 @@ void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { Token::Value op = expr->op(); if (op == Token::VOID) { VISIT_FOR_EFFECT(expr->expression()); - Push(graph()->GetConstantUndefined()); + ast_context()->ReturnValue(graph()->GetConstantUndefined()); } else if (op == Token::DELETE) { Property* prop = expr->expression()->AsProperty(); Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); @@ -4353,36 +4431,47 @@ void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { // Result of deleting non-property, non-variable reference is true. // Evaluate the subexpression for side effects. VISIT_FOR_EFFECT(expr->expression()); - Push(graph_->GetConstantTrue()); + ast_context()->ReturnValue(graph()->GetConstantTrue()); } else if (var != NULL && !var->is_global() && var->AsSlot() != NULL && var->AsSlot()->type() != Slot::LOOKUP) { // Result of deleting non-global, non-dynamic variables is false. // The subexpression does not have side effects. - Push(graph_->GetConstantFalse()); + ast_context()->ReturnValue(graph()->GetConstantFalse()); } else if (prop != NULL) { VISIT_FOR_VALUE(prop->obj()); VISIT_FOR_VALUE(prop->key()); HValue* key = Pop(); HValue* obj = Pop(); - PushAndAdd(new HDeleteProperty(obj, key)); + ast_context()->ReturnInstruction(new HDeleteProperty(obj, key), + expr->id()); } else if (var->is_global()) { BAILOUT("delete with global variable"); } else { BAILOUT("delete with non-global variable"); } } else if (op == Token::NOT) { - HSubgraph* true_graph = CreateEmptySubgraph(); - HSubgraph* false_graph = CreateEmptySubgraph(); - VisitCondition(expr->expression(), - false_graph->entry_block(), - true_graph->entry_block(), - true, true); - if (HasStackOverflow()) return; - true_graph->environment()->Push(graph_->GetConstantTrue()); - false_graph->environment()->Push(graph_->GetConstantFalse()); - current_subgraph_->AppendJoin(true_graph, false_graph, expr); + if (ast_context()->IsTest()) { + TestContext* context = TestContext::cast(ast_context()); + VisitForControl(expr->expression(), + context->if_false(), + context->if_true(), + !context->invert_false(), + !context->invert_true()); + } else { + HSubgraph* true_graph = CreateEmptySubgraph(); + HSubgraph* false_graph = CreateEmptySubgraph(); + VisitCondition(expr->expression(), + false_graph->entry_block(), + true_graph->entry_block(), + true, true); + if (HasStackOverflow()) return; + true_graph->environment()->Push(graph_->GetConstantTrue()); + false_graph->environment()->Push(graph_->GetConstantFalse()); + current_subgraph_->AppendJoin(true_graph, false_graph, expr); + ast_context()->ReturnValue(Pop()); + } } else if (op == Token::BIT_NOT || op == Token::SUB) { VISIT_FOR_VALUE(expr->expression()); HValue* value = Pop(); @@ -4398,11 +4487,11 @@ void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { UNREACHABLE(); break; } - PushAndAdd(instr); + ast_context()->ReturnInstruction(instr, expr->id()); } else if (op == Token::TYPEOF) { VISIT_FOR_VALUE(expr->expression()); HValue* value = Pop(); - PushAndAdd(new HTypeof(value)); + ast_context()->ReturnInstruction(new HTypeof(value), expr->id()); } else { BAILOUT("Value: unsupported unary operation"); } @@ -4453,11 +4542,15 @@ void HGraphBuilder::VisitCountOperation(CountOperation* expr) { } if (var->is_global()) { - HandleGlobalVariableAssignment(proxy, instr, expr->position()); + HandleGlobalVariableAssignment(var, + instr, + expr->position(), + expr->AssignmentId()); } else { ASSERT(var->IsStackAllocated()); Bind(var, instr); } + ast_context()->ReturnValue(Pop()); } else if (prop != NULL) { prop->RecordTypeFeedback(oracle()); @@ -4465,11 +4558,10 @@ void HGraphBuilder::VisitCountOperation(CountOperation* expr) { if (prop->key()->IsPropertyName()) { // Named property. - // Match the full code generator stack by simulate an extra stack element - // for postfix operations in a value context. - if (expr->is_postfix() && !ast_context()->IsEffect()) { - Push(graph_->GetConstantUndefined()); - } + // Match the full code generator stack by simulating an extra stack + // element for postfix operations in a value context. + bool has_extra = expr->is_postfix() && !ast_context()->IsEffect(); + if (has_extra) Push(graph_->GetConstantUndefined()); VISIT_FOR_VALUE(prop->obj()); HValue* obj = Top(); @@ -4485,37 +4577,35 @@ void HGraphBuilder::VisitCountOperation(CountOperation* expr) { PushAndAdd(load); if (load->HasSideEffects()) AddSimulate(increment->id()); - HValue* value = Pop(); - - HInstruction* instr = BuildIncrement(value, inc); - AddInstruction(instr); + HValue* before = Pop(); + // There is no deoptimization to after the increment, so we don't need + // to simulate the expression stack after this instruction. + HInstruction* after = BuildIncrement(before, inc); + AddInstruction(after); - HInstruction* store = BuildStoreNamed(obj, instr, prop); + HInstruction* store = BuildStoreNamed(obj, after, prop); AddInstruction(store); - // Drop simulated receiver and push the result. - // There is no deoptimization to after the increment, so we can simulate - // the expression stack here. - Drop(1); - if (expr->is_prefix()) { - Push(instr); - } else { - if (!ast_context()->IsEffect()) Drop(1); // Drop simulated zero. - Push(value); - } + // Overwrite the receiver in the bailout environment with the result + // of the operation, and the placeholder with the original value if + // necessary. + environment()->SetExpressionStackAt(0, after); + if (has_extra) environment()->SetExpressionStackAt(1, before); + if (store->HasSideEffects()) AddSimulate(expr->AssignmentId()); + Drop(has_extra ? 2 : 1); + + ast_context()->ReturnValue(expr->is_postfix() ? before : after); } else { // Keyed property. // Match the full code generator stack by simulate an extra stack element // for postfix operations in a value context. - if (expr->is_postfix() && !ast_context()->IsEffect()) { - Push(graph_->GetConstantUndefined()); - } + bool has_extra = expr->is_postfix() && !ast_context()->IsEffect(); + if (has_extra) Push(graph_->GetConstantUndefined()); VISIT_FOR_VALUE(prop->obj()); VISIT_FOR_VALUE(prop->key()); - HValue* obj = environment()->ExpressionStackAt(1); HValue* key = environment()->ExpressionStackAt(0); @@ -4528,27 +4618,29 @@ void HGraphBuilder::VisitCountOperation(CountOperation* expr) { PushAndAdd(load); if (load->HasSideEffects()) AddSimulate(increment->id()); - HValue* value = Pop(); - - HInstruction* instr = BuildIncrement(value, inc); - AddInstruction(instr); + HValue* before = Pop(); + // There is no deoptimization to after the increment, so we don't need + // to simulate the expression stack after this instruction. + HInstruction* after = BuildIncrement(before, inc); + AddInstruction(after); HInstruction* store = is_fast_elements - ? BuildStoreKeyedFastElement(obj, key, instr, prop) - : new HStoreKeyedGeneric(obj, key, instr); + ? BuildStoreKeyedFastElement(obj, key, after, prop) + : new HStoreKeyedGeneric(obj, key, after); AddInstruction(store); - // Drop simulated receiver and key and push the result. - // There is no deoptimization to after the increment, so we can simulate - // the expression stack here. - Drop(2); - if (expr->is_prefix()) { - Push(instr); - } else { - if (!ast_context()->IsEffect()) Drop(1); // Drop simulated zero. - Push(value); - } + // Drop the key from the bailout environment. Overwrite the receiver + // with the result of the operation, and the placeholder with the + // original value if necessary. + Drop(1); + environment()->SetExpressionStackAt(0, after); + if (has_extra) environment()->SetExpressionStackAt(1, before); + if (store->HasSideEffects()) AddSimulate(expr->AssignmentId()); + Drop(has_extra ? 2 : 1); + + ast_context()->ReturnValue(expr->is_postfix() ? before : after); } + } else { BAILOUT("invalid lhs in count operation"); } @@ -4630,21 +4722,47 @@ static bool IsClassOfTest(CompareOperation* expr) { void HGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { if (expr->op() == Token::COMMA) { VISIT_FOR_EFFECT(expr->left()); - VISIT_FOR_VALUE(expr->right()); - } else if (expr->op() == Token::AND || expr->op() == Token::OR) { - VISIT_FOR_VALUE(expr->left()); - ASSERT(current_subgraph_->HasExit()); + // Visit the right subexpression in the same AST context as the entire + // expression. + Visit(expr->right()); - HValue* left = Top(); + } else if (expr->op() == Token::AND || expr->op() == Token::OR) { bool is_logical_and = (expr->op() == Token::AND); + if (ast_context()->IsTest()) { + TestContext* context = TestContext::cast(ast_context()); + // Translate left subexpression. + HBasicBlock* eval_right = graph()->CreateBasicBlock(); + if (is_logical_and) { + VisitForControl(expr->left(), eval_right, context->if_false(), + false, context->invert_false()); + } else { + VisitForControl(expr->left(), context->if_true(), eval_right, + context->invert_true(), false); + } + if (HasStackOverflow()) return; + eval_right->SetJoinId(expr->left()->id()); + + // Translate right subexpression by visiting it in the same AST + // context as the entire expression. + eval_right->last_environment()->Pop(); + subgraph()->set_exit_block(eval_right); + Visit(expr->right()); + + } else { + VISIT_FOR_VALUE(expr->left()); + ASSERT(current_subgraph_->HasExit()); + + HValue* left = Top(); + HEnvironment* environment_copy = environment()->Copy(); + environment_copy->Pop(); + HSubgraph* right_subgraph; + right_subgraph = CreateBranchSubgraph(environment_copy); + ADD_TO_SUBGRAPH(right_subgraph, expr->right()); + current_subgraph_->AppendOptional(right_subgraph, is_logical_and, left); + current_subgraph_->exit_block()->SetJoinId(expr->id()); + ast_context()->ReturnValue(Pop()); + } - HEnvironment* environment_copy = environment()->Copy(); - environment_copy->Pop(); - HSubgraph* right_subgraph; - right_subgraph = CreateBranchSubgraph(environment_copy); - ADD_TO_SUBGRAPH(right_subgraph, expr->right()); - current_subgraph_->AppendOptional(right_subgraph, is_logical_and, left); - current_subgraph_->exit_block()->SetJoinId(expr->id()); } else { VISIT_FOR_VALUE(expr->left()); VISIT_FOR_VALUE(expr->right()); @@ -4652,7 +4770,8 @@ void HGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { HValue* right = Pop(); HValue* left = Pop(); HInstruction* instr = BuildBinaryOperation(expr, left, right); - PushAndAdd(instr, expr->position()); + instr->set_position(expr->position()); + ast_context()->ReturnInstruction(instr, expr->id()); } } @@ -4691,7 +4810,8 @@ void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) { Literal* literal = expr->right()->AsLiteral(); Handle<String> rhs = Handle<String>::cast(literal->handle()); HInstruction* instr = new HClassOfTest(value, rhs); - PushAndAdd(instr, expr->position()); + instr->set_position(expr->position()); + ast_context()->ReturnInstruction(instr, expr->id()); return; } @@ -4705,7 +4825,8 @@ void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) { HValue* left = Pop(); HInstruction* instr = new HTypeofIs(left, Handle<String>::cast(right_literal->handle())); - PushAndAdd(instr, expr->position()); + instr->set_position(expr->position()); + ast_context()->ReturnInstruction(instr, expr->id()); return; } @@ -4741,7 +4862,8 @@ void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) { compare->SetInputRepresentation(r); instr = compare; } - PushAndAdd(instr, expr->position()); + instr->set_position(expr->position()); + ast_context()->ReturnInstruction(instr, expr->id()); } @@ -4750,8 +4872,7 @@ void HGraphBuilder::VisitCompareToNull(CompareToNull* expr) { HValue* value = Pop(); HIsNull* compare = new HIsNull(value, expr->is_strict()); - - PushAndAdd(compare); + ast_context()->ReturnInstruction(compare, expr->id()); } @@ -4778,301 +4899,305 @@ void HGraphBuilder::VisitDeclaration(Declaration* decl) { // Generators for inline runtime functions. // Support for types. -void HGraphBuilder::GenerateIsSmi(int argument_count) { +void HGraphBuilder::GenerateIsSmi(int argument_count, int ast_id) { ASSERT(argument_count == 1); - HValue* value = Pop(); - PushAndAdd(new HIsSmi(value)); + HIsSmi* result = new HIsSmi(value); + ast_context()->ReturnInstruction(result, ast_id); } -void HGraphBuilder::GenerateIsSpecObject(int argument_count) { +void HGraphBuilder::GenerateIsSpecObject(int argument_count, int ast_id) { ASSERT(argument_count == 1); - HValue* value = Pop(); - HHasInstanceType* test = + HHasInstanceType* result = new HHasInstanceType(value, FIRST_JS_OBJECT_TYPE, LAST_TYPE); - PushAndAdd(test); + ast_context()->ReturnInstruction(result, ast_id); } -void HGraphBuilder::GenerateIsFunction(int argument_count) { +void HGraphBuilder::GenerateIsFunction(int argument_count, int ast_id) { ASSERT(argument_count == 1); - HValue* value = Pop(); - HHasInstanceType* test = - new HHasInstanceType(value, JS_FUNCTION_TYPE); - PushAndAdd(test); + HHasInstanceType* result = new HHasInstanceType(value, JS_FUNCTION_TYPE); + ast_context()->ReturnInstruction(result, ast_id); } -void HGraphBuilder::GenerateHasCachedArrayIndex(int argument_count) { +void HGraphBuilder::GenerateHasCachedArrayIndex(int argument_count, + int ast_id) { ASSERT(argument_count == 1); - HValue* value = Pop(); - HHasCachedArrayIndex* spec_test = new HHasCachedArrayIndex(value); - PushAndAdd(spec_test); + HHasCachedArrayIndex* result = new HHasCachedArrayIndex(value); + ast_context()->ReturnInstruction(result, ast_id); } -void HGraphBuilder::GenerateIsArray(int argument_count) { +void HGraphBuilder::GenerateIsArray(int argument_count, int ast_id) { ASSERT(argument_count == 1); - HValue* value = Pop(); - HHasInstanceType* test = - new HHasInstanceType(value, JS_ARRAY_TYPE); - PushAndAdd(test); + HHasInstanceType* result = new HHasInstanceType(value, JS_ARRAY_TYPE); + ast_context()->ReturnInstruction(result, ast_id); } -void HGraphBuilder::GenerateIsRegExp(int argument_count) { +void HGraphBuilder::GenerateIsRegExp(int argument_count, int ast_id) { ASSERT(argument_count == 1); - HValue* value = Pop(); - HHasInstanceType* test = - new HHasInstanceType(value, JS_REGEXP_TYPE); - PushAndAdd(test); + HHasInstanceType* result = new HHasInstanceType(value, JS_REGEXP_TYPE); + ast_context()->ReturnInstruction(result, ast_id); } -void HGraphBuilder::GenerateIsNonNegativeSmi(int argument_count) { +void HGraphBuilder::GenerateIsNonNegativeSmi(int argument_count, + int ast_id) { BAILOUT("inlined runtime function: IsNonNegativeSmi"); } -void HGraphBuilder::GenerateIsObject(int argument_count) { +void HGraphBuilder::GenerateIsObject(int argument_count, int ast_id) { BAILOUT("inlined runtime function: IsObject"); } -void HGraphBuilder::GenerateIsUndetectableObject(int argument_count) { +void HGraphBuilder::GenerateIsUndetectableObject(int argument_count, + int ast_id) { BAILOUT("inlined runtime function: IsUndetectableObject"); } void HGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf( - int argument_count) { + int argument_count, + int ast_id) { BAILOUT("inlined runtime function: IsStringWrapperSafeForDefaultValueOf"); } // Support for construct call checks. -void HGraphBuilder::GenerateIsConstructCall(int argument_count) { +void HGraphBuilder::GenerateIsConstructCall(int argument_count, int ast_id) { BAILOUT("inlined runtime function: IsConstructCall"); } // Support for arguments.length and arguments[?]. -void HGraphBuilder::GenerateArgumentsLength(int argument_count) { +void HGraphBuilder::GenerateArgumentsLength(int argument_count, int ast_id) { ASSERT(argument_count == 0); HInstruction* elements = AddInstruction(new HArgumentsElements); - PushAndAdd(new HArgumentsLength(elements)); + HArgumentsLength* result = new HArgumentsLength(elements); + ast_context()->ReturnInstruction(result, ast_id); } -void HGraphBuilder::GenerateArguments(int argument_count) { +void HGraphBuilder::GenerateArguments(int argument_count, int ast_id) { ASSERT(argument_count == 1); HValue* index = Pop(); HInstruction* elements = AddInstruction(new HArgumentsElements); HInstruction* length = AddInstruction(new HArgumentsLength(elements)); - PushAndAdd(new HAccessArgumentsAt(elements, length, index)); + HAccessArgumentsAt* result = new HAccessArgumentsAt(elements, length, index); + ast_context()->ReturnInstruction(result, ast_id); } // Support for accessing the class and value fields of an object. -void HGraphBuilder::GenerateClassOf(int argument_count) { +void HGraphBuilder::GenerateClassOf(int argument_count, int ast_id) { // The special form detected by IsClassOfTest is detected before we get here // and does not cause a bailout. BAILOUT("inlined runtime function: ClassOf"); } -void HGraphBuilder::GenerateValueOf(int argument_count) { +void HGraphBuilder::GenerateValueOf(int argument_count, int ast_id) { ASSERT(argument_count == 1); - HValue* value = Pop(); - HValueOf* op = new HValueOf(value); - PushAndAdd(op); + HValueOf* result = new HValueOf(value); + ast_context()->ReturnInstruction(result, ast_id); } -void HGraphBuilder::GenerateSetValueOf(int argument_count) { +void HGraphBuilder::GenerateSetValueOf(int argument_count, int ast_id) { BAILOUT("inlined runtime function: SetValueOf"); } // Fast support for charCodeAt(n). -void HGraphBuilder::GenerateStringCharCodeAt(int argument_count) { +void HGraphBuilder::GenerateStringCharCodeAt(int argument_count, int ast_id) { BAILOUT("inlined runtime function: StringCharCodeAt"); } // Fast support for string.charAt(n) and string[n]. -void HGraphBuilder::GenerateStringCharFromCode(int argument_count) { +void HGraphBuilder::GenerateStringCharFromCode(int argument_count, + int ast_id) { BAILOUT("inlined runtime function: StringCharFromCode"); } // Fast support for string.charAt(n) and string[n]. -void HGraphBuilder::GenerateStringCharAt(int argument_count) { +void HGraphBuilder::GenerateStringCharAt(int argument_count, int ast_id) { ASSERT_EQ(2, argument_count); PushArgumentsForStubCall(argument_count); - PushAndAdd(new HCallStub(CodeStub::StringCharAt, argument_count), - RelocInfo::kNoPosition); + HCallStub* result = new HCallStub(CodeStub::StringCharAt, argument_count); + ast_context()->ReturnInstruction(result, ast_id); } // Fast support for object equality testing. -void HGraphBuilder::GenerateObjectEquals(int argument_count) { +void HGraphBuilder::GenerateObjectEquals(int argument_count, int ast_id) { ASSERT(argument_count == 2); - HValue* right = Pop(); HValue* left = Pop(); - PushAndAdd(new HCompareJSObjectEq(left, right)); + HCompareJSObjectEq* result = new HCompareJSObjectEq(left, right); + ast_context()->ReturnInstruction(result, ast_id); } -void HGraphBuilder::GenerateLog(int argument_count) { +void HGraphBuilder::GenerateLog(int argument_count, int ast_id) { UNREACHABLE(); // We caught this in VisitCallRuntime. } // Fast support for Math.random(). -void HGraphBuilder::GenerateRandomHeapNumber(int argument_count) { +void HGraphBuilder::GenerateRandomHeapNumber(int argument_count, int ast_id) { BAILOUT("inlined runtime function: RandomHeapNumber"); } // Fast support for StringAdd. -void HGraphBuilder::GenerateStringAdd(int argument_count) { +void HGraphBuilder::GenerateStringAdd(int argument_count, int ast_id) { ASSERT_EQ(2, argument_count); PushArgumentsForStubCall(argument_count); - PushAndAdd(new HCallStub(CodeStub::StringAdd, argument_count), - RelocInfo::kNoPosition); + HCallStub* result = new HCallStub(CodeStub::StringAdd, argument_count); + ast_context()->ReturnInstruction(result, ast_id); } // Fast support for SubString. -void HGraphBuilder::GenerateSubString(int argument_count) { +void HGraphBuilder::GenerateSubString(int argument_count, int ast_id) { ASSERT_EQ(3, argument_count); PushArgumentsForStubCall(argument_count); - PushAndAdd(new HCallStub(CodeStub::SubString, argument_count), - RelocInfo::kNoPosition); + HCallStub* result = new HCallStub(CodeStub::SubString, argument_count); + ast_context()->ReturnInstruction(result, ast_id); } // Fast support for StringCompare. -void HGraphBuilder::GenerateStringCompare(int argument_count) { +void HGraphBuilder::GenerateStringCompare(int argument_count, int ast_id) { ASSERT_EQ(2, argument_count); PushArgumentsForStubCall(argument_count); - PushAndAdd(new HCallStub(CodeStub::StringCompare, argument_count), - RelocInfo::kNoPosition); + HCallStub* result = new HCallStub(CodeStub::StringCompare, argument_count); + ast_context()->ReturnInstruction(result, ast_id); } // Support for direct calls from JavaScript to native RegExp code. -void HGraphBuilder::GenerateRegExpExec(int argument_count) { +void HGraphBuilder::GenerateRegExpExec(int argument_count, int ast_id) { ASSERT_EQ(4, argument_count); PushArgumentsForStubCall(argument_count); - PushAndAdd(new HCallStub(CodeStub::RegExpExec, argument_count), - RelocInfo::kNoPosition); + HCallStub* result = new HCallStub(CodeStub::RegExpExec, argument_count); + ast_context()->ReturnInstruction(result, ast_id); } // Construct a RegExp exec result with two in-object properties. -void HGraphBuilder::GenerateRegExpConstructResult(int argument_count) { +void HGraphBuilder::GenerateRegExpConstructResult(int argument_count, + int ast_id) { ASSERT_EQ(3, argument_count); PushArgumentsForStubCall(argument_count); - PushAndAdd(new HCallStub(CodeStub::RegExpConstructResult, argument_count), - RelocInfo::kNoPosition); + HCallStub* result = + new HCallStub(CodeStub::RegExpConstructResult, argument_count); + ast_context()->ReturnInstruction(result, ast_id); } // Support for fast native caches. -void HGraphBuilder::GenerateGetFromCache(int argument_count) { +void HGraphBuilder::GenerateGetFromCache(int argument_count, int ast_id) { BAILOUT("inlined runtime function: GetFromCache"); } // Fast support for number to string. -void HGraphBuilder::GenerateNumberToString(int argument_count) { +void HGraphBuilder::GenerateNumberToString(int argument_count, int ast_id) { ASSERT_EQ(1, argument_count); PushArgumentsForStubCall(argument_count); - PushAndAdd(new HCallStub(CodeStub::NumberToString, argument_count), - RelocInfo::kNoPosition); + HCallStub* result = new HCallStub(CodeStub::NumberToString, argument_count); + ast_context()->ReturnInstruction(result, ast_id); } // Fast swapping of elements. Takes three expressions, the object and two // indices. This should only be used if the indices are known to be // non-negative and within bounds of the elements array at the call site. -void HGraphBuilder::GenerateSwapElements(int argument_count) { +void HGraphBuilder::GenerateSwapElements(int argument_count, int ast_id) { BAILOUT("inlined runtime function: SwapElements"); } // Fast call for custom callbacks. -void HGraphBuilder::GenerateCallFunction(int argument_count) { +void HGraphBuilder::GenerateCallFunction(int argument_count, int ast_id) { BAILOUT("inlined runtime function: CallFunction"); } // Fast call to math functions. -void HGraphBuilder::GenerateMathPow(int argument_count) { +void HGraphBuilder::GenerateMathPow(int argument_count, int ast_id) { ASSERT_EQ(2, argument_count); - PushArgumentsForStubCall(argument_count); - PushAndAdd(new HCallStub(CodeStub::MathPow, argument_count), - RelocInfo::kNoPosition); + HValue* right = Pop(); + HValue* left = Pop(); + HPower* result = new HPower(left, right); + ast_context()->ReturnInstruction(result, ast_id); } -void HGraphBuilder::GenerateMathSin(int argument_count) { +void HGraphBuilder::GenerateMathSin(int argument_count, int ast_id) { ASSERT_EQ(1, argument_count); PushArgumentsForStubCall(argument_count); - HCallStub* instr = + HCallStub* result = new HCallStub(CodeStub::TranscendentalCache, argument_count); - instr->set_transcendental_type(TranscendentalCache::SIN); - PushAndAdd(instr, RelocInfo::kNoPosition); + result->set_transcendental_type(TranscendentalCache::SIN); + ast_context()->ReturnInstruction(result, ast_id); } -void HGraphBuilder::GenerateMathCos(int argument_count) { +void HGraphBuilder::GenerateMathCos(int argument_count, int ast_id) { ASSERT_EQ(1, argument_count); PushArgumentsForStubCall(argument_count); - HCallStub* instr = + HCallStub* result = new HCallStub(CodeStub::TranscendentalCache, argument_count); - instr->set_transcendental_type(TranscendentalCache::COS); - PushAndAdd(instr, RelocInfo::kNoPosition); + result->set_transcendental_type(TranscendentalCache::COS); + ast_context()->ReturnInstruction(result, ast_id); } -void HGraphBuilder::GenerateMathLog(int argument_count) { +void HGraphBuilder::GenerateMathLog(int argument_count, int ast_id) { ASSERT_EQ(1, argument_count); PushArgumentsForStubCall(argument_count); - HCallStub* instr = + HCallStub* result = new HCallStub(CodeStub::TranscendentalCache, argument_count); - instr->set_transcendental_type(TranscendentalCache::LOG); - PushAndAdd(instr, RelocInfo::kNoPosition); + result->set_transcendental_type(TranscendentalCache::LOG); + ast_context()->ReturnInstruction(result, ast_id); } -void HGraphBuilder::GenerateMathSqrt(int argument_count) { +void HGraphBuilder::GenerateMathSqrt(int argument_count, int ast_id) { BAILOUT("inlined runtime function: MathSqrt"); } // Check whether two RegExps are equivalent -void HGraphBuilder::GenerateIsRegExpEquivalent(int argument_count) { +void HGraphBuilder::GenerateIsRegExpEquivalent(int argument_count, + int ast_id) { BAILOUT("inlined runtime function: IsRegExpEquivalent"); } -void HGraphBuilder::GenerateGetCachedArrayIndex(int argument_count) { +void HGraphBuilder::GenerateGetCachedArrayIndex(int argument_count, + int ast_id) { BAILOUT("inlined runtime function: GetCachedArrayIndex"); } -void HGraphBuilder::GenerateFastAsciiArrayJoin(int argument_count) { +void HGraphBuilder::GenerateFastAsciiArrayJoin(int argument_count, + int ast_id) { BAILOUT("inlined runtime function: FastAsciiArrayJoin"); } diff --git a/deps/v8/src/hydrogen.h b/deps/v8/src/hydrogen.h index 91f3c9e2d63..5611d8da182 100644 --- a/deps/v8/src/hydrogen.h +++ b/deps/v8/src/hydrogen.h @@ -557,10 +557,29 @@ class AstContext { bool IsValue() const { return kind_ == Expression::kValue; } bool IsTest() const { return kind_ == Expression::kTest; } + // 'Fill' this context with a hydrogen value. The value is assumed to + // have already been inserted in the instruction stream (or not need to + // be, e.g., HPhi). Call this function in tail position in the Visit + // functions for expressions. + virtual void ReturnValue(HValue* value) = 0; + + // Add a hydrogen instruction to the instruction stream (recording an + // environment simulation if necessary) and then fill this context with + // the instruction as value. + virtual void ReturnInstruction(HInstruction* instr, int ast_id) = 0; + protected: AstContext(HGraphBuilder* owner, Expression::Context kind); virtual ~AstContext(); + HGraphBuilder* owner() const { return owner_; } + + // We want to be able to assert, in a context-specific way, that the stack + // height makes sense when the context is filled. +#ifdef DEBUG + int original_count_; +#endif + private: HGraphBuilder* owner_; Expression::Context kind_; @@ -573,6 +592,10 @@ class EffectContext: public AstContext { explicit EffectContext(HGraphBuilder* owner) : AstContext(owner, Expression::kEffect) { } + virtual ~EffectContext(); + + virtual void ReturnValue(HValue* value); + virtual void ReturnInstruction(HInstruction* instr, int ast_id); }; @@ -581,6 +604,10 @@ class ValueContext: public AstContext { explicit ValueContext(HGraphBuilder* owner) : AstContext(owner, Expression::kValue) { } + virtual ~ValueContext(); + + virtual void ReturnValue(HValue* value); + virtual void ReturnInstruction(HInstruction* instr, int ast_id); }; @@ -598,6 +625,9 @@ class TestContext: public AstContext { invert_false_(invert_false) { } + virtual void ReturnValue(HValue* value); + virtual void ReturnInstruction(HInstruction* instr, int ast_id); + static TestContext* cast(AstContext* context) { ASSERT(context->IsTest()); return reinterpret_cast<TestContext*>(context); @@ -610,6 +640,10 @@ class TestContext: public AstContext { bool invert_false() { return invert_false_; } private: + // Build the shared core part of the translation unpacking a value into + // control flow. + void BuildBranch(HValue* value); + HBasicBlock* if_true_; HBasicBlock* if_false_; bool invert_true_; @@ -631,9 +665,25 @@ class HGraphBuilder: public AstVisitor { HGraph* CreateGraph(CompilationInfo* info); + // Simple accessors. + HGraph* graph() const { return graph_; } + HSubgraph* subgraph() const { return current_subgraph_; } + + HEnvironment* environment() const { return subgraph()->environment(); } + HBasicBlock* CurrentBlock() const { return subgraph()->exit_block(); } + + // Adding instructions. + HInstruction* AddInstruction(HInstruction* instr); + void AddSimulate(int id); + + // Bailout environment manipulation. + void Push(HValue* value) { environment()->Push(value); } + HValue* Pop() { return environment()->Pop(); } + private: // Type of a member function that generates inline code for a native function. - typedef void (HGraphBuilder::*InlineFunctionGenerator)(int argument_count); + typedef void (HGraphBuilder::*InlineFunctionGenerator)(int argument_count, + int ast_id); // Forward declarations for inner scope classes. class SubgraphScope; @@ -650,19 +700,14 @@ class HGraphBuilder: public AstVisitor { // Simple accessors. TypeFeedbackOracle* oracle() const { return oracle_; } - HGraph* graph() const { return graph_; } - HSubgraph* subgraph() const { return current_subgraph_; } AstContext* ast_context() const { return ast_context_; } void set_ast_context(AstContext* context) { ast_context_ = context; } AstContext* call_context() const { return call_context_; } HBasicBlock* function_return() const { return function_return_; } - HEnvironment* environment() const { return subgraph()->environment(); } - - HBasicBlock* CurrentBlock() const { return subgraph()->exit_block(); } // Generators for inline runtime functions. -#define INLINE_FUNCTION_GENERATOR_DECLARATION(Name, argc, ressize) \ - void Generate##Name(int argument_count); +#define INLINE_FUNCTION_GENERATOR_DECLARATION(Name, argc, ressize) \ + void Generate##Name(int argument_count, int ast_id); INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_DECLARATION) INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_DECLARATION) @@ -683,8 +728,6 @@ class HGraphBuilder: public AstVisitor { HSubgraph* true_graph, HSubgraph* false_graph); - void Push(HValue* value) { environment()->Push(value); } - HValue* Pop() { return environment()->Pop(); } HValue* Top() const { return environment()->Top(); } void Drop(int n) { environment()->Drop(n); } void Bind(Variable* var, HValue* value) { environment()->Bind(var, value); } @@ -708,18 +751,15 @@ class HGraphBuilder: public AstVisitor { HValue* VisitArgument(Expression* expr); void VisitArgumentList(ZoneList<Expression*>* arguments); - HInstruction* AddInstruction(HInstruction* instr); - void AddSimulate(int id); void AddPhi(HPhi* phi); void PushAndAdd(HInstruction* instr); - void PushAndAdd(HInstruction* instr, int position); void PushArgumentsForStubCall(int argument_count); - // Initialize the arguments to the call based on then environment, add it - // to the graph, and drop the arguments from the environment. - void ProcessCall(HCall* call, int source_position); + // Remove the arguments from the bailout environment and emit instructions + // to push them as outgoing parameters. + void ProcessCall(HCall* call); void AssumeRepresentation(HValue* value, Representation r); static Representation ToRepresentation(TypeInfo info); @@ -743,7 +783,7 @@ class HGraphBuilder: public AstVisitor { FunctionLiteral* function); // Helpers for flow graph construction. - void LookupGlobalPropertyCell(VariableProxy* expr, + void LookupGlobalPropertyCell(Variable* var, LookupResult* lookup, bool is_store); @@ -753,10 +793,11 @@ class HGraphBuilder: public AstVisitor { bool TryMathFunctionInline(Call* expr); void TraceInline(Handle<JSFunction> target, bool result); - void HandleGlobalVariableAssignment(VariableProxy* proxy, + void HandleGlobalVariableAssignment(Variable* var, HValue* value, - int position); - void HandleGlobalVariableLoad(VariableProxy* expr); + int position, + int ast_id); + void HandlePropertyAssignment(Assignment* expr); void HandleCompoundAssignment(Assignment* expr); void HandlePolymorphicLoadNamedField(Property* expr, diff --git a/deps/v8/src/ia32/builtins-ia32.cc b/deps/v8/src/ia32/builtins-ia32.cc index c28e1444102..918f346d89c 100644 --- a/deps/v8/src/ia32/builtins-ia32.cc +++ b/deps/v8/src/ia32/builtins-ia32.cc @@ -29,7 +29,6 @@ #if defined(V8_TARGET_ARCH_IA32) -#include "code-stubs.h" #include "codegen-inl.h" #include "deoptimizer.h" #include "full-codegen.h" diff --git a/deps/v8/src/ia32/full-codegen-ia32.cc b/deps/v8/src/ia32/full-codegen-ia32.cc index 1f7095f5780..e538ee4b9f9 100644 --- a/deps/v8/src/ia32/full-codegen-ia32.cc +++ b/deps/v8/src/ia32/full-codegen-ia32.cc @@ -911,7 +911,9 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { __ bind(&update_each); __ mov(result_register(), ebx); // Perform the assignment as if via '='. - EmitAssignment(stmt->each()); + { EffectContext context(this); + EmitAssignment(stmt->each(), stmt->AssignmentId()); + } // Generate code for the body of the loop. Visit(stmt->body()); @@ -1478,7 +1480,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { // For property compound assignments we need another deoptimization // point after the property load. if (property != NULL) { - PrepareForBailoutForId(expr->compound_bailout_id(), TOS_REG); + PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG); } Token::Value op = expr->binary_op(); @@ -1521,6 +1523,8 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { case VARIABLE: EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), expr->op()); + PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); + context()->Plug(eax); break; case NAMED_PROPERTY: EmitNamedPropertyAssignment(expr); @@ -1849,7 +1853,7 @@ void FullCodeGenerator::EmitBinaryOp(Token::Value op, } -void FullCodeGenerator::EmitAssignment(Expression* expr) { +void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) { // Invalid left-hand sides are rewritten to have a 'throw // ReferenceError' on the left-hand side. if (!expr->IsValidLeftHandSide()) { @@ -1897,6 +1901,8 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) { break; } } + PrepareForBailoutForId(bailout_ast_id, TOS_REG); + context()->Plug(eax); } @@ -1969,8 +1975,6 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, } __ bind(&done); } - - context()->Plug(eax); } @@ -2007,10 +2011,10 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { __ push(Operand(esp, kPointerSize)); // Receiver is under value. __ CallRuntime(Runtime::kToFastProperties, 1); __ pop(eax); - context()->DropAndPlug(1, eax); - } else { - context()->Plug(eax); + __ Drop(1); } + PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); + context()->Plug(eax); } @@ -2048,6 +2052,7 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { __ pop(eax); } + PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); context()->Plug(eax); } @@ -3749,6 +3754,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { { EffectContext context(this); EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), Token::ASSIGN); + PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); + context.Plug(eax); } // For all contexts except EffectContext We have the result on // top of the stack. @@ -3759,6 +3766,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { // Perform the assignment as if via '='. EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), Token::ASSIGN); + PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); + context()->Plug(eax); } break; case NAMED_PROPERTY: { @@ -3766,6 +3775,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { __ pop(edx); Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); EmitCallIC(ic, RelocInfo::CODE_TARGET); + PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); if (expr->is_postfix()) { if (!context()->IsEffect()) { context()->PlugTOS(); @@ -3780,6 +3790,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { __ pop(edx); Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); EmitCallIC(ic, RelocInfo::CODE_TARGET); + PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); if (expr->is_postfix()) { // Result is on the stack if (!context()->IsEffect()) { diff --git a/deps/v8/src/ia32/lithium-codegen-ia32.cc b/deps/v8/src/ia32/lithium-codegen-ia32.cc index dc0f5e90f98..b5c0289174e 100644 --- a/deps/v8/src/ia32/lithium-codegen-ia32.cc +++ b/deps/v8/src/ia32/lithium-codegen-ia32.cc @@ -2174,6 +2174,67 @@ void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { } +void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) { + XMMRegister xmm_scratch = xmm0; + XMMRegister input_reg = ToDoubleRegister(instr->input()); + ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); + ExternalReference negative_infinity = + ExternalReference::address_of_negative_infinity(); + __ movdbl(xmm_scratch, Operand::StaticVariable(negative_infinity)); + __ ucomisd(xmm_scratch, input_reg); + DeoptimizeIf(equal, instr->environment()); + __ sqrtsd(input_reg, input_reg); +} + + +void LCodeGen::DoPower(LPower* instr) { + LOperand* left = instr->left(); + LOperand* right = instr->right(); + Representation exponent_type = instr->hydrogen()->right()->representation(); + if (exponent_type.IsDouble()) { + // Pass two doubles as arguments on the stack. + __ PrepareCallCFunction(4, eax); + __ movdbl(Operand(esp, 0 * kDoubleSize), ToDoubleRegister(left)); + __ movdbl(Operand(esp, 1 * kDoubleSize), ToDoubleRegister(right)); + __ CallCFunction(ExternalReference::power_double_double_function(), 4); + } else if (exponent_type.IsInteger32()) { + __ PrepareCallCFunction(4, ebx); + __ movdbl(Operand(esp, 0 * kDoubleSize), ToDoubleRegister(left)); + __ mov(Operand(esp, 1 * kDoubleSize), ToRegister(right)); + __ CallCFunction(ExternalReference::power_double_int_function(), 4); + } else { + ASSERT(exponent_type.IsTagged()); + __ PrepareCallCFunction(4, ebx); + __ movdbl(Operand(esp, 0 * kDoubleSize), ToDoubleRegister(left)); + Register right_reg = ToRegister(right); + Label non_smi; + Label done; + __ test(right_reg, Immediate(kSmiTagMask)); + __ j(not_zero, &non_smi); + __ SmiUntag(right_reg); + __ mov(Operand(esp, 1 * kDoubleSize), ToRegister(right)); + __ CallCFunction(ExternalReference::power_double_int_function(), 4); + __ jmp(&done); + + __ bind(&non_smi); + __ CmpObjectType(right_reg, HEAP_NUMBER_TYPE , ebx); + DeoptimizeIf(not_equal, instr->environment()); + __ movdbl(xmm1, FieldOperand(right_reg, HeapNumber::kValueOffset)); + __ movdbl(Operand(esp, 1 * kDoubleSize), xmm1); + __ CallCFunction(ExternalReference::power_double_double_function(), 4); + + __ bind(&done); + } + + // Return value is in st(0) on ia32. + // Store it into the (fixed) result register. + __ sub(Operand(esp), Immediate(kDoubleSize)); + __ fstp_d(Operand(esp, 0)); + __ movdbl(ToDoubleRegister(instr->result()), Operand(esp, 0)); + __ add(Operand(esp), Immediate(kDoubleSize)); +} + + void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) { switch (instr->op()) { case kMathAbs: @@ -2188,6 +2249,9 @@ void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) { case kMathSqrt: DoMathSqrt(instr); break; + case kMathPowHalf: + DoMathPowHalf(instr); + break; default: UNREACHABLE(); } diff --git a/deps/v8/src/ia32/lithium-codegen-ia32.h b/deps/v8/src/ia32/lithium-codegen-ia32.h index 91b3fabca3d..ca4e9b3fae4 100644 --- a/deps/v8/src/ia32/lithium-codegen-ia32.h +++ b/deps/v8/src/ia32/lithium-codegen-ia32.h @@ -175,6 +175,7 @@ class LCodeGen BASE_EMBEDDED { void DoMathFloor(LUnaryMathOperation* instr); void DoMathRound(LUnaryMathOperation* instr); void DoMathSqrt(LUnaryMathOperation* instr); + void DoMathPowHalf(LUnaryMathOperation* instr); // Support for recording safepoint and position information. void RecordSafepoint(LPointerMap* pointers, int deoptimization_index); diff --git a/deps/v8/src/ia32/lithium-ia32.cc b/deps/v8/src/ia32/lithium-ia32.cc index e3a3d7bcb02..1f9714357e2 100644 --- a/deps/v8/src/ia32/lithium-ia32.cc +++ b/deps/v8/src/ia32/lithium-ia32.cc @@ -460,12 +460,6 @@ int LChunk::NearestGapPos(int index) const { } -int LChunk::NearestNextGapPos(int index) const { - while (!IsGapAt(index)) index++; - return index; -} - - void LChunk::AddGapMove(int index, LOperand* from, LOperand* to) { GetGapAt(index)->GetOrCreateParallelMove(LGap::START)->AddMove(from, to); } @@ -1372,6 +1366,8 @@ LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) { return AssignEnvironment(DefineAsRegister(result)); case kMathSqrt: return DefineSameAsFirst(result); + case kMathPowHalf: + return AssignEnvironment(DefineSameAsFirst(result)); default: UNREACHABLE(); return NULL; @@ -1572,6 +1568,22 @@ LInstruction* LChunkBuilder::DoAdd(HAdd* instr) { } +LInstruction* LChunkBuilder::DoPower(HPower* instr) { + ASSERT(instr->representation().IsDouble()); + // We call a C function for double power. It can't trigger a GC. + // We need to use fixed result register for the call. + Representation exponent_type = instr->right()->representation(); + ASSERT(instr->left()->representation().IsDouble()); + LOperand* left = UseFixedDouble(instr->left(), xmm1); + LOperand* right = exponent_type.IsDouble() ? + UseFixedDouble(instr->right(), xmm2) : + UseFixed(instr->right(), eax); + LPower* result = new LPower(left, right); + return MarkAsCall(DefineFixedDouble(result, xmm1), instr, + CAN_DEOPTIMIZE_EAGERLY); +} + + LInstruction* LChunkBuilder::DoCompare(HCompare* instr) { Token::Value op = instr->token(); if (instr->left()->representation().IsInteger32()) { diff --git a/deps/v8/src/ia32/lithium-ia32.h b/deps/v8/src/ia32/lithium-ia32.h index af0d5604ddc..c97859cfc90 100644 --- a/deps/v8/src/ia32/lithium-ia32.h +++ b/deps/v8/src/ia32/lithium-ia32.h @@ -67,6 +67,7 @@ class LGapNode; // LLoadKeyedGeneric // LModI // LMulI +// LPower // LShiftI // LSubI // LCallConstantFunction @@ -229,6 +230,7 @@ class LGapNode; V(ObjectLiteral) \ V(OsrEntry) \ V(Parameter) \ + V(Power) \ V(PushArgument) \ V(RegExpLiteral) \ V(Return) \ @@ -1154,6 +1156,16 @@ class LAddI: public LBinaryOperation { }; +class LPower: public LBinaryOperation { + public: + LPower(LOperand* left, LOperand* right) + : LBinaryOperation(left, right) { } + + DECLARE_CONCRETE_INSTRUCTION(Power, "power") + DECLARE_HYDROGEN_ACCESSOR(Power) +}; + + class LArithmeticD: public LBinaryOperation { public: LArithmeticD(Token::Value op, LOperand* left, LOperand* right) @@ -1890,7 +1902,6 @@ class LChunk: public ZoneObject { LGap* GetGapAt(int index) const; bool IsGapAt(int index) const; int NearestGapPos(int index) const; - int NearestNextGapPos(int index) const; void MarkEmptyBlocks(); const ZoneList<LPointerMap*>* pointer_maps() const { return &pointer_maps_; } LLabel* GetLabel(int block_id) const { diff --git a/deps/v8/src/ia32/macro-assembler-ia32.cc b/deps/v8/src/ia32/macro-assembler-ia32.cc index 84911ecec5d..6c51d6859c2 100644 --- a/deps/v8/src/ia32/macro-assembler-ia32.cc +++ b/deps/v8/src/ia32/macro-assembler-ia32.cc @@ -1216,25 +1216,29 @@ MaybeObject* MacroAssembler::TryTailCallRuntime(Runtime::FunctionId fid, } -// If true, a Handle<T> passed by value is passed and returned by -// using the location_ field directly. If false, it is passed and -// returned as a pointer to a handle. -#ifdef USING_BSD_ABI -static const bool kPassHandlesDirectly = true; +// If true, a Handle<T> returned by value from a function with cdecl calling +// convention will be returned directly as a value of location_ field in a +// register eax. +// If false, it is returned as a pointer to a preallocated by caller memory +// region. Pointer to this region should be passed to a function as an +// implicit first argument. +#if defined(USING_BSD_ABI) || defined(__MINGW32__) +static const bool kReturnHandlesDirectly = true; #else -static const bool kPassHandlesDirectly = false; +static const bool kReturnHandlesDirectly = false; #endif Operand ApiParameterOperand(int index) { - return Operand(esp, (index + (kPassHandlesDirectly ? 0 : 1)) * kPointerSize); + return Operand( + esp, (index + (kReturnHandlesDirectly ? 0 : 1)) * kPointerSize); } void MacroAssembler::PrepareCallApiFunction(int argc, Register scratch) { - if (kPassHandlesDirectly) { + if (kReturnHandlesDirectly) { EnterApiExitFrame(argc); - // When handles as passed directly we don't have to allocate extra + // When handles are returned directly we don't have to allocate extra // space for and pass an out parameter. } else { // We allocate two additional slots: return value and pointer to it. @@ -1279,7 +1283,7 @@ MaybeObject* MacroAssembler::TryCallApiFunctionAndReturn(ApiFunction* function, // Call the api function! call(function->address(), RelocInfo::RUNTIME_ENTRY); - if (!kPassHandlesDirectly) { + if (!kReturnHandlesDirectly) { // The returned value is a pointer to the handle holding the result. // Dereference this to get to the location. mov(eax, Operand(eax, 0)); diff --git a/deps/v8/src/json.js b/deps/v8/src/json.js index e8b732a52aa..c0af9d0e463 100644 --- a/deps/v8/src/json.js +++ b/deps/v8/src/json.js @@ -66,21 +66,10 @@ function JSONParse(text, reviver) { } } -function StackContains(stack, val) { - var length = stack.length; - for (var i = 0; i < length; i++) { - if (stack[i] === val) { - return true; - } - } - return false; -} - function SerializeArray(value, replacer, stack, indent, gap) { - if (StackContains(stack, value)) { + if (!%PushIfAbsent(stack, value)) { throw MakeTypeError('circular_structure', []); } - stack.push(value); var stepback = indent; indent += gap; var partial = []; @@ -108,10 +97,9 @@ function SerializeArray(value, replacer, stack, indent, gap) { } function SerializeObject(value, replacer, stack, indent, gap) { - if (StackContains(stack, value)) { + if (!%PushIfAbsent(stack, value)) { throw MakeTypeError('circular_structure', []); } - stack.push(value); var stepback = indent; indent += gap; var partial = []; @@ -197,10 +185,9 @@ function JSONSerialize(key, holder, replacer, stack, indent, gap) { function BasicSerializeArray(value, stack, builder) { - if (StackContains(stack, value)) { + if (!%PushIfAbsent(stack, value)) { throw MakeTypeError('circular_structure', []); } - stack.push(value); builder.push("["); var len = value.length; for (var i = 0; i < len; i++) { @@ -220,10 +207,9 @@ function BasicSerializeArray(value, stack, builder) { function BasicSerializeObject(value, stack, builder) { - if (StackContains(stack, value)) { + if (!%PushIfAbsent(stack, value)) { throw MakeTypeError('circular_structure', []); } - stack.push(value); builder.push("{"); for (var p in value) { if (%HasLocalProperty(value, p)) { diff --git a/deps/v8/src/lithium-allocator.cc b/deps/v8/src/lithium-allocator.cc index db0bc8b72d2..513a67c7c83 100644 --- a/deps/v8/src/lithium-allocator.cc +++ b/deps/v8/src/lithium-allocator.cc @@ -247,7 +247,7 @@ LOperand* LiveRange::CreateAssignedOperand() { LOperand* op = NULL; if (HasRegisterAssigned()) { ASSERT(!IsSpilled()); - if (assigned_double_) { + if (IsDouble()) { op = LDoubleRegister::Create(assigned_register()); } else { op = LRegister::Create(assigned_register()); @@ -290,7 +290,7 @@ void LiveRange::AdvanceLastProcessedMarker( void LiveRange::SplitAt(LifetimePosition position, LiveRange* result) { - ASSERT(Start().Value() <= position.Value()); + ASSERT(Start().Value() < position.Value()); ASSERT(result->IsEmpty()); // Find the last interval that ends before the position. If the // position is contained in one of the intervals in the chain, we @@ -625,7 +625,7 @@ LiveRange* LAllocator::FixedLiveRangeFor(int index) { if (result == NULL) { result = new LiveRange(FixedLiveRangeID(index)); ASSERT(result->IsFixed()); - result->set_assigned_register(index, false); + result->set_assigned_register(index, GENERAL_REGISTERS); fixed_live_ranges_[index] = result; } return result; @@ -642,7 +642,7 @@ LiveRange* LAllocator::FixedDoubleLiveRangeFor(int index) { if (result == NULL) { result = new LiveRange(FixedDoubleLiveRangeID(index)); ASSERT(result->IsFixed()); - result->set_assigned_register(index, true); + result->set_assigned_register(index, DOUBLE_REGISTERS); fixed_double_live_ranges_[index] = result; } return result; @@ -1258,14 +1258,6 @@ void LAllocator::BuildLiveRanges() { } -void LAllocator::AllocateGeneralRegisters() { - HPhase phase("Allocate general registers", this); - num_registers_ = Register::kNumAllocatableRegisters; - mode_ = CPU_REGISTERS; - AllocateRegisters(); -} - - bool LAllocator::SafePointsAreInOrder() const { const ZoneList<LPointerMap*>* pointer_maps = chunk_->pointer_maps(); int safe_point = 0; @@ -1397,10 +1389,18 @@ void LAllocator::ProcessOsrEntry() { } +void LAllocator::AllocateGeneralRegisters() { + HPhase phase("Allocate general registers", this); + num_registers_ = Register::kNumAllocatableRegisters; + mode_ = GENERAL_REGISTERS; + AllocateRegisters(); +} + + void LAllocator::AllocateDoubleRegisters() { HPhase phase("Allocate double registers", this); num_registers_ = DoubleRegister::kNumAllocatableRegisters; - mode_ = XMM_REGISTERS; + mode_ = DOUBLE_REGISTERS; AllocateRegisters(); } @@ -1411,7 +1411,7 @@ void LAllocator::AllocateRegisters() { for (int i = 0; i < live_ranges_.length(); ++i) { if (live_ranges_[i] != NULL) { - if (HasDoubleValue(live_ranges_[i]->id()) == (mode_ == XMM_REGISTERS)) { + if (RequiredRegisterKind(live_ranges_[i]->id()) == mode_) { AddToUnhandledUnsorted(live_ranges_[i]); } } @@ -1422,7 +1422,7 @@ void LAllocator::AllocateRegisters() { ASSERT(active_live_ranges_.is_empty()); ASSERT(inactive_live_ranges_.is_empty()); - if (mode_ == XMM_REGISTERS) { + if (mode_ == DOUBLE_REGISTERS) { for (int i = 0; i < fixed_double_live_ranges_.length(); ++i) { LiveRange* current = fixed_double_live_ranges_.at(i); if (current != NULL) { @@ -1463,11 +1463,7 @@ void LAllocator::AllocateRegisters() { current->Start().NextInstruction().Value()) { // Do not spill live range eagerly if use position that can benefit from // the register is too close to the start of live range. - LiveRange* part = Split(current, - current->Start().NextInstruction(), - pos->pos()); - Spill(current); - AddToUnhandledSorted(part); + SpillBetween(current, current->Start(), pos->pos()); ASSERT(UnhandledIsSorted()); continue; } @@ -1521,6 +1517,16 @@ void LAllocator::Setup() { } +const char* LAllocator::RegisterName(int allocation_index) { + ASSERT(mode_ != NONE); + if (mode_ == GENERAL_REGISTERS) { + return Register::AllocationIndexToString(allocation_index); + } else { + return DoubleRegister::AllocationIndexToString(allocation_index); + } +} + + void LAllocator::TraceAlloc(const char* msg, ...) { if (FLAG_trace_alloc) { va_list arguments; @@ -1544,10 +1550,12 @@ bool LAllocator::HasTaggedValue(int virtual_register) const { } -bool LAllocator::HasDoubleValue(int virtual_register) const { +RegisterKind LAllocator::RequiredRegisterKind(int virtual_register) const { HValue* value = graph()->LookupValue(virtual_register); - if (value == NULL) return false; - return value->representation().IsDouble(); + if (value != NULL && value->representation().IsDouble()) { + return DOUBLE_REGISTERS; + } + return GENERAL_REGISTERS; } @@ -1728,16 +1736,22 @@ void LAllocator::InactiveToActive(LiveRange* range) { } +// TryAllocateFreeReg and AllocateBlockedReg assume this +// when allocating local arrays. +STATIC_ASSERT(DoubleRegister::kNumAllocatableRegisters >= + Register::kNumAllocatableRegisters); + + bool LAllocator::TryAllocateFreeReg(LiveRange* current) { - LifetimePosition max_pos = LifetimePosition::FromInstructionIndex( - chunk_->instructions()->length() + 1); - ASSERT(DoubleRegister::kNumAllocatableRegisters >= - Register::kNumAllocatableRegisters); - EmbeddedVector<LifetimePosition, DoubleRegister::kNumAllocatableRegisters> - free_pos(max_pos); + LifetimePosition free_until_pos[DoubleRegister::kNumAllocatableRegisters]; + + for (int i = 0; i < DoubleRegister::kNumAllocatableRegisters; i++) { + free_until_pos[i] = LifetimePosition::MaxPosition(); + } + for (int i = 0; i < active_live_ranges_.length(); ++i) { LiveRange* cur_active = active_live_ranges_.at(i); - free_pos[cur_active->assigned_register()] = + free_until_pos[cur_active->assigned_register()] = LifetimePosition::FromInstructionIndex(0); } @@ -1748,67 +1762,83 @@ bool LAllocator::TryAllocateFreeReg(LiveRange* current) { cur_inactive->FirstIntersection(current); if (!next_intersection.IsValid()) continue; int cur_reg = cur_inactive->assigned_register(); - free_pos[cur_reg] = Min(free_pos[cur_reg], next_intersection); + free_until_pos[cur_reg] = Min(free_until_pos[cur_reg], next_intersection); } - UsePosition* pos = current->FirstPosWithHint(); - if (pos != NULL) { - LOperand* hint = pos->hint(); + UsePosition* hinted_use = current->FirstPosWithHint(); + if (hinted_use != NULL) { + LOperand* hint = hinted_use->hint(); if (hint->IsRegister() || hint->IsDoubleRegister()) { int register_index = hint->index(); - TraceAlloc("Found reg hint %d for live range %d (free [%d, end %d[)\n", - register_index, - current->id(), - free_pos[register_index].Value(), - current->End().Value()); - if (free_pos[register_index].Value() >= current->End().Value()) { - TraceAlloc("Assigning preferred reg %d to live range %d\n", - register_index, + TraceAlloc( + "Found reg hint %s (free until [%d) for live range %d (end %d[).\n", + RegisterName(register_index), + free_until_pos[register_index].Value(), + current->id(), + current->End().Value()); + + // The desired register is free until the end of the current live range. + if (free_until_pos[register_index].Value() >= current->End().Value()) { + TraceAlloc("Assigning preferred reg %s to live range %d\n", + RegisterName(register_index), current->id()); - current->set_assigned_register(register_index, mode_ == XMM_REGISTERS); + current->set_assigned_register(register_index, mode_); return true; } } } - int max_reg = 0; + // Find the register which stays free for the longest time. + int reg = 0; for (int i = 1; i < RegisterCount(); ++i) { - if (free_pos[i].Value() > free_pos[max_reg].Value()) { - max_reg = i; + if (free_until_pos[i].Value() > free_until_pos[reg].Value()) { + reg = i; } } - if (free_pos[max_reg].InstructionIndex() == 0) { + LifetimePosition pos = free_until_pos[reg]; + + if (pos.Value() <= current->Start().Value()) { + // All registers are blocked. return false; - } else if (free_pos[max_reg].Value() >= current->End().Value()) { - TraceAlloc("Assigning reg %d to live range %d\n", max_reg, current->id()); - current->set_assigned_register(max_reg, mode_ == XMM_REGISTERS); - } else { - // Split the interval at the nearest gap and never split an interval at its - // start position. - LifetimePosition pos = - LifetimePosition::FromInstructionIndex( - chunk_->NearestGapPos(free_pos[max_reg].InstructionIndex())); - if (pos.Value() <= current->Start().Value()) return false; - LiveRange* second_range = Split(current, pos); - AddToUnhandledSorted(second_range); - current->set_assigned_register(max_reg, mode_ == XMM_REGISTERS); } + if (pos.Value() < current->End().Value()) { + // Register reg is available at the range start but becomes blocked before + // the range end. Split current at position where it becomes blocked. + LiveRange* tail = SplitAt(current, pos); + AddToUnhandledSorted(tail); + } + + + // Register reg is available at the range start and is free until + // the range end. + ASSERT(pos.Value() >= current->End().Value()); + TraceAlloc("Assigning reg %s to live range %d\n", + RegisterName(reg), + current->id()); + current->set_assigned_register(reg, mode_); + return true; } void LAllocator::AllocateBlockedReg(LiveRange* current) { - LifetimePosition max_pos = - LifetimePosition::FromInstructionIndex( - chunk_->instructions()->length() + 1); - ASSERT(DoubleRegister::kNumAllocatableRegisters >= - Register::kNumAllocatableRegisters); - EmbeddedVector<LifetimePosition, DoubleRegister::kNumAllocatableRegisters> - use_pos(max_pos); - EmbeddedVector<LifetimePosition, DoubleRegister::kNumAllocatableRegisters> - block_pos(max_pos); + UsePosition* register_use = current->NextRegisterPosition(current->Start()); + if (register_use == NULL) { + // There is no use in the current live range that requires a register. + // We can just spill it. + Spill(current); + return; + } + + + LifetimePosition use_pos[DoubleRegister::kNumAllocatableRegisters]; + LifetimePosition block_pos[DoubleRegister::kNumAllocatableRegisters]; + + for (int i = 0; i < DoubleRegister::kNumAllocatableRegisters; i++) { + use_pos[i] = block_pos[i] = LifetimePosition::MaxPosition(); + } for (int i = 0; i < active_live_ranges_.length(); ++i) { LiveRange* range = active_live_ranges_[i]; @@ -1841,47 +1871,63 @@ void LAllocator::AllocateBlockedReg(LiveRange* current) { } } - int max_reg = 0; + int reg = 0; for (int i = 1; i < RegisterCount(); ++i) { - if (use_pos[i].Value() > use_pos[max_reg].Value()) { - max_reg = i; + if (use_pos[i].Value() > use_pos[reg].Value()) { + reg = i; } } - UsePosition* first_usage = current->NextRegisterPosition(current->Start()); - if (first_usage == NULL) { - Spill(current); - } else if (use_pos[max_reg].Value() < first_usage->pos().Value()) { - SplitAndSpill(current, current->Start(), first_usage->pos()); - } else { - if (block_pos[max_reg].Value() < current->End().Value()) { - // Split current before blocked position. - LiveRange* second_range = Split(current, - current->Start(), - block_pos[max_reg]); - AddToUnhandledSorted(second_range); - } + LifetimePosition pos = use_pos[reg]; + + if (pos.Value() < register_use->pos().Value()) { + // All registers are blocked before the first use that requires a register. + // Spill starting part of live range up to that use. + // + // Corner case: the first use position is equal to the start of the range. + // In this case we have nothing to spill and SpillBetween will just return + // this range to the list of unhandled ones. This will lead to the infinite + // loop. + ASSERT(current->Start().Value() < register_use->pos().Value()); + SpillBetween(current, current->Start(), register_use->pos()); + return; + } - current->set_assigned_register(max_reg, mode_ == XMM_REGISTERS); - SplitAndSpillIntersecting(current); + if (block_pos[reg].Value() < current->End().Value()) { + // Register becomes blocked before the current range end. Split before that + // position. + LiveRange* tail = SplitBetween(current, + current->Start(), + block_pos[reg].InstructionStart()); + AddToUnhandledSorted(tail); } + + // Register reg is not blocked for the whole range. + ASSERT(block_pos[reg].Value() >= current->End().Value()); + TraceAlloc("Assigning reg %s to live range %d\n", + RegisterName(reg), + current->id()); + current->set_assigned_register(reg, mode_); + + // This register was not free. Thus we need to find and spill + // parts of active and inactive live regions that use the same register + // at the same lifetime positions as current. + SplitAndSpillIntersecting(current); } void LAllocator::SplitAndSpillIntersecting(LiveRange* current) { ASSERT(current->HasRegisterAssigned()); int reg = current->assigned_register(); - LifetimePosition split_pos = - LifetimePosition::FromInstructionIndex( - chunk_->NearestGapPos(current->Start().InstructionIndex())); + LifetimePosition split_pos = current->Start(); for (int i = 0; i < active_live_ranges_.length(); ++i) { LiveRange* range = active_live_ranges_[i]; if (range->assigned_register() == reg) { UsePosition* next_pos = range->NextRegisterPosition(current->Start()); if (next_pos == NULL) { - SplitAndSpill(range, split_pos); + SpillAfter(range, split_pos); } else { - SplitAndSpill(range, split_pos, next_pos->pos()); + SpillBetween(range, split_pos, next_pos->pos()); } ActiveToHandled(range); --i; @@ -1896,10 +1942,10 @@ void LAllocator::SplitAndSpillIntersecting(LiveRange* current) { if (next_intersection.IsValid()) { UsePosition* next_pos = range->NextRegisterPosition(current->Start()); if (next_pos == NULL) { - SplitAndSpill(range, split_pos); + SpillAfter(range, split_pos); } else { next_intersection = Min(next_intersection, next_pos->pos()); - SplitAndSpill(range, split_pos, next_intersection); + SpillBetween(range, split_pos, next_intersection); } InactiveToHandled(range); --i; @@ -1909,19 +1955,50 @@ void LAllocator::SplitAndSpillIntersecting(LiveRange* current) { } -LiveRange* LAllocator::Split(LiveRange* range, - LifetimePosition start, - LifetimePosition end) { +bool LAllocator::IsBlockBoundary(LifetimePosition pos) { + return pos.IsInstructionStart() && + chunk_->instructions()->at(pos.InstructionIndex())->IsLabel(); +} + + +void LAllocator::AddGapMove(int pos, LiveRange* prev, LiveRange* next) { + UsePosition* prev_pos = prev->AddUsePosition( + LifetimePosition::FromInstructionIndex(pos)); + UsePosition* next_pos = next->AddUsePosition( + LifetimePosition::FromInstructionIndex(pos)); + LOperand* prev_operand = prev_pos->operand(); + LOperand* next_operand = next_pos->operand(); + LGap* gap = chunk_->GetGapAt(pos); + gap->GetOrCreateParallelMove(LGap::START)-> + AddMove(prev_operand, next_operand); + next_pos->set_hint(prev_operand); +} + + +LiveRange* LAllocator::SplitAt(LiveRange* range, LifetimePosition pos) { + ASSERT(!range->IsFixed()); + TraceAlloc("Splitting live range %d at %d\n", range->id(), pos.Value()); + + if (pos.Value() <= range->Start().Value()) return range; + + LiveRange* result = LiveRangeFor(next_virtual_register_++); + range->SplitAt(pos, result); + return result; +} + + +LiveRange* LAllocator::SplitBetween(LiveRange* range, + LifetimePosition start, + LifetimePosition end) { ASSERT(!range->IsFixed()); - TraceAlloc("Splitting live range %d in position between [%d, %d[\n", + TraceAlloc("Splitting live range %d in position between [%d, %d]\n", range->id(), start.Value(), end.Value()); - LifetimePosition split_pos = FindOptimalSplitPos( - start, end.PrevInstruction().InstructionEnd()); + LifetimePosition split_pos = FindOptimalSplitPos(start, end); ASSERT(split_pos.Value() >= start.Value()); - return Split(range, split_pos); + return SplitAt(range, split_pos); } @@ -1944,81 +2021,52 @@ LifetimePosition LAllocator::FindOptimalSplitPos(LifetimePosition start, } HBasicBlock* block = end_block; - // Move to the most outside loop header. + // Find header of outermost loop. while (block->parent_loop_header() != NULL && block->parent_loop_header()->block_id() > start_block->block_id()) { block = block->parent_loop_header(); } - if (block == end_block) { - return end; - } + if (block == end_block) return end; return LifetimePosition::FromInstructionIndex( block->first_instruction_index()); } -bool LAllocator::IsBlockBoundary(LifetimePosition pos) { - return pos.IsInstructionStart() && - chunk_->instructions()->at(pos.InstructionIndex())->IsLabel(); +void LAllocator::SpillAfter(LiveRange* range, LifetimePosition pos) { + LiveRange* second_part = SplitAt(range, pos); + Spill(second_part); } -void LAllocator::AddGapMove(int pos, LiveRange* prev, LiveRange* next) { - UsePosition* prev_pos = prev->AddUsePosition( - LifetimePosition::FromInstructionIndex(pos)); - UsePosition* next_pos = next->AddUsePosition( - LifetimePosition::FromInstructionIndex(pos)); - LOperand* prev_operand = prev_pos->operand(); - LOperand* next_operand = next_pos->operand(); - LGap* gap = chunk_->GetGapAt(pos); - gap->GetOrCreateParallelMove(LGap::START)-> - AddMove(prev_operand, next_operand); - next_pos->set_hint(prev_operand); -} - +void LAllocator::SpillBetween(LiveRange* range, + LifetimePosition start, + LifetimePosition end) { + ASSERT(start.Value() < end.Value()); + LiveRange* second_part = SplitAt(range, start); -LiveRange* LAllocator::Split(LiveRange* range, LifetimePosition pos) { - ASSERT(!range->IsFixed()); - TraceAlloc("Splitting live range %d at %d\n", range->id(), pos.Value()); - if (pos.Value() <= range->Start().Value()) { - return range; - } - LiveRange* result = LiveRangeFor(next_virtual_register_++); - range->SplitAt(pos, result); - return result; -} + if (second_part->Start().Value() < end.Value()) { + // The split result intersects with [start, end[. + // Split it at position between ]start+1, end[, spill the middle part + // and put the rest to unhandled. + LiveRange* third_part = SplitBetween( + second_part, + second_part->Start().InstructionEnd(), + end.PrevInstruction().InstructionEnd()); + ASSERT(third_part != second_part); -void LAllocator::SplitAndSpill(LiveRange* range, - LifetimePosition start, - LifetimePosition end) { - // We have an interval range and want to make sure that it is - // spilled at start and at most spilled until end. - ASSERT(start.Value() < end.Value()); - LiveRange* tail_part = Split(range, start); - if (tail_part->Start().Value() < end.Value()) { - LiveRange* third_part = Split(tail_part, - tail_part->Start().NextInstruction(), - end); - Spill(tail_part); - ASSERT(third_part != tail_part); + Spill(second_part); AddToUnhandledSorted(third_part); } else { - AddToUnhandledSorted(tail_part); + // The split result does not intersect with [start, end[. + // Nothing to spill. Just put it to unhandled as whole. + AddToUnhandledSorted(second_part); } } -void LAllocator::SplitAndSpill(LiveRange* range, LifetimePosition at) { - at = LifetimePosition::FromInstructionIndex( - chunk_->NearestGapPos(at.InstructionIndex())); - LiveRange* second_part = Split(range, at); - Spill(second_part); -} - - void LAllocator::Spill(LiveRange* range) { ASSERT(!range->IsSpilled()); TraceAlloc("Spilling live range %d\n", range->id()); @@ -2026,7 +2074,7 @@ void LAllocator::Spill(LiveRange* range) { if (!first->HasAllocatedSpillOperand()) { LOperand* op = TryReuseSpillSlot(range); - if (op == NULL) op = chunk_->GetNextSpillSlot(mode_ == XMM_REGISTERS); + if (op == NULL) op = chunk_->GetNextSpillSlot(mode_ == DOUBLE_REGISTERS); first->SetSpillOperand(op); } range->MakeSpilled(); diff --git a/deps/v8/src/lithium-allocator.h b/deps/v8/src/lithium-allocator.h index 52fee6455f9..3ec984e262f 100644 --- a/deps/v8/src/lithium-allocator.h +++ b/deps/v8/src/lithium-allocator.h @@ -55,6 +55,7 @@ class LPointerMap; class LStackSlot; class LRegister; + // This class represents a single point of a LOperand's lifetime. // For each lithium instruction there are exactly two lifetime positions: // the beginning and the end of the instruction. Lifetime positions for @@ -121,7 +122,13 @@ class LifetimePosition { // instruction. bool IsValid() const { return value_ != -1; } - static LifetimePosition Invalid() { return LifetimePosition(); } + static inline LifetimePosition Invalid() { return LifetimePosition(); } + + static inline LifetimePosition MaxPosition() { + // We have to use this kind of getter instead of static member due to + // crash bug in GDB. + return LifetimePosition(kMaxInt); + } private: static const int kStep = 2; @@ -135,6 +142,13 @@ class LifetimePosition { }; +enum RegisterKind { + NONE, + GENERAL_REGISTERS, + DOUBLE_REGISTERS +}; + + class LOperand: public ZoneObject { public: enum Kind { @@ -594,8 +608,8 @@ class LiveRange: public ZoneObject { explicit LiveRange(int id) : id_(id), spilled_(false), - assigned_double_(false), assigned_register_(kInvalidAssignment), + assigned_register_kind_(NONE), last_interval_(NULL), first_interval_(NULL), first_pos_(NULL), @@ -620,10 +634,10 @@ class LiveRange: public ZoneObject { LOperand* CreateAssignedOperand(); int assigned_register() const { return assigned_register_; } int spill_start_index() const { return spill_start_index_; } - void set_assigned_register(int reg, bool double_reg) { + void set_assigned_register(int reg, RegisterKind register_kind) { ASSERT(!HasRegisterAssigned() && !IsSpilled()); assigned_register_ = reg; - assigned_double_ = double_reg; + assigned_register_kind_ = register_kind; ConvertOperands(); } void MakeSpilled() { @@ -652,9 +666,13 @@ class LiveRange: public ZoneObject { // Can this live range be spilled at this position. bool CanBeSpilled(LifetimePosition pos); + // Split this live range at the given position which must follow the start of + // the range. + // All uses following the given position will be moved from this + // live range to the result live range. void SplitAt(LifetimePosition position, LiveRange* result); - bool IsDouble() const { return assigned_double_; } + bool IsDouble() const { return assigned_register_kind_ == DOUBLE_REGISTERS; } bool HasRegisterAssigned() const { return assigned_register_ != kInvalidAssignment; } @@ -721,8 +739,8 @@ class LiveRange: public ZoneObject { int id_; bool spilled_; - bool assigned_double_; int assigned_register_; + RegisterKind assigned_register_kind_; UseInterval* last_interval_; UseInterval* first_interval_; UsePosition* first_pos_; @@ -774,8 +792,8 @@ class LAllocator BASE_EMBEDDED { // Checks whether the value of a given virtual register is tagged. bool HasTaggedValue(int virtual_register) const; - // Checks whether the value of a given virtual register is a double. - bool HasDoubleValue(int virtual_register) const; + // Returns the register kind required by the given virtual register. + RegisterKind RequiredRegisterKind(int virtual_register) const; // Begin a new instruction. void BeginInstruction(); @@ -814,12 +832,6 @@ class LAllocator BASE_EMBEDDED { #endif private: - enum OperationMode { - NONE, - CPU_REGISTERS, - XMM_REGISTERS - }; - void MeetRegisterConstraints(); void ResolvePhis(); void BuildLiveRanges(); @@ -871,17 +883,38 @@ class LAllocator BASE_EMBEDDED { // Helper methods for allocating registers. bool TryAllocateFreeReg(LiveRange* range); void AllocateBlockedReg(LiveRange* range); - void SplitAndSpillIntersecting(LiveRange* range); + + // Live range splitting helpers. + + // Split the given range at the given position. + // If range starts at or after the given position then the + // original range is returned. + // Otherwise returns the live range that starts at pos and contains + // all uses from the original range that follow pos. Uses at pos will + // still be owned by the original range after splitting. + LiveRange* SplitAt(LiveRange* range, LifetimePosition pos); + + // Split the given range in a position from the interval [start, end]. + LiveRange* SplitBetween(LiveRange* range, + LifetimePosition start, + LifetimePosition end); + + // Find a lifetime position in the interval [start, end] which + // is optimal for splitting: it is either header of the outermost + // loop covered by this interval or the latest possible position. LifetimePosition FindOptimalSplitPos(LifetimePosition start, LifetimePosition end); - LiveRange* Split(LiveRange* range, - LifetimePosition start, - LifetimePosition end); - LiveRange* Split(LiveRange* range, LifetimePosition split_pos); - void SplitAndSpill(LiveRange* range, - LifetimePosition start, - LifetimePosition end); - void SplitAndSpill(LiveRange* range, LifetimePosition at); + + // Spill the given life range after position pos. + void SpillAfter(LiveRange* range, LifetimePosition pos); + + // Spill the given life range after position start and up to position end. + void SpillBetween(LiveRange* range, + LifetimePosition start, + LifetimePosition end); + + void SplitAndSpillIntersecting(LiveRange* range); + void Spill(LiveRange* range); bool IsBlockBoundary(LifetimePosition pos); void AddGapMove(int pos, LiveRange* prev, LiveRange* next); @@ -914,6 +947,8 @@ class LAllocator BASE_EMBEDDED { HPhi* LookupPhi(LOperand* operand) const; LGap* GetLastGap(HBasicBlock* block) const; + const char* RegisterName(int allocation_index); + LChunk* chunk_; ZoneList<InstructionSummary*> summaries_; InstructionSummary* next_summary_; @@ -938,7 +973,7 @@ class LAllocator BASE_EMBEDDED { // Next virtual register number to be assigned to temporaries. int next_virtual_register_; - OperationMode mode_; + RegisterKind mode_; int num_registers_; HGraph* graph_; diff --git a/deps/v8/src/log-utils.cc b/deps/v8/src/log-utils.cc index d6d8754b23e..c7b75679ea9 100644 --- a/deps/v8/src/log-utils.cc +++ b/deps/v8/src/log-utils.cc @@ -273,29 +273,7 @@ void LogMessageBuilder::Append(String* str) { void LogMessageBuilder::AppendAddress(Address addr) { - static Address last_address_ = NULL; - AppendAddress(addr, last_address_); - last_address_ = addr; -} - - -void LogMessageBuilder::AppendAddress(Address addr, Address bias) { - if (!FLAG_compress_log) { - Append("0x%" V8PRIxPTR, addr); - } else if (bias == NULL) { - Append("%" V8PRIxPTR, addr); - } else { - uintptr_t delta; - char sign; - if (addr >= bias) { - delta = addr - bias; - sign = '+'; - } else { - delta = bias - addr; - sign = '-'; - } - Append("%c%" V8PRIxPTR, sign, delta); - } + Append("0x%" V8PRIxPTR, addr); } @@ -343,24 +321,6 @@ void LogMessageBuilder::AppendStringPart(const char* str, int len) { } -bool LogMessageBuilder::StoreInCompressor(LogRecordCompressor* compressor) { - return compressor->Store(Vector<const char>(Log::message_buffer_, pos_)); -} - - -bool LogMessageBuilder::RetrieveCompressedPrevious( - LogRecordCompressor* compressor, const char* prefix) { - pos_ = 0; - if (prefix[0] != '\0') Append(prefix); - Vector<char> prev_record(Log::message_buffer_ + pos_, - Log::kMessageBufferSize - pos_); - const bool has_prev = compressor->RetrievePreviousCompressed(&prev_record); - if (!has_prev) return false; - pos_ += prev_record.length(); - return true; -} - - void LogMessageBuilder::WriteToLogFile() { ASSERT(pos_ <= Log::kMessageBufferSize); const int written = Log::Write(Log::message_buffer_, pos_); @@ -369,145 +329,6 @@ void LogMessageBuilder::WriteToLogFile() { } } - -// Formatting string for back references to the whole line. E.g. "#2" means -// "the second line above". -const char* LogRecordCompressor::kLineBackwardReferenceFormat = "#%d"; - -// Formatting string for back references. E.g. "#2:10" means -// "the second line above, start from char 10 (0-based)". -const char* LogRecordCompressor::kBackwardReferenceFormat = "#%d:%d"; - - -LogRecordCompressor::~LogRecordCompressor() { - for (int i = 0; i < buffer_.length(); ++i) { - buffer_[i].Dispose(); - } -} - - -static int GetNumberLength(int number) { - ASSERT(number >= 0); - ASSERT(number < 10000); - if (number < 10) return 1; - if (number < 100) return 2; - if (number < 1000) return 3; - return 4; -} - - -int LogRecordCompressor::GetBackwardReferenceSize(int distance, int pos) { - // See kLineBackwardReferenceFormat and kBackwardReferenceFormat. - return pos == 0 ? GetNumberLength(distance) + 1 - : GetNumberLength(distance) + GetNumberLength(pos) + 2; -} - - -void LogRecordCompressor::PrintBackwardReference(Vector<char> dest, - int distance, - int pos) { - if (pos == 0) { - OS::SNPrintF(dest, kLineBackwardReferenceFormat, distance); - } else { - OS::SNPrintF(dest, kBackwardReferenceFormat, distance, pos); - } -} - - -bool LogRecordCompressor::Store(const Vector<const char>& record) { - // Check if the record is the same as the last stored one. - if (curr_ != -1) { - Vector<const char>& curr = buffer_[curr_]; - if (record.length() == curr.length() - && strncmp(record.start(), curr.start(), record.length()) == 0) { - return false; - } - } - // buffer_ is circular. - prev_ = curr_++; - curr_ %= buffer_.length(); - Vector<char> record_copy = Vector<char>::New(record.length()); - memcpy(record_copy.start(), record.start(), record.length()); - buffer_[curr_].Dispose(); - buffer_[curr_] = - Vector<const char>(record_copy.start(), record_copy.length()); - return true; -} - - -bool LogRecordCompressor::RetrievePreviousCompressed( - Vector<char>* prev_record) { - if (prev_ == -1) return false; - - int index = prev_; - // Distance from prev_. - int distance = 0; - // Best compression result among records in the buffer. - struct { - intptr_t truncated_len; - int distance; - int copy_from_pos; - int backref_size; - } best = {-1, 0, 0, 0}; - Vector<const char>& prev = buffer_[prev_]; - const char* const prev_start = prev.start(); - const char* const prev_end = prev.start() + prev.length(); - do { - // We're moving backwards until we reach the current record. - // Remember that buffer_ is circular. - if (--index == -1) index = buffer_.length() - 1; - ++distance; - if (index == curr_) break; - - Vector<const char>& data = buffer_[index]; - if (data.start() == NULL) break; - const char* const data_end = data.start() + data.length(); - const char* prev_ptr = prev_end; - const char* data_ptr = data_end; - // Compare strings backwards, stop on the last matching character. - while (prev_ptr != prev_start && data_ptr != data.start() - && *(prev_ptr - 1) == *(data_ptr - 1)) { - --prev_ptr; - --data_ptr; - } - const intptr_t truncated_len = prev_end - prev_ptr; - const int copy_from_pos = static_cast<int>(data_ptr - data.start()); - // Check if the length of compressed tail is enough. - if (truncated_len <= kMaxBackwardReferenceSize - && truncated_len <= GetBackwardReferenceSize(distance, copy_from_pos)) { - continue; - } - - // Record compression results. - if (truncated_len > best.truncated_len) { - best.truncated_len = truncated_len; - best.distance = distance; - best.copy_from_pos = copy_from_pos; - best.backref_size = GetBackwardReferenceSize(distance, copy_from_pos); - } - } while (true); - - if (best.distance == 0) { - // Can't compress the previous record. Return as is. - ASSERT(prev_record->length() >= prev.length()); - memcpy(prev_record->start(), prev.start(), prev.length()); - prev_record->Truncate(prev.length()); - } else { - // Copy the uncompressible part unchanged. - const intptr_t unchanged_len = prev.length() - best.truncated_len; - // + 1 for '\0'. - ASSERT(prev_record->length() >= unchanged_len + best.backref_size + 1); - memcpy(prev_record->start(), prev.start(), unchanged_len); - // Append the backward reference. - Vector<char> backref( - prev_record->start() + unchanged_len, best.backref_size + 1); - PrintBackwardReference(backref, best.distance, best.copy_from_pos); - ASSERT(strlen(backref.start()) - best.backref_size == 0); - prev_record->Truncate(static_cast<int>(unchanged_len + best.backref_size)); - } - return true; -} - #endif // ENABLE_LOGGING_AND_PROFILING } } // namespace v8::internal diff --git a/deps/v8/src/log-utils.h b/deps/v8/src/log-utils.h index ffea9282cba..719d37030e1 100644 --- a/deps/v8/src/log-utils.h +++ b/deps/v8/src/log-utils.h @@ -176,50 +176,6 @@ class Log : public AllStatic { friend class Logger; friend class LogMessageBuilder; - friend class LogRecordCompressor; -}; - - -// An utility class for performing backward reference compression -// of string ends. It operates using a window of previous strings. -class LogRecordCompressor { - public: - // 'window_size' is the size of backward lookup window. - explicit LogRecordCompressor(int window_size) - : buffer_(window_size + kNoCompressionWindowSize), - kMaxBackwardReferenceSize( - GetBackwardReferenceSize(window_size, Log::kMessageBufferSize)), - curr_(-1), prev_(-1) { - } - - ~LogRecordCompressor(); - - // Fills vector with a compressed version of the previous record. - // Returns false if there is no previous record. - bool RetrievePreviousCompressed(Vector<char>* prev_record); - - // Stores a record if it differs from a previous one (or there's no previous). - // Returns true, if the record has been stored. - bool Store(const Vector<const char>& record); - - private: - // The minimum size of a buffer: a place needed for the current and - // the previous record. Since there is no place for precedessors of a previous - // record, it can't be compressed at all. - static const int kNoCompressionWindowSize = 2; - - // Formatting strings for back references. - static const char* kLineBackwardReferenceFormat; - static const char* kBackwardReferenceFormat; - - static int GetBackwardReferenceSize(int distance, int pos); - - static void PrintBackwardReference(Vector<char> dest, int distance, int pos); - - ScopedVector< Vector<const char> > buffer_; - const int kMaxBackwardReferenceSize; - int curr_; - int prev_; }; @@ -244,32 +200,14 @@ class LogMessageBuilder BASE_EMBEDDED { // Append a heap string. void Append(String* str); - // Appends an address, compressing it if needed by offsetting - // from Logger::last_address_. + // Appends an address. void AppendAddress(Address addr); - // Appends an address, compressing it if needed. - void AppendAddress(Address addr, Address bias); - void AppendDetailed(String* str, bool show_impl_info); // Append a portion of a string. void AppendStringPart(const char* str, int len); - // Stores log message into compressor, returns true if the message - // was stored (i.e. doesn't repeat the previous one). - bool StoreInCompressor(LogRecordCompressor* compressor); - - // Sets log message to a previous version of compressed message. - // Returns false, if there is no previous message. - bool RetrieveCompressedPrevious(LogRecordCompressor* compressor) { - return RetrieveCompressedPrevious(compressor, ""); - } - - // Does the same at the version without arguments, and sets a prefix. - bool RetrieveCompressedPrevious(LogRecordCompressor* compressor, - const char* prefix); - // Write the log message to the log file currently opened. void WriteToLogFile(); diff --git a/deps/v8/src/log.cc b/deps/v8/src/log.cc index 67233479244..b8e3f05a473 100644 --- a/deps/v8/src/log.cc +++ b/deps/v8/src/log.cc @@ -303,7 +303,6 @@ void Profiler::Engage() { Logger::ticker_->SetProfiler(this); Logger::ProfilerBeginEvent(); - Logger::LogAliases(); } @@ -343,43 +342,21 @@ void Profiler::Run() { Ticker* Logger::ticker_ = NULL; Profiler* Logger::profiler_ = NULL; SlidingStateWindow* Logger::sliding_state_window_ = NULL; -const char** Logger::log_events_ = NULL; -CompressionHelper* Logger::compression_helper_ = NULL; int Logger::logging_nesting_ = 0; int Logger::cpu_profiler_nesting_ = 0; int Logger::heap_profiler_nesting_ = 0; -#define DECLARE_LONG_EVENT(ignore1, long_name, ignore2) long_name, -const char* kLongLogEventsNames[Logger::NUMBER_OF_LOG_EVENTS] = { - LOG_EVENTS_AND_TAGS_LIST(DECLARE_LONG_EVENT) +#define DECLARE_EVENT(ignore1, name) name, +const char* kLogEventsNames[Logger::NUMBER_OF_LOG_EVENTS] = { + LOG_EVENTS_AND_TAGS_LIST(DECLARE_EVENT) }; -#undef DECLARE_LONG_EVENT - -#define DECLARE_SHORT_EVENT(ignore1, ignore2, short_name) short_name, -const char* kCompressedLogEventsNames[Logger::NUMBER_OF_LOG_EVENTS] = { - LOG_EVENTS_AND_TAGS_LIST(DECLARE_SHORT_EVENT) -}; -#undef DECLARE_SHORT_EVENT +#undef DECLARE_EVENT void Logger::ProfilerBeginEvent() { if (!Log::IsEnabled()) return; LogMessageBuilder msg; msg.Append("profiler,\"begin\",%d\n", kSamplingIntervalMs); - if (FLAG_compress_log) { - msg.Append("profiler,\"compression\",%d\n", kCompressionWindowSize); - } - msg.WriteToLogFile(); -} - - -void Logger::LogAliases() { - if (!Log::IsEnabled() || !FLAG_compress_log) return; - LogMessageBuilder msg; - for (int i = 0; i < NUMBER_OF_LOG_EVENTS; ++i) { - msg.Append("alias,%s,%s\n", - kCompressedLogEventsNames[i], kLongLogEventsNames[i]); - } msg.WriteToLogFile(); } @@ -687,54 +664,15 @@ void Logger::DeleteEvent(const char* name, void* object) { #ifdef ENABLE_LOGGING_AND_PROFILING - -// A class that contains all common code dealing with record compression. -class CompressionHelper { - public: - explicit CompressionHelper(int window_size) - : compressor_(window_size), repeat_count_(0) { } - - // Handles storing message in compressor, retrieving the previous one and - // prefixing it with repeat count, if needed. - // Returns true if message needs to be written to log. - bool HandleMessage(LogMessageBuilder* msg) { - if (!msg->StoreInCompressor(&compressor_)) { - // Current message repeats the previous one, don't write it. - ++repeat_count_; - return false; - } - if (repeat_count_ == 0) { - return msg->RetrieveCompressedPrevious(&compressor_); - } - OS::SNPrintF(prefix_, "%s,%d,", - Logger::log_events_[Logger::REPEAT_META_EVENT], - repeat_count_ + 1); - repeat_count_ = 0; - return msg->RetrieveCompressedPrevious(&compressor_, prefix_.start()); - } - - private: - LogRecordCompressor compressor_; - int repeat_count_; - EmbeddedVector<char, 20> prefix_; -}; - -#endif // ENABLE_LOGGING_AND_PROFILING - - -#ifdef ENABLE_LOGGING_AND_PROFILING void Logger::CallbackEventInternal(const char* prefix, const char* name, Address entry_point) { if (!Log::IsEnabled() || !FLAG_log_code) return; LogMessageBuilder msg; msg.Append("%s,%s,", - log_events_[CODE_CREATION_EVENT], log_events_[CALLBACK_TAG]); + kLogEventsNames[CODE_CREATION_EVENT], + kLogEventsNames[CALLBACK_TAG]); msg.AppendAddress(entry_point); msg.Append(",1,\"%s%s\"", prefix, name); - if (FLAG_compress_log) { - ASSERT(compression_helper_ != NULL); - if (!compression_helper_->HandleMessage(&msg)) return; - } msg.Append('\n'); msg.WriteToLogFile(); } @@ -786,7 +724,9 @@ void Logger::CodeCreateEvent(LogEventsAndTags tag, #ifdef ENABLE_LOGGING_AND_PROFILING if (!Log::IsEnabled() || !FLAG_log_code) return; LogMessageBuilder msg; - msg.Append("%s,%s,", log_events_[CODE_CREATION_EVENT], log_events_[tag]); + msg.Append("%s,%s,", + kLogEventsNames[CODE_CREATION_EVENT], + kLogEventsNames[tag]); msg.AppendAddress(code->address()); msg.Append(",%d,\"%s", code->ExecutableSize(), ComputeMarker(code)); for (const char* p = comment; *p != '\0'; p++) { @@ -797,10 +737,6 @@ void Logger::CodeCreateEvent(LogEventsAndTags tag, } msg.Append('"'); LowLevelCodeCreateEvent(code, &msg); - if (FLAG_compress_log) { - ASSERT(compression_helper_ != NULL); - if (!compression_helper_->HandleMessage(&msg)) return; - } msg.Append('\n'); msg.WriteToLogFile(); #endif @@ -813,14 +749,12 @@ void Logger::CodeCreateEvent(LogEventsAndTags tag, Code* code, String* name) { LogMessageBuilder msg; SmartPointer<char> str = name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL); - msg.Append("%s,%s,", log_events_[CODE_CREATION_EVENT], log_events_[tag]); + msg.Append("%s,%s,", + kLogEventsNames[CODE_CREATION_EVENT], + kLogEventsNames[tag]); msg.AppendAddress(code->address()); msg.Append(",%d,\"%s%s\"", code->ExecutableSize(), ComputeMarker(code), *str); LowLevelCodeCreateEvent(code, &msg); - if (FLAG_compress_log) { - ASSERT(compression_helper_ != NULL); - if (!compression_helper_->HandleMessage(&msg)) return; - } msg.Append('\n'); msg.WriteToLogFile(); #endif @@ -837,7 +771,9 @@ void Logger::CodeCreateEvent(LogEventsAndTags tag, name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL); SmartPointer<char> sourcestr = source->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL); - msg.Append("%s,%s,", log_events_[CODE_CREATION_EVENT], log_events_[tag]); + msg.Append("%s,%s,", + kLogEventsNames[CODE_CREATION_EVENT], + kLogEventsNames[tag]); msg.AppendAddress(code->address()); msg.Append(",%d,\"%s%s %s:%d\"", code->ExecutableSize(), @@ -846,10 +782,6 @@ void Logger::CodeCreateEvent(LogEventsAndTags tag, *sourcestr, line); LowLevelCodeCreateEvent(code, &msg); - if (FLAG_compress_log) { - ASSERT(compression_helper_ != NULL); - if (!compression_helper_->HandleMessage(&msg)) return; - } msg.Append('\n'); msg.WriteToLogFile(); #endif @@ -860,14 +792,12 @@ void Logger::CodeCreateEvent(LogEventsAndTags tag, Code* code, int args_count) { #ifdef ENABLE_LOGGING_AND_PROFILING if (!Log::IsEnabled() || !FLAG_log_code) return; LogMessageBuilder msg; - msg.Append("%s,%s,", log_events_[CODE_CREATION_EVENT], log_events_[tag]); + msg.Append("%s,%s,", + kLogEventsNames[CODE_CREATION_EVENT], + kLogEventsNames[tag]); msg.AppendAddress(code->address()); msg.Append(",%d,\"args_count: %d\"", code->ExecutableSize(), args_count); LowLevelCodeCreateEvent(code, &msg); - if (FLAG_compress_log) { - ASSERT(compression_helper_ != NULL); - if (!compression_helper_->HandleMessage(&msg)) return; - } msg.Append('\n'); msg.WriteToLogFile(); #endif @@ -878,7 +808,7 @@ void Logger::CodeMovingGCEvent() { #ifdef ENABLE_LOGGING_AND_PROFILING if (!Log::IsEnabled() || !FLAG_log_code || !FLAG_ll_prof) return; LogMessageBuilder msg; - msg.Append("%s\n", log_events_[CODE_MOVING_GC]); + msg.Append("%s\n", kLogEventsNames[CODE_MOVING_GC]); msg.WriteToLogFile(); OS::SignalCodeMovingGC(); #endif @@ -890,16 +820,13 @@ void Logger::RegExpCodeCreateEvent(Code* code, String* source) { if (!Log::IsEnabled() || !FLAG_log_code) return; LogMessageBuilder msg; msg.Append("%s,%s,", - log_events_[CODE_CREATION_EVENT], log_events_[REG_EXP_TAG]); + kLogEventsNames[CODE_CREATION_EVENT], + kLogEventsNames[REG_EXP_TAG]); msg.AppendAddress(code->address()); msg.Append(",%d,\"", code->ExecutableSize()); msg.AppendDetailed(source, false); msg.Append('\"'); LowLevelCodeCreateEvent(code, &msg); - if (FLAG_compress_log) { - ASSERT(compression_helper_ != NULL); - if (!compression_helper_->HandleMessage(&msg)) return; - } msg.Append('\n'); msg.WriteToLogFile(); #endif @@ -924,13 +851,9 @@ void Logger::SnapshotPositionEvent(Address addr, int pos) { #ifdef ENABLE_LOGGING_AND_PROFILING if (!Log::IsEnabled() || !FLAG_log_snapshot_positions) return; LogMessageBuilder msg; - msg.Append("%s,", log_events_[SNAPSHOT_POSITION_EVENT]); + msg.Append("%s,", kLogEventsNames[SNAPSHOT_POSITION_EVENT]); msg.AppendAddress(addr); msg.Append(",%d", pos); - if (FLAG_compress_log) { - ASSERT(compression_helper_ != NULL); - if (!compression_helper_->HandleMessage(&msg)) return; - } msg.Append('\n'); msg.WriteToLogFile(); #endif @@ -942,18 +865,12 @@ void Logger::FunctionCreateEvent(JSFunction* function) { // This function can be called from GC iterators (during Scavenge, // MC, and MS), so marking bits can be set on objects. That's // why unchecked accessors are used here. - static Address prev_code = NULL; if (!Log::IsEnabled() || !FLAG_log_code) return; LogMessageBuilder msg; - msg.Append("%s,", log_events_[FUNCTION_CREATION_EVENT]); + msg.Append("%s,", kLogEventsNames[FUNCTION_CREATION_EVENT]); msg.AppendAddress(function->address()); msg.Append(','); - msg.AppendAddress(function->unchecked_code()->address(), prev_code); - prev_code = function->unchecked_code()->address(); - if (FLAG_compress_log) { - ASSERT(compression_helper_ != NULL); - if (!compression_helper_->HandleMessage(&msg)) return; - } + msg.AppendAddress(function->unchecked_code()->address()); msg.Append('\n'); msg.WriteToLogFile(); #endif @@ -987,18 +904,12 @@ void Logger::FunctionDeleteEvent(Address from) { void Logger::MoveEventInternal(LogEventsAndTags event, Address from, Address to) { - static Address prev_to_ = NULL; if (!Log::IsEnabled() || !FLAG_log_code) return; LogMessageBuilder msg; - msg.Append("%s,", log_events_[event]); + msg.Append("%s,", kLogEventsNames[event]); msg.AppendAddress(from); msg.Append(','); - msg.AppendAddress(to, prev_to_); - prev_to_ = to; - if (FLAG_compress_log) { - ASSERT(compression_helper_ != NULL); - if (!compression_helper_->HandleMessage(&msg)) return; - } + msg.AppendAddress(to); msg.Append('\n'); msg.WriteToLogFile(); } @@ -1009,12 +920,8 @@ void Logger::MoveEventInternal(LogEventsAndTags event, void Logger::DeleteEventInternal(LogEventsAndTags event, Address from) { if (!Log::IsEnabled() || !FLAG_log_code) return; LogMessageBuilder msg; - msg.Append("%s,", log_events_[event]); + msg.Append("%s,", kLogEventsNames[event]); msg.AppendAddress(from); - if (FLAG_compress_log) { - ASSERT(compression_helper_ != NULL); - if (!compression_helper_->HandleMessage(&msg)) return; - } msg.Append('\n'); msg.WriteToLogFile(); } @@ -1202,30 +1109,20 @@ void Logger::DebugEvent(const char* event_type, Vector<uint16_t> parameter) { #ifdef ENABLE_LOGGING_AND_PROFILING void Logger::TickEvent(TickSample* sample, bool overflow) { if (!Log::IsEnabled() || !FLAG_prof) return; - static Address prev_sp = NULL; - static Address prev_function = NULL; LogMessageBuilder msg; - msg.Append("%s,", log_events_[TICK_EVENT]); - Address prev_addr = sample->pc; - msg.AppendAddress(prev_addr); + msg.Append("%s,", kLogEventsNames[TICK_EVENT]); + msg.AppendAddress(sample->pc); msg.Append(','); - msg.AppendAddress(sample->sp, prev_sp); - prev_sp = sample->sp; + msg.AppendAddress(sample->sp); msg.Append(','); - msg.AppendAddress(sample->function, prev_function); - prev_function = sample->function; + msg.AppendAddress(sample->function); msg.Append(",%d", static_cast<int>(sample->state)); if (overflow) { msg.Append(",overflow"); } for (int i = 0; i < sample->frames_count; ++i) { msg.Append(','); - msg.AppendAddress(sample->stack[i], prev_addr); - prev_addr = sample->stack[i]; - } - if (FLAG_compress_log) { - ASSERT(compression_helper_ != NULL); - if (!compression_helper_->HandleMessage(&msg)) return; + msg.AppendAddress(sample->stack[i]); } msg.Append('\n'); msg.WriteToLogFile(); @@ -1654,12 +1551,6 @@ bool Logger::Setup() { sliding_state_window_ = new SlidingStateWindow(); } - log_events_ = FLAG_compress_log ? - kCompressedLogEventsNames : kLongLogEventsNames; - if (FLAG_compress_log) { - compression_helper_ = new CompressionHelper(kCompressionWindowSize); - } - if (start_logging) { logging_nesting_ = 1; } @@ -1707,9 +1598,6 @@ void Logger::TearDown() { profiler_ = NULL; } - delete compression_helper_; - compression_helper_ = NULL; - delete sliding_state_window_; sliding_state_window_ = NULL; diff --git a/deps/v8/src/log.h b/deps/v8/src/log.h index 54b131bb0c2..771709c8a10 100644 --- a/deps/v8/src/log.h +++ b/deps/v8/src/log.h @@ -74,7 +74,6 @@ class Profiler; class Semaphore; class SlidingStateWindow; class LogMessageBuilder; -class CompressionHelper; #undef LOG #ifdef ENABLE_LOGGING_AND_PROFILING @@ -88,58 +87,55 @@ class CompressionHelper; #endif #define LOG_EVENTS_AND_TAGS_LIST(V) \ - V(CODE_CREATION_EVENT, "code-creation", "cc") \ - V(CODE_MOVE_EVENT, "code-move", "cm") \ - V(CODE_DELETE_EVENT, "code-delete", "cd") \ - V(CODE_MOVING_GC, "code-moving-gc", "cg") \ - V(FUNCTION_CREATION_EVENT, "function-creation", "fc") \ - V(FUNCTION_MOVE_EVENT, "function-move", "fm") \ - V(FUNCTION_DELETE_EVENT, "function-delete", "fd") \ - V(SNAPSHOT_POSITION_EVENT, "snapshot-pos", "sp") \ - V(TICK_EVENT, "tick", "t") \ - V(REPEAT_META_EVENT, "repeat", "r") \ - V(BUILTIN_TAG, "Builtin", "bi") \ - V(CALL_DEBUG_BREAK_TAG, "CallDebugBreak", "cdb") \ - V(CALL_DEBUG_PREPARE_STEP_IN_TAG, "CallDebugPrepareStepIn", "cdbsi") \ - V(CALL_IC_TAG, "CallIC", "cic") \ - V(CALL_INITIALIZE_TAG, "CallInitialize", "ci") \ - V(CALL_MEGAMORPHIC_TAG, "CallMegamorphic", "cmm") \ - V(CALL_MISS_TAG, "CallMiss", "cm") \ - V(CALL_NORMAL_TAG, "CallNormal", "cn") \ - V(CALL_PRE_MONOMORPHIC_TAG, "CallPreMonomorphic", "cpm") \ - V(KEYED_CALL_DEBUG_BREAK_TAG, "KeyedCallDebugBreak", "kcdb") \ - V(KEYED_CALL_DEBUG_PREPARE_STEP_IN_TAG, \ - "KeyedCallDebugPrepareStepIn", \ - "kcdbsi") \ - V(KEYED_CALL_IC_TAG, "KeyedCallIC", "kcic") \ - V(KEYED_CALL_INITIALIZE_TAG, "KeyedCallInitialize", "kci") \ - V(KEYED_CALL_MEGAMORPHIC_TAG, "KeyedCallMegamorphic", "kcmm") \ - V(KEYED_CALL_MISS_TAG, "KeyedCallMiss", "kcm") \ - V(KEYED_CALL_NORMAL_TAG, "KeyedCallNormal", "kcn") \ - V(KEYED_CALL_PRE_MONOMORPHIC_TAG, \ - "KeyedCallPreMonomorphic", \ - "kcpm") \ - V(CALLBACK_TAG, "Callback", "cb") \ - V(EVAL_TAG, "Eval", "e") \ - V(FUNCTION_TAG, "Function", "f") \ - V(KEYED_LOAD_IC_TAG, "KeyedLoadIC", "klic") \ - V(KEYED_STORE_IC_TAG, "KeyedStoreIC", "ksic") \ - V(LAZY_COMPILE_TAG, "LazyCompile", "lc") \ - V(LOAD_IC_TAG, "LoadIC", "lic") \ - V(REG_EXP_TAG, "RegExp", "re") \ - V(SCRIPT_TAG, "Script", "sc") \ - V(STORE_IC_TAG, "StoreIC", "sic") \ - V(STUB_TAG, "Stub", "s") \ - V(NATIVE_FUNCTION_TAG, "Function", "f") \ - V(NATIVE_LAZY_COMPILE_TAG, "LazyCompile", "lc") \ - V(NATIVE_SCRIPT_TAG, "Script", "sc") + V(CODE_CREATION_EVENT, "code-creation") \ + V(CODE_MOVE_EVENT, "code-move") \ + V(CODE_DELETE_EVENT, "code-delete") \ + V(CODE_MOVING_GC, "code-moving-gc") \ + V(FUNCTION_CREATION_EVENT, "function-creation") \ + V(FUNCTION_MOVE_EVENT, "function-move") \ + V(FUNCTION_DELETE_EVENT, "function-delete") \ + V(SNAPSHOT_POSITION_EVENT, "snapshot-pos") \ + V(TICK_EVENT, "tick") \ + V(REPEAT_META_EVENT, "repeat") \ + V(BUILTIN_TAG, "Builtin") \ + V(CALL_DEBUG_BREAK_TAG, "CallDebugBreak") \ + V(CALL_DEBUG_PREPARE_STEP_IN_TAG, "CallDebugPrepareStepIn") \ + V(CALL_IC_TAG, "CallIC") \ + V(CALL_INITIALIZE_TAG, "CallInitialize") \ + V(CALL_MEGAMORPHIC_TAG, "CallMegamorphic") \ + V(CALL_MISS_TAG, "CallMiss") \ + V(CALL_NORMAL_TAG, "CallNormal") \ + V(CALL_PRE_MONOMORPHIC_TAG, "CallPreMonomorphic") \ + V(KEYED_CALL_DEBUG_BREAK_TAG, "KeyedCallDebugBreak") \ + V(KEYED_CALL_DEBUG_PREPARE_STEP_IN_TAG, \ + "KeyedCallDebugPrepareStepIn") \ + V(KEYED_CALL_IC_TAG, "KeyedCallIC") \ + V(KEYED_CALL_INITIALIZE_TAG, "KeyedCallInitialize") \ + V(KEYED_CALL_MEGAMORPHIC_TAG, "KeyedCallMegamorphic") \ + V(KEYED_CALL_MISS_TAG, "KeyedCallMiss") \ + V(KEYED_CALL_NORMAL_TAG, "KeyedCallNormal") \ + V(KEYED_CALL_PRE_MONOMORPHIC_TAG, "KeyedCallPreMonomorphic") \ + V(CALLBACK_TAG, "Callback") \ + V(EVAL_TAG, "Eval") \ + V(FUNCTION_TAG, "Function") \ + V(KEYED_LOAD_IC_TAG, "KeyedLoadIC") \ + V(KEYED_STORE_IC_TAG, "KeyedStoreIC") \ + V(LAZY_COMPILE_TAG, "LazyCompile") \ + V(LOAD_IC_TAG, "LoadIC") \ + V(REG_EXP_TAG, "RegExp") \ + V(SCRIPT_TAG, "Script") \ + V(STORE_IC_TAG, "StoreIC") \ + V(STUB_TAG, "Stub") \ + V(NATIVE_FUNCTION_TAG, "Function") \ + V(NATIVE_LAZY_COMPILE_TAG, "LazyCompile") \ + V(NATIVE_SCRIPT_TAG, "Script") // Note that 'NATIVE_' cases for functions and scripts are mapped onto // original tags when writing to the log. class Logger { public: -#define DECLARE_ENUM(enum_item, ignore1, ignore2) enum_item, +#define DECLARE_ENUM(enum_item, ignore) enum_item, enum LogEventsAndTags { LOG_EVENTS_AND_TAGS_LIST(DECLARE_ENUM) NUMBER_OF_LOG_EVENTS @@ -292,9 +288,6 @@ class Logger { private: - // Size of window used for log records compression. - static const int kCompressionWindowSize = 4; - // Emits the profiler's first message. static void ProfilerBeginEvent(); @@ -312,9 +305,6 @@ class Logger { static void DeleteEventInternal(LogEventsAndTags event, Address from); - // Emits aliases for compressed messages. - static void LogAliases(); - // Emits the source code of a regexp. Used by regexp events. static void LogRegExpSource(Handle<JSRegExp> regexp); @@ -357,15 +347,8 @@ class Logger { // recent VM states. static SlidingStateWindow* sliding_state_window_; - // An array of log events names. - static const char** log_events_; - - // An instance of helper created if log compression is enabled. - static CompressionHelper* compression_helper_; - // Internal implementation classes with access to // private members. - friend class CompressionHelper; friend class EventLog; friend class TimeLog; friend class Profiler; diff --git a/deps/v8/src/math.js b/deps/v8/src/math.js index fa1934da415..2e886d099a9 100644 --- a/deps/v8/src/math.js +++ b/deps/v8/src/math.js @@ -264,6 +264,7 @@ function SetupMath() { %SetMathFunctionId($Math.round, 2); %SetMathFunctionId($Math.abs, 4); %SetMathFunctionId($Math.sqrt, 0xd); + %SetMathFunctionId($Math.pow, 0xe); // TODO(erikcorry): Set the id of the other functions so they can be // optimized. }; diff --git a/deps/v8/src/objects.h b/deps/v8/src/objects.h index 1827ab0114a..c3958e23968 100644 --- a/deps/v8/src/objects.h +++ b/deps/v8/src/objects.h @@ -3729,7 +3729,9 @@ enum MathFunctionId { kMathACos = 0xa, kMathATan = 0xb, kMathExp = 0xc, - kMathSqrt = 0xd + kMathSqrt = 0xd, + kMathPow = 0xe, + kMathPowHalf = 0xf }; @@ -4154,11 +4156,11 @@ class SharedFunctionInfo: public HeapObject { static const int kTryFullCodegen = 1; static const int kAllowLazyCompilation = 2; static const int kMathFunctionShift = 3; - static const int kMathFunctionMask = 0xf; - static const int kLiveObjectsMayExist = 7; - static const int kCodeAgeShift = 8; + static const int kMathFunctionMask = 0x1f; + static const int kLiveObjectsMayExist = 8; + static const int kCodeAgeShift = 9; static const int kCodeAgeMask = 0x7; - static const int kOptimizationDisabled = 11; + static const int kOptimizationDisabled = 12; DISALLOW_IMPLICIT_CONSTRUCTORS(SharedFunctionInfo); }; diff --git a/deps/v8/src/parser.cc b/deps/v8/src/parser.cc index 056332b5b44..94ad57c9c28 100644 --- a/deps/v8/src/parser.cc +++ b/deps/v8/src/parser.cc @@ -609,7 +609,25 @@ FunctionLiteral* Parser::ParseProgram(Handle<String> source, // Initialize parser state. source->TryFlatten(); - scanner_.Initialize(source); + if (source->IsExternalTwoByteString()) { + // Notice that the stream is destroyed at the end of the branch block. + // The last line of the blocks can't be moved outside, even though they're + // identical calls. + ExternalTwoByteStringUC16CharacterStream stream( + Handle<ExternalTwoByteString>::cast(source), 0, source->length()); + scanner_.Initialize(&stream, JavaScriptScanner::kAllLiterals); + return DoParseProgram(source, in_global_context, &zone_scope); + } else { + GenericStringUC16CharacterStream stream(source, 0, source->length()); + scanner_.Initialize(&stream, JavaScriptScanner::kAllLiterals); + return DoParseProgram(source, in_global_context, &zone_scope); + } +} + + +FunctionLiteral* Parser::DoParseProgram(Handle<String> source, + bool in_global_context, + ZoneScope* zone_scope) { ASSERT(target_stack_ == NULL); if (pre_data_ != NULL) pre_data_->Initialize(); @@ -655,25 +673,45 @@ FunctionLiteral* Parser::ParseProgram(Handle<String> source, // If there was a syntax error we have to get rid of the AST // and it is not safe to do so before the scope has been deleted. - if (result == NULL) zone_scope.DeleteOnExit(); + if (result == NULL) zone_scope->DeleteOnExit(); return result; } - FunctionLiteral* Parser::ParseLazy(Handle<SharedFunctionInfo> info) { CompilationZoneScope zone_scope(DONT_DELETE_ON_EXIT); HistogramTimerScope timer(&Counters::parse_lazy); Handle<String> source(String::cast(script_->source())); Counters::total_parse_size.Increment(source->length()); + // Initialize parser state. + source->TryFlatten(); + if (source->IsExternalTwoByteString()) { + ExternalTwoByteStringUC16CharacterStream stream( + Handle<ExternalTwoByteString>::cast(source), + info->start_position(), + info->end_position()); + FunctionLiteral* result = ParseLazy(info, &stream, &zone_scope); + return result; + } else { + GenericStringUC16CharacterStream stream(source, + info->start_position(), + info->end_position()); + FunctionLiteral* result = ParseLazy(info, &stream, &zone_scope); + return result; + } +} + + +FunctionLiteral* Parser::ParseLazy(Handle<SharedFunctionInfo> info, + UC16CharacterStream* source, + ZoneScope* zone_scope) { + scanner_.Initialize(source, JavaScriptScanner::kAllLiterals); + ASSERT(target_stack_ == NULL); + Handle<String> name(String::cast(info->name())); fni_ = new FuncNameInferrer(); fni_->PushEnclosingName(name); - // Initialize parser state. - source->TryFlatten(); - scanner_.Initialize(source, info->start_position(), info->end_position()); - ASSERT(target_stack_ == NULL); mode_ = PARSE_EAGERLY; // Place holder for the result. @@ -705,7 +743,7 @@ FunctionLiteral* Parser::ParseLazy(Handle<SharedFunctionInfo> info) { // not safe to do before scope has been deleted. if (result == NULL) { Top::StackOverflow(); - zone_scope.DeleteOnExit(); + zone_scope->DeleteOnExit(); } else { Handle<String> inferred_name(info->inferred_name()); result->set_inferred_name(inferred_name); @@ -719,12 +757,12 @@ Handle<String> Parser::GetSymbol(bool* ok) { if (pre_data() != NULL) { symbol_id = pre_data()->GetSymbolIdentifier(); } - return LookupSymbol(symbol_id, scanner_.literal()); + return LookupSymbol(symbol_id, scanner().literal()); } void Parser::ReportMessage(const char* type, Vector<const char*> args) { - Scanner::Location source_location = scanner_.location(); + Scanner::Location source_location = scanner().location(); ReportMessageAt(source_location, type, args); } @@ -1641,7 +1679,7 @@ Statement* Parser::ParseContinueStatement(bool* ok) { Expect(Token::CONTINUE, CHECK_OK); Handle<String> label = Handle<String>::null(); Token::Value tok = peek(); - if (!scanner_.has_line_terminator_before_next() && + if (!scanner().has_line_terminator_before_next() && tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) { label = ParseIdentifier(CHECK_OK); } @@ -1667,7 +1705,7 @@ Statement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) { Expect(Token::BREAK, CHECK_OK); Handle<String> label; Token::Value tok = peek(); - if (!scanner_.has_line_terminator_before_next() && + if (!scanner().has_line_terminator_before_next() && tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) { label = ParseIdentifier(CHECK_OK); } @@ -1712,7 +1750,7 @@ Statement* Parser::ParseReturnStatement(bool* ok) { } Token::Value tok = peek(); - if (scanner_.has_line_terminator_before_next() || + if (scanner().has_line_terminator_before_next() || tok == Token::SEMICOLON || tok == Token::RBRACE || tok == Token::EOS) { @@ -1844,7 +1882,7 @@ Statement* Parser::ParseThrowStatement(bool* ok) { Expect(Token::THROW, CHECK_OK); int pos = scanner().location().beg_pos; - if (scanner_.has_line_terminator_before_next()) { + if (scanner().has_line_terminator_before_next()) { ReportMessage("newline_after_throw", Vector<const char*>::empty()); *ok = false; return NULL; @@ -2408,7 +2446,8 @@ Expression* Parser::ParsePostfixExpression(bool* ok) { // LeftHandSideExpression ('++' | '--')? Expression* expression = ParseLeftHandSideExpression(CHECK_OK); - if (!scanner_.has_line_terminator_before_next() && Token::IsCountOp(peek())) { + if (!scanner().has_line_terminator_before_next() && + Token::IsCountOp(peek())) { // Signal a reference error if the expression is an invalid // left-hand side expression. We could report this as a syntax // error here but for compatibility with JSC we choose to report the @@ -2677,7 +2716,7 @@ Expression* Parser::ParsePrimaryExpression(bool* ok) { case Token::NUMBER: { Consume(Token::NUMBER); double value = - StringToDouble(scanner_.literal(), ALLOW_HEX | ALLOW_OCTALS); + StringToDouble(scanner().literal(), ALLOW_HEX | ALLOW_OCTALS); result = NewNumberLiteral(value); break; } @@ -3028,7 +3067,7 @@ Expression* Parser::ParseObjectLiteral(bool* ok) { case Token::NUMBER: { Consume(Token::NUMBER); double value = - StringToDouble(scanner_.literal(), ALLOW_HEX | ALLOW_OCTALS); + StringToDouble(scanner().literal(), ALLOW_HEX | ALLOW_OCTALS); key = NewNumberLiteral(value); break; } @@ -3089,7 +3128,7 @@ Expression* Parser::ParseObjectLiteral(bool* ok) { Expression* Parser::ParseRegExpLiteral(bool seen_equal, bool* ok) { - if (!scanner_.ScanRegExpPattern(seen_equal)) { + if (!scanner().ScanRegExpPattern(seen_equal)) { Next(); ReportMessage("unterminated_regexp", Vector<const char*>::empty()); *ok = false; @@ -3099,10 +3138,10 @@ Expression* Parser::ParseRegExpLiteral(bool seen_equal, bool* ok) { int literal_index = temp_scope_->NextMaterializedLiteralIndex(); Handle<String> js_pattern = - Factory::NewStringFromUtf8(scanner_.next_literal(), TENURED); - scanner_.ScanRegExpFlags(); + Factory::NewStringFromUtf8(scanner().next_literal(), TENURED); + scanner().ScanRegExpFlags(); Handle<String> js_flags = - Factory::NewStringFromUtf8(scanner_.next_literal(), TENURED); + Factory::NewStringFromUtf8(scanner().next_literal(), TENURED); Next(); return new RegExpLiteral(js_pattern, js_flags, literal_index); @@ -3158,7 +3197,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name, // FormalParameterList :: // '(' (Identifier)*[','] ')' Expect(Token::LPAREN, CHECK_OK); - int start_pos = scanner_.location().beg_pos; + int start_pos = scanner().location().beg_pos; bool done = (peek() == Token::RPAREN); while (!done) { Handle<String> param_name = ParseIdentifier(CHECK_OK); @@ -3195,7 +3234,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name, bool is_lazily_compiled = mode() == PARSE_LAZILY && top_scope_->HasTrivialOuterContext(); - int function_block_pos = scanner_.location().beg_pos; + int function_block_pos = scanner().location().beg_pos; int materialized_literal_count; int expected_property_count; int end_pos; @@ -3212,7 +3251,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name, ReportInvalidPreparseData(name, CHECK_OK); } Counters::total_preparse_skipped.Increment(end_pos - function_block_pos); - scanner_.SeekForward(end_pos); + // Seek to position just before terminal '}'. + scanner().SeekForward(end_pos - 1); materialized_literal_count = entry.literal_count(); expected_property_count = entry.property_count(); only_simple_this_property_assignments = false; @@ -3228,7 +3268,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name, this_property_assignments = temp_scope.this_property_assignments(); Expect(Token::RBRACE, CHECK_OK); - end_pos = scanner_.location().end_pos; + end_pos = scanner().location().end_pos; } FunctionLiteral* function_literal = @@ -3332,7 +3372,7 @@ void Parser::ExpectSemicolon(bool* ok) { Next(); return; } - if (scanner_.has_line_terminator_before_next() || + if (scanner().has_line_terminator_before_next() || tok == Token::RBRACE || tok == Token::EOS) { return; @@ -3383,8 +3423,8 @@ Handle<String> Parser::ParseIdentifierOrGetOrSet(bool* is_get, bool* ok) { Expect(Token::IDENTIFIER, ok); if (!*ok) return Handle<String>(); - if (scanner_.literal_length() == 3) { - const char* token = scanner_.literal_string(); + if (scanner().literal_length() == 3) { + const char* token = scanner().literal_string(); *is_get = strcmp(token, "get") == 0; *is_set = !*is_get && strcmp(token, "set") == 0; } @@ -3503,8 +3543,8 @@ Expression* Parser::NewThrowError(Handle<String> constructor, // ---------------------------------------------------------------------------- // JSON -Handle<Object> JsonParser::ParseJson(Handle<String> source) { - source->TryFlatten(); +Handle<Object> JsonParser::ParseJson(Handle<String> script, + UC16CharacterStream* source) { scanner_.Initialize(source); stack_overflow_ = false; Handle<Object> result = ParseJsonValue(); @@ -3540,7 +3580,7 @@ Handle<Object> JsonParser::ParseJson(Handle<String> source) { } Scanner::Location source_location = scanner_.location(); - MessageLocation location(Factory::NewScript(source), + MessageLocation location(Factory::NewScript(script), source_location.beg_pos, source_location.end_pos); int argc = (name_opt == NULL) ? 0 : 1; @@ -4409,10 +4449,25 @@ CharacterRange RegExpParser::ParseClassAtom(uc16* char_class) { } +static const uc16 kNoCharClass = 0; + +// Adds range or pre-defined character class to character ranges. +// If char_class is not kInvalidClass, it's interpreted as a class +// escape (i.e., 's' means whitespace, from '\s'). +static inline void AddRangeOrEscape(ZoneList<CharacterRange>* ranges, + uc16 char_class, + CharacterRange range) { + if (char_class != kNoCharClass) { + CharacterRange::AddClassEscape(char_class, ranges); + } else { + ranges->Add(range); + } +} + + RegExpTree* RegExpParser::ParseCharacterClass() { static const char* kUnterminated = "Unterminated character class"; static const char* kRangeOutOfOrder = "Range out of order in character class"; - static const char* kInvalidRange = "Invalid character range"; ASSERT_EQ(current(), '['); Advance(); @@ -4421,30 +4476,10 @@ RegExpTree* RegExpParser::ParseCharacterClass() { is_negated = true; Advance(); } - // A CharacterClass is a sequence of single characters, character class - // escapes or ranges. Ranges are on the form "x-y" where x and y are - // single characters (and not character class escapes like \s). - // A "-" may occur at the start or end of the character class (just after - // "[" or "[^", or just before "]") without being considered part of a - // range. A "-" may also appear as the beginning or end of a range. - // I.e., [--+] is valid, so is [!--]. - ZoneList<CharacterRange>* ranges = new ZoneList<CharacterRange>(2); while (has_more() && current() != ']') { - uc16 char_class = 0; + uc16 char_class = kNoCharClass; CharacterRange first = ParseClassAtom(&char_class CHECK_FAILED); - if (char_class) { - CharacterRange::AddClassEscape(char_class, ranges); - if (current() == '-') { - Advance(); - ranges->Add(CharacterRange::Singleton('-')); - if (current() != ']') { - ReportError(CStrVector(kInvalidRange) CHECK_FAILED); - } - break; - } - continue; - } if (current() == '-') { Advance(); if (current() == kEndMarker) { @@ -4452,20 +4487,25 @@ RegExpTree* RegExpParser::ParseCharacterClass() { // following code report an error. break; } else if (current() == ']') { - ranges->Add(first); + AddRangeOrEscape(ranges, char_class, first); ranges->Add(CharacterRange::Singleton('-')); break; } - CharacterRange next = ParseClassAtom(&char_class CHECK_FAILED); - if (char_class) { - ReportError(CStrVector(kInvalidRange) CHECK_FAILED); + uc16 char_class_2 = kNoCharClass; + CharacterRange next = ParseClassAtom(&char_class_2 CHECK_FAILED); + if (char_class != kNoCharClass || char_class_2 != kNoCharClass) { + // Either end is an escaped character class. Treat the '-' verbatim. + AddRangeOrEscape(ranges, char_class, first); + ranges->Add(CharacterRange::Singleton('-')); + AddRangeOrEscape(ranges, char_class_2, next); + continue; } if (first.from() > next.to()) { return ReportError(CStrVector(kRangeOutOfOrder) CHECK_FAILED); } ranges->Add(CharacterRange::Range(first.from(), next.to())); } else { - ranges->Add(first); + AddRangeOrEscape(ranges, char_class, first); } } if (!has_more()) { @@ -4555,13 +4595,12 @@ int ScriptDataImpl::ReadNumber(byte** source) { // Create a Scanner for the preparser to use as input, and preparse the source. -static ScriptDataImpl* DoPreParse(Handle<String> source, - unibrow::CharacterStream* stream, +static ScriptDataImpl* DoPreParse(UC16CharacterStream* source, bool allow_lazy, ParserRecorder* recorder, int literal_flags) { V8JavaScriptScanner scanner; - scanner.Initialize(source, stream, literal_flags); + scanner.Initialize(source, literal_flags); intptr_t stack_limit = StackGuard::real_climit(); if (!preparser::PreParser::PreParseProgram(&scanner, recorder, @@ -4580,8 +4619,7 @@ static ScriptDataImpl* DoPreParse(Handle<String> source, // Preparse, but only collect data that is immediately useful, // even if the preparser data is only used once. -ScriptDataImpl* ParserApi::PartialPreParse(Handle<String> source, - unibrow::CharacterStream* stream, +ScriptDataImpl* ParserApi::PartialPreParse(UC16CharacterStream* source, v8::Extension* extension) { bool allow_lazy = FLAG_lazy && (extension == NULL); if (!allow_lazy) { @@ -4590,22 +4628,19 @@ ScriptDataImpl* ParserApi::PartialPreParse(Handle<String> source, return NULL; } PartialParserRecorder recorder; - - return DoPreParse(source, stream, allow_lazy, &recorder, + return DoPreParse(source, allow_lazy, &recorder, JavaScriptScanner::kNoLiterals); } -ScriptDataImpl* ParserApi::PreParse(Handle<String> source, - unibrow::CharacterStream* stream, +ScriptDataImpl* ParserApi::PreParse(UC16CharacterStream* source, v8::Extension* extension) { Handle<Script> no_script; bool allow_lazy = FLAG_lazy && (extension == NULL); CompleteParserRecorder recorder; int kPreParseLiteralsFlags = JavaScriptScanner::kLiteralString | JavaScriptScanner::kLiteralIdentifier; - return DoPreParse(source, stream, allow_lazy, - &recorder, kPreParseLiteralsFlags); + return DoPreParse(source, allow_lazy, &recorder, kPreParseLiteralsFlags); } diff --git a/deps/v8/src/parser.h b/deps/v8/src/parser.h index 58cd946cad6..70d0e18fdb8 100644 --- a/deps/v8/src/parser.h +++ b/deps/v8/src/parser.h @@ -169,14 +169,12 @@ class ParserApi { static bool Parse(CompilationInfo* info); // Generic preparser generating full preparse data. - static ScriptDataImpl* PreParse(Handle<String> source, - unibrow::CharacterStream* stream, + static ScriptDataImpl* PreParse(UC16CharacterStream* source, 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, + static ScriptDataImpl* PartialPreParse(UC16CharacterStream* source, v8::Extension* extension); }; @@ -435,18 +433,26 @@ class Parser { Vector<const char*> args); protected: + FunctionLiteral* ParseLazy(Handle<SharedFunctionInfo> info, + UC16CharacterStream* source, + ZoneScope* zone_scope); enum Mode { PARSE_LAZILY, PARSE_EAGERLY }; + // Called by ParseProgram after setting up the scanner. + FunctionLiteral* DoParseProgram(Handle<String> source, + bool in_global_context, + ZoneScope* zone_scope); + // Report syntax error void ReportUnexpectedToken(Token::Value token); void ReportInvalidPreparseData(Handle<String> name, bool* ok); void ReportMessage(const char* message, Vector<const char*> args); bool inside_with() const { return with_nesting_level_ > 0; } - Scanner& scanner() { return scanner_; } + V8JavaScriptScanner& scanner() { return scanner_; } Mode mode() const { return mode_; } ScriptDataImpl* pre_data() const { return pre_data_; } @@ -548,7 +554,7 @@ class Parser { INLINE(Token::Value peek()) { if (stack_overflow_) return Token::ILLEGAL; - return scanner_.peek(); + return scanner().peek(); } INLINE(Token::Value Next()) { @@ -560,9 +566,11 @@ class Parser { } if (StackLimitCheck().HasOverflowed()) { // Any further calls to Next or peek will return the illegal token. + // The current call must return the next token, which might already + // have been peek'ed. stack_overflow_ = true; } - return scanner_.Next(); + return scanner().Next(); } INLINE(void Consume(Token::Value token)); @@ -702,7 +710,14 @@ class JsonParser BASE_EMBEDDED { // Parse JSON input as a single JSON value. // Returns null handle and sets exception if parsing failed. static Handle<Object> Parse(Handle<String> source) { - return JsonParser().ParseJson(source); + if (source->IsExternalTwoByteString()) { + ExternalTwoByteStringUC16CharacterStream stream( + Handle<ExternalTwoByteString>::cast(source), 0, source->length()); + return JsonParser().ParseJson(source, &stream); + } else { + GenericStringUC16CharacterStream stream(source, 0, source->length()); + return JsonParser().ParseJson(source, &stream); + } } private: @@ -710,7 +725,7 @@ class JsonParser BASE_EMBEDDED { ~JsonParser() { } // Parse a string containing a single JSON value. - Handle<Object> ParseJson(Handle<String>); + Handle<Object> ParseJson(Handle<String> script, UC16CharacterStream* source); // 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. diff --git a/deps/v8/src/platform-linux.cc b/deps/v8/src/platform-linux.cc index 46c74b017ff..7efb25de94f 100644 --- a/deps/v8/src/platform-linux.cc +++ b/deps/v8/src/platform-linux.cc @@ -134,9 +134,7 @@ static bool CPUInfoContainsString(const char * search_string) { } bool OS::ArmCpuHasFeature(CpuFeature feature) { - const int max_items = 2; - const char* search_strings[max_items] = { NULL, NULL }; - int search_items = 0; + const char* search_string = NULL; // Simple detection of VFP at runtime for Linux. // It is based on /proc/cpuinfo, which reveals hardware configuration // to user-space applications. According to ARM (mid 2009), no similar @@ -144,25 +142,26 @@ bool OS::ArmCpuHasFeature(CpuFeature feature) { // so it's up to individual OSes to provide such. switch (feature) { case VFP3: - search_strings[0] = "vfpv3"; - // Some old kernels will report vfp for A8, not vfpv3, so we check for - // A8 explicitely. The cpuinfo file report the CPU Part which for Cortex - // A8 is 0xc08. - search_strings[1] = "0xc08"; - search_items = 2; - ASSERT(search_items <= max_items); + search_string = "vfpv3"; break; case ARMv7: - search_strings[0] = "ARMv7" ; - search_items = 1; - ASSERT(search_items <= max_items); + search_string = "ARMv7"; break; default: UNREACHABLE(); } - for (int i = 0; i < search_items; ++i) { - if (CPUInfoContainsString(search_strings[i])) { + if (CPUInfoContainsString(search_string)) { + return true; + } + + if (feature == VFP3) { + // Some old kernels will report vfp not vfpv3. Here we make a last attempt + // to detect vfpv3 by checking for vfp *and* neon, since neon is only + // available on architectures with vfpv3. + // Checking neon on its own is not enough as it is possible to have neon + // without vfp. + if (CPUInfoContainsString("vfp") && CPUInfoContainsString("neon")) { return true; } } diff --git a/deps/v8/src/preparser-api.cc b/deps/v8/src/preparser-api.cc index f096e941b70..cbec9b70961 100644 --- a/deps/v8/src/preparser-api.cc +++ b/deps/v8/src/preparser-api.cc @@ -39,39 +39,121 @@ namespace v8 { namespace internal { // UTF16Buffer based on a v8::UnicodeInputStream. -class InputStreamUTF16Buffer : public UTF16Buffer { +class InputStreamUTF16Buffer : public UC16CharacterStream { public: - explicit InputStreamUTF16Buffer(UnicodeInputStream* stream) - : UTF16Buffer(), - stream_(stream) { } + /* The InputStreamUTF16Buffer maintains an internal buffer + * that is filled in chunks from the UC16CharacterStream. + * It also maintains unlimited pushback capability, but optimized + * for small pushbacks. + * The pushback_buffer_ pointer points to the limit of pushbacks + * in the current buffer. There is room for a few pushback'ed chars before + * the buffer containing the most recently read chunk. If this is overflowed, + * an external buffer is allocated/reused to hold further pushbacks, and + * pushback_buffer_ and buffer_cursor_/buffer_end_ now points to the + * new buffer. When this buffer is read to the end again, the cursor is + * switched back to the internal buffer + */ + explicit InputStreamUTF16Buffer(v8::UnicodeInputStream* stream) + : UC16CharacterStream(), + stream_(stream), + pushback_buffer_(buffer_), + pushback_buffer_end_cache_(NULL), + pushback_buffer_backing_(NULL), + pushback_buffer_backing_size_(0) { + buffer_cursor_ = buffer_end_ = buffer_ + kPushBackSize; + } - virtual ~InputStreamUTF16Buffer() { } + virtual ~InputStreamUTF16Buffer() { + if (pushback_buffer_backing_ != NULL) { + DeleteArray(pushback_buffer_backing_); + } + } - virtual void PushBack(uc32 ch) { - stream_->PushBack(ch); + virtual void PushBack(uc16 ch) { + ASSERT(pos_ > 0); + if (buffer_cursor_ <= pushback_buffer_) { + // No more room in the current buffer to do pushbacks. + if (pushback_buffer_end_cache_ == NULL) { + // We have overflowed the pushback space at the beginning of buffer_. + // Switch to using a separate allocated pushback buffer. + if (pushback_buffer_backing_ == NULL) { + // Allocate a buffer the first time we need it. + pushback_buffer_backing_ = NewArray<uc16>(kPushBackSize); + pushback_buffer_backing_size_ = kPushBackSize; + } + pushback_buffer_ = pushback_buffer_backing_; + pushback_buffer_end_cache_ = buffer_end_; + buffer_end_ = pushback_buffer_backing_ + pushback_buffer_backing_size_; + buffer_cursor_ = buffer_end_ - 1; + } else { + // Hit the bottom of the allocated pushback buffer. + // Double the buffer and continue. + uc16* new_buffer = NewArray<uc16>(pushback_buffer_backing_size_ * 2); + memcpy(new_buffer + pushback_buffer_backing_size_, + pushback_buffer_backing_, + pushback_buffer_backing_size_); + DeleteArray(pushback_buffer_backing_); + buffer_cursor_ = new_buffer + pushback_buffer_backing_size_; + pushback_buffer_backing_ = pushback_buffer_ = new_buffer; + buffer_end_ = pushback_buffer_backing_ + pushback_buffer_backing_size_; + } + } + pushback_buffer_[buffer_cursor_ - pushback_buffer_- 1] = ch; pos_--; } - virtual uc32 Advance() { - uc32 result = stream_->Next(); - if (result >= 0) pos_++; - return result; + protected: + virtual bool ReadBlock() { + if (pushback_buffer_end_cache_ != NULL) { + buffer_cursor_ = buffer_; + buffer_end_ = pushback_buffer_end_cache_; + pushback_buffer_end_cache_ = NULL; + return buffer_end_ > buffer_cursor_; + } + // Copy the top of the buffer into the pushback area. + int32_t value; + uc16* buffer_start = buffer_ + kPushBackSize; + buffer_cursor_ = buffer_end_ = buffer_start; + while ((value = stream_->Next()) >= 0) { + if (value > static_cast<int32_t>(unibrow::Utf8::kMaxThreeByteChar)) { + value = unibrow::Utf8::kBadChar; + } + // buffer_end_ is a const pointer, but buffer_ is writable. + buffer_start[buffer_end_++ - buffer_start] = static_cast<uc16>(value); + if (buffer_end_ == buffer_ + kPushBackSize + kBufferSize) break; + } + return buffer_end_ > buffer_start; } - virtual void SeekForward(int pos) { + virtual unsigned SlowSeekForward(unsigned pos) { // Seeking in the input is not used by preparsing. // It's only used by the real parser based on preparser data. UNIMPLEMENTED(); + return 0; } private: + static const unsigned kBufferSize = 512; + static const unsigned kPushBackSize = 16; v8::UnicodeInputStream* const stream_; + // Buffer holding first kPushBackSize characters of pushback buffer, + // then kBufferSize chars of read-ahead. + // The pushback buffer is only used if pushing back characters past + // the start of a block. + uc16 buffer_[kPushBackSize + kBufferSize]; + // Limit of pushbacks before new allocation is necessary. + uc16* pushback_buffer_; + // Only if that pushback buffer at the start of buffer_ isn't sufficient + // is the following used. + const uc16* pushback_buffer_end_cache_; + uc16* pushback_buffer_backing_; + unsigned pushback_buffer_backing_size_; }; class StandAloneJavaScriptScanner : public JavaScriptScanner { public: - void Initialize(UTF16Buffer* source) { + void Initialize(UC16CharacterStream* source) { source_ = source; literal_flags_ = kLiteralString | kLiteralIdentifier; Init(); @@ -92,7 +174,6 @@ void FatalProcessOutOfMemory(const char* reason) { bool EnableSlowAsserts() { return true; } - } // namespace internal. diff --git a/deps/v8/src/preparser.cc b/deps/v8/src/preparser.cc index 03fc9dcb183..7cce685eee1 100644 --- a/deps/v8/src/preparser.cc +++ b/deps/v8/src/preparser.cc @@ -1078,6 +1078,7 @@ PreParser::Expression PreParser::ParseFunctionLiteral(bool* ok) { Expect(i::Token::RBRACE, CHECK_OK); + // Position right after terminal '}'. int end_pos = scanner_->location().end_pos; log_->LogFunction(function_block_pos, end_pos, function_scope.materialized_literal_count(), diff --git a/deps/v8/src/profile-generator-inl.h b/deps/v8/src/profile-generator-inl.h index 8b5c1e21cb6..3df6af06f61 100644 --- a/deps/v8/src/profile-generator-inl.h +++ b/deps/v8/src/profile-generator-inl.h @@ -122,7 +122,7 @@ CodeEntry* ProfileGenerator::EntryForVMState(StateTag tag) { } -inline uint64_t HeapEntry::id() { +uint64_t HeapEntry::id() { union { Id stored_id; uint64_t returned_id; @@ -146,6 +146,18 @@ void HeapEntriesMap::UpdateEntries(Visitor* visitor) { } } + +bool HeapSnapshotGenerator::ReportProgress(bool force) { + const int kProgressReportGranularity = 10000; + if (control_ != NULL + && (force || progress_counter_ % kProgressReportGranularity == 0)) { + return + control_->ReportProgressValue(progress_counter_, progress_total_) == + v8::ActivityControl::kContinue; + } + return true; +} + } } // namespace v8::internal #endif // ENABLE_LOGGING_AND_PROFILING diff --git a/deps/v8/src/profile-generator.cc b/deps/v8/src/profile-generator.cc index ff4661fbc5e..364f51d4f1c 100644 --- a/deps/v8/src/profile-generator.cc +++ b/deps/v8/src/profile-generator.cc @@ -1382,86 +1382,6 @@ HeapEntry* HeapSnapshot::AddEntry(HeapEntry::Type type, } -void HeapSnapshot::FillReversePostorderIndexes(Vector<HeapEntry*>* entries) { - ClearPaint(); - int current_entry = 0; - List<HeapEntry*> nodes_to_visit; - nodes_to_visit.Add(root()); - root()->paint_reachable(); - while (!nodes_to_visit.is_empty()) { - HeapEntry* entry = nodes_to_visit.last(); - Vector<HeapGraphEdge> children = entry->children(); - bool has_new_edges = false; - for (int i = 0; i < children.length(); ++i) { - if (children[i].type() == HeapGraphEdge::kShortcut) continue; - HeapEntry* child = children[i].to(); - if (!child->painted_reachable()) { - nodes_to_visit.Add(child); - child->paint_reachable(); - has_new_edges = true; - } - } - if (!has_new_edges) { - entry->set_ordered_index(current_entry); - (*entries)[current_entry++] = entry; - nodes_to_visit.RemoveLast(); - } - } - entries->Truncate(current_entry); -} - - -static int Intersect(int i1, int i2, const Vector<HeapEntry*>& dominators) { - int finger1 = i1, finger2 = i2; - while (finger1 != finger2) { - while (finger1 < finger2) finger1 = dominators[finger1]->ordered_index(); - while (finger2 < finger1) finger2 = dominators[finger2]->ordered_index(); - } - return finger1; -} - -// The algorithm is based on the article: -// K. Cooper, T. Harvey and K. Kennedy "A Simple, Fast Dominance Algorithm" -// Softw. Pract. Exper. 4 (2001), pp. 1–10. -void HeapSnapshot::BuildDominatorTree(const Vector<HeapEntry*>& entries, - Vector<HeapEntry*>* dominators) { - if (entries.length() == 0) return; - const int root_index = entries.length() - 1; - for (int i = 0; i < root_index; ++i) (*dominators)[i] = NULL; - (*dominators)[root_index] = entries[root_index]; - bool changed = true; - while (changed) { - changed = false; - for (int i = root_index - 1; i >= 0; --i) { - HeapEntry* new_idom = NULL; - Vector<HeapGraphEdge*> rets = entries[i]->retainers(); - int j = 0; - for (; j < rets.length(); ++j) { - if (rets[j]->type() == HeapGraphEdge::kShortcut) continue; - HeapEntry* ret = rets[j]->From(); - if (dominators->at(ret->ordered_index()) != NULL) { - new_idom = ret; - break; - } - } - for (++j; j < rets.length(); ++j) { - if (rets[j]->type() == HeapGraphEdge::kShortcut) continue; - HeapEntry* ret = rets[j]->From(); - if (dominators->at(ret->ordered_index()) != NULL) { - new_idom = entries[Intersect(ret->ordered_index(), - new_idom->ordered_index(), - *dominators)]; - } - } - if (new_idom != NULL && dominators->at(i) != new_idom) { - (*dominators)[i] = new_idom; - changed = true; - } - } - } -} - - void HeapSnapshot::SetDominatorsToSelf() { for (int i = 0; i < entries_.length(); ++i) { HeapEntry* entry = entries_[i]; @@ -1470,61 +1390,6 @@ void HeapSnapshot::SetDominatorsToSelf() { } -void HeapSnapshot::SetEntriesDominators() { - // This array is used for maintaining reverse postorder of nodes. - ScopedVector<HeapEntry*> ordered_entries(entries_.length()); - FillReversePostorderIndexes(&ordered_entries); - ScopedVector<HeapEntry*> dominators(ordered_entries.length()); - BuildDominatorTree(ordered_entries, &dominators); - for (int i = 0; i < ordered_entries.length(); ++i) { - ASSERT(dominators[i] != NULL); - ordered_entries[i]->set_dominator(dominators[i]); - } - // For nodes unreachable from root, set dominator to itself. - SetDominatorsToSelf(); -} - - -void HeapSnapshot::ApproximateRetainedSizes() { - SetEntriesDominators(); - // As for the dominators tree we only know parent nodes, not - // children, to sum up total sizes we traverse the tree level by - // level upwards, starting from leaves. - for (int i = 0; i < entries_.length(); ++i) { - HeapEntry* entry = entries_[i]; - entry->set_retained_size(entry->self_size()); - entry->set_leaf(); - } - while (true) { - bool onlyLeaves = true; - for (int i = 0; i < entries_.length(); ++i) { - HeapEntry *entry = entries_[i], *dominator = entry->dominator(); - if (!entry->is_processed() && dominator != entry) { - dominator->set_non_leaf(); - onlyLeaves = false; - } - } - if (onlyLeaves) break; - - for (int i = 0; i < entries_.length(); ++i) { - HeapEntry *entry = entries_[i], *dominator = entry->dominator(); - if (entry->is_leaf() && dominator != entry) { - dominator->add_retained_size(entry->retained_size()); - } - } - - // Mark all current leaves as processed, reset non-leaves back to leaves. - for (int i = 0; i < entries_.length(); ++i) { - HeapEntry* entry = entries_[i]; - if (entry->is_leaf()) - entry->set_processed(); - else if (entry->is_non_leaf()) - entry->set_leaf(); - } - } -} - - HeapEntry* HeapSnapshot::GetNextEntryToInit() { if (entries_.length() > 0) { HeapEntry* last_entry = entries_.last(); @@ -1716,15 +1581,22 @@ HeapSnapshot* HeapSnapshotsCollection::NewSnapshot(HeapSnapshot::Type type, const char* name, unsigned uid) { is_tracking_objects_ = true; // Start watching for heap objects moves. - HeapSnapshot* snapshot = new HeapSnapshot(this, type, name, uid); - snapshots_.Add(snapshot); - HashMap::Entry* entry = - snapshots_uids_.Lookup(reinterpret_cast<void*>(snapshot->uid()), - static_cast<uint32_t>(snapshot->uid()), - true); - ASSERT(entry->value == NULL); - entry->value = snapshot; - return snapshot; + return new HeapSnapshot(this, type, name, uid); +} + + +void HeapSnapshotsCollection::SnapshotGenerationFinished( + HeapSnapshot* snapshot) { + ids_.SnapshotGenerationFinished(); + if (snapshot != NULL) { + snapshots_.Add(snapshot); + HashMap::Entry* entry = + snapshots_uids_.Lookup(reinterpret_cast<void*>(snapshot->uid()), + static_cast<uint32_t>(snapshot->uid()), + true); + ASSERT(entry->value == NULL); + entry->value = snapshot; + } } @@ -1832,8 +1704,10 @@ void HeapObjectsSet::Insert(Object* obj) { } -HeapSnapshotGenerator::HeapSnapshotGenerator(HeapSnapshot* snapshot) +HeapSnapshotGenerator::HeapSnapshotGenerator(HeapSnapshot* snapshot, + v8::ActivityControl* control) : snapshot_(snapshot), + control_(control), collection_(snapshot->collection()), filler_(NULL) { } @@ -1990,21 +1864,13 @@ class RootsReferencesExtractor : public ObjectVisitor { }; -void HeapSnapshotGenerator::GenerateSnapshot() { +bool HeapSnapshotGenerator::GenerateSnapshot() { AssertNoAllocation no_alloc; + SetProgressTotal(4); // 2 passes + dominators + sizes. + // Pass 1. Iterate heap contents to count entries and references. - SnapshotCounter counter(&entries_); - filler_ = &counter; - filler_->AddEntry(HeapSnapshot::kInternalRootObject); - filler_->AddEntry(HeapSnapshot::kGcRootsObject); - HeapIterator iterator(HeapIterator::kPreciseFiltering); - for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) { - ExtractReferences(obj); - } - SetRootGcRootsReference(); - RootsReferencesExtractor extractor(this); - Heap::IterateRoots(&extractor, VISIT_ONLY_STRONG); + if (!CountEntriesAndReferences()) return false; // Allocate and fill entries in the snapshot, allocate references. snapshot_->AllocateEntries(entries_.entries_count(), @@ -2014,16 +1880,14 @@ void HeapSnapshotGenerator::GenerateSnapshot() { entries_.UpdateEntries(&allocator); // Pass 2. Fill references. - SnapshotFiller filler(snapshot_, &entries_); - filler_ = &filler; - iterator.reset(); - for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) { - ExtractReferences(obj); - } - SetRootGcRootsReference(); - Heap::IterateRoots(&extractor, VISIT_ONLY_STRONG); + if (!FillReferences()) return false; + + if (!SetEntriesDominators()) return false; + if (!ApproximateRetainedSizes()) return false; - snapshot_->ApproximateRetainedSizes(); + progress_counter_ = progress_total_; + if (!ReportProgress(true)) return false; + return true; } @@ -2351,6 +2215,183 @@ void HeapSnapshotGenerator::SetGcRootsReference(Object* child_obj) { } +void HeapSnapshotGenerator::SetProgressTotal(int iterations_count) { + if (control_ == NULL) return; + + HeapIterator iterator(HeapIterator::kPreciseFiltering); + int objects_count = 0; + for (HeapObject* obj = iterator.next(); + obj != NULL; + obj = iterator.next(), ++objects_count) {} + progress_total_ = objects_count * iterations_count; + progress_counter_ = 0; +} + + +bool HeapSnapshotGenerator::CountEntriesAndReferences() { + SnapshotCounter counter(&entries_); + filler_ = &counter; + filler_->AddEntry(HeapSnapshot::kInternalRootObject); + filler_->AddEntry(HeapSnapshot::kGcRootsObject); + return IterateAndExtractReferences(); +} + + +bool HeapSnapshotGenerator::FillReferences() { + SnapshotFiller filler(snapshot_, &entries_); + filler_ = &filler; + return IterateAndExtractReferences(); +} + + +void HeapSnapshotGenerator::FillReversePostorderIndexes( + Vector<HeapEntry*>* entries) { + snapshot_->ClearPaint(); + int current_entry = 0; + List<HeapEntry*> nodes_to_visit; + nodes_to_visit.Add(snapshot_->root()); + snapshot_->root()->paint_reachable(); + while (!nodes_to_visit.is_empty()) { + HeapEntry* entry = nodes_to_visit.last(); + Vector<HeapGraphEdge> children = entry->children(); + bool has_new_edges = false; + for (int i = 0; i < children.length(); ++i) { + if (children[i].type() == HeapGraphEdge::kShortcut) continue; + HeapEntry* child = children[i].to(); + if (!child->painted_reachable()) { + nodes_to_visit.Add(child); + child->paint_reachable(); + has_new_edges = true; + } + } + if (!has_new_edges) { + entry->set_ordered_index(current_entry); + (*entries)[current_entry++] = entry; + nodes_to_visit.RemoveLast(); + } + } + entries->Truncate(current_entry); +} + + +static int Intersect(int i1, int i2, const Vector<HeapEntry*>& dominators) { + int finger1 = i1, finger2 = i2; + while (finger1 != finger2) { + while (finger1 < finger2) finger1 = dominators[finger1]->ordered_index(); + while (finger2 < finger1) finger2 = dominators[finger2]->ordered_index(); + } + return finger1; +} + +// The algorithm is based on the article: +// K. Cooper, T. Harvey and K. Kennedy "A Simple, Fast Dominance Algorithm" +// Softw. Pract. Exper. 4 (2001), pp. 1–10. +bool HeapSnapshotGenerator::BuildDominatorTree( + const Vector<HeapEntry*>& entries, + Vector<HeapEntry*>* dominators) { + if (entries.length() == 0) return true; + const int entries_length = entries.length(), root_index = entries_length - 1; + for (int i = 0; i < root_index; ++i) (*dominators)[i] = NULL; + (*dominators)[root_index] = entries[root_index]; + int changed = 1; + const int base_progress_counter = progress_counter_; + while (changed != 0) { + changed = 0; + for (int i = root_index - 1; i >= 0; --i) { + HeapEntry* new_idom = NULL; + Vector<HeapGraphEdge*> rets = entries[i]->retainers(); + int j = 0; + for (; j < rets.length(); ++j) { + if (rets[j]->type() == HeapGraphEdge::kShortcut) continue; + HeapEntry* ret = rets[j]->From(); + if (dominators->at(ret->ordered_index()) != NULL) { + new_idom = ret; + break; + } + } + for (++j; j < rets.length(); ++j) { + if (rets[j]->type() == HeapGraphEdge::kShortcut) continue; + HeapEntry* ret = rets[j]->From(); + if (dominators->at(ret->ordered_index()) != NULL) { + new_idom = entries[Intersect(ret->ordered_index(), + new_idom->ordered_index(), + *dominators)]; + } + } + if (new_idom != NULL && dominators->at(i) != new_idom) { + (*dominators)[i] = new_idom; + ++changed; + } + } + int remaining = entries_length - changed; + if (remaining < 0) remaining = 0; + progress_counter_ = base_progress_counter + remaining; + if (!ReportProgress(true)) return false; + } + return true; +} + + +bool HeapSnapshotGenerator::SetEntriesDominators() { + // This array is used for maintaining reverse postorder of nodes. + ScopedVector<HeapEntry*> ordered_entries(snapshot_->entries()->length()); + FillReversePostorderIndexes(&ordered_entries); + ScopedVector<HeapEntry*> dominators(ordered_entries.length()); + if (!BuildDominatorTree(ordered_entries, &dominators)) return false; + for (int i = 0; i < ordered_entries.length(); ++i) { + ASSERT(dominators[i] != NULL); + ordered_entries[i]->set_dominator(dominators[i]); + } + // For nodes unreachable from root, set dominator to itself. + snapshot_->SetDominatorsToSelf(); + return true; +} + + +bool HeapSnapshotGenerator::ApproximateRetainedSizes() { + // As for the dominators tree we only know parent nodes, not + // children, to sum up total sizes we "bubble" node's self size + // adding it to all of its parents. + for (int i = 0; i < snapshot_->entries()->length(); ++i) { + HeapEntry* entry = snapshot_->entries()->at(i); + entry->set_retained_size(entry->self_size()); + } + for (int i = 0; + i < snapshot_->entries()->length(); + ++i, IncProgressCounter()) { + HeapEntry* entry = snapshot_->entries()->at(i); + int entry_size = entry->self_size(); + for (HeapEntry* dominator = entry->dominator(); + dominator != entry; + entry = dominator, dominator = entry->dominator()) { + dominator->add_retained_size(entry_size); + } + if (!ReportProgress()) return false; + } + return true; +} + + +bool HeapSnapshotGenerator::IterateAndExtractReferences() { + HeapIterator iterator(HeapIterator::kPreciseFiltering); + bool interrupted = false; + // Heap iteration with precise filtering must be finished in any case. + for (HeapObject* obj = iterator.next(); + obj != NULL; + obj = iterator.next(), IncProgressCounter()) { + if (!interrupted) { + ExtractReferences(obj); + if (!ReportProgress()) interrupted = true; + } + } + if (interrupted) return false; + SetRootGcRootsReference(); + RootsReferencesExtractor extractor(this); + Heap::IterateRoots(&extractor, VISIT_ONLY_STRONG); + return ReportProgress(); +} + + void HeapSnapshotsDiff::CreateRoots(int additions_count, int deletions_count) { raw_additions_root_ = NewArray<char>(HeapEntry::EntriesSize(1, additions_count, 0)); diff --git a/deps/v8/src/profile-generator.h b/deps/v8/src/profile-generator.h index 16764a214ab..cacd27eaab0 100644 --- a/deps/v8/src/profile-generator.h +++ b/deps/v8/src/profile-generator.h @@ -526,7 +526,7 @@ class HeapEntry BASE_EMBEDDED { HeapSnapshot* snapshot() { return snapshot_; } Type type() { return static_cast<Type>(type_); } const char* name() { return name_; } - uint64_t id(); + inline uint64_t id(); int self_size() { return self_size_; } int retained_size() { return retained_size_; } void add_retained_size(int size) { retained_size_ += size; } @@ -558,13 +558,6 @@ class HeapEntry BASE_EMBEDDED { void ApplyAndPaintAllReachable(Visitor* visitor); void PaintAllReachable(); - bool is_leaf() { return painted_ == kLeaf; } - void set_leaf() { painted_ = kLeaf; } - bool is_non_leaf() { return painted_ == kNonLeaf; } - void set_non_leaf() { painted_ = kNonLeaf; } - bool is_processed() { return painted_ == kProcessed; } - void set_processed() { painted_ = kProcessed; } - void SetIndexedReference(HeapGraphEdge::Type type, int child_index, int index, @@ -625,10 +618,6 @@ class HeapEntry BASE_EMBEDDED { static const unsigned kUnpainted = 0; static const unsigned kPainted = 1; static const unsigned kPaintedReachableFromOthers = 2; - // Paints used for approximate retained sizes calculation. - static const unsigned kLeaf = 0; - static const unsigned kNonLeaf = 1; - static const unsigned kProcessed = 2; static const int kExactRetainedSizeTag = 1; @@ -682,6 +671,7 @@ class HeapSnapshot { unsigned uid() { return uid_; } HeapEntry* root() { return root_entry_; } HeapEntry* gc_roots() { return gc_roots_entry_; } + List<HeapEntry*>* entries() { return &entries_; } void AllocateEntries( int entries_count, int children_count, int retainers_count); @@ -693,7 +683,6 @@ class HeapSnapshot { int size, int children_count, int retainers_count); - void ApproximateRetainedSizes(); void ClearPaint(); HeapSnapshotsDiff* CompareWith(HeapSnapshot* snapshot); HeapEntry* GetEntryById(uint64_t id); @@ -716,10 +705,6 @@ class HeapSnapshot { int children_count, int retainers_count); HeapEntry* GetNextEntryToInit(); - void BuildDominatorTree(const Vector<HeapEntry*>& entries, - Vector<HeapEntry*>* dominators); - void FillReversePostorderIndexes(Vector<HeapEntry*>* entries); - void SetEntriesDominators(); HeapSnapshotsCollection* collection_; Type type_; @@ -845,7 +830,7 @@ class HeapSnapshotsCollection { HeapSnapshot* NewSnapshot( HeapSnapshot::Type type, const char* name, unsigned uid); - void SnapshotGenerationFinished() { ids_.SnapshotGenerationFinished(); } + void SnapshotGenerationFinished(HeapSnapshot* snapshot); List<HeapSnapshot*>* snapshots() { return &snapshots_; } HeapSnapshot* GetSnapshot(unsigned uid); @@ -968,16 +953,27 @@ class HeapSnapshotGenerator { HeapEntry* child_entry) = 0; }; - explicit HeapSnapshotGenerator(HeapSnapshot* snapshot); - void GenerateSnapshot(); + HeapSnapshotGenerator(HeapSnapshot* snapshot, + v8::ActivityControl* control); + bool GenerateSnapshot(); private: + bool ApproximateRetainedSizes(); + bool BuildDominatorTree(const Vector<HeapEntry*>& entries, + Vector<HeapEntry*>* dominators); + bool CountEntriesAndReferences(); HeapEntry* GetEntry(Object* obj); + void IncProgressCounter() { ++progress_counter_; } void ExtractReferences(HeapObject* obj); void ExtractClosureReferences(JSObject* js_obj, HeapEntry* entry); void ExtractPropertyReferences(JSObject* js_obj, HeapEntry* entry); void ExtractElementReferences(JSObject* js_obj, HeapEntry* entry); void ExtractInternalReferences(JSObject* js_obj, HeapEntry* entry); + bool FillReferences(); + void FillReversePostorderIndexes(Vector<HeapEntry*>* entries); + bool IterateAndExtractReferences(); + inline bool ReportProgress(bool force = false); + bool SetEntriesDominators(); void SetClosureReference(HeapObject* parent_obj, HeapEntry* parent, String* reference_name, @@ -1009,8 +1005,10 @@ class HeapSnapshotGenerator { void SetRootShortcutReference(Object* child); void SetRootGcRootsReference(); void SetGcRootsReference(Object* child); + void SetProgressTotal(int iterations_count); HeapSnapshot* snapshot_; + v8::ActivityControl* control_; HeapSnapshotsCollection* collection_; // Mapping from HeapObject* pointers to HeapEntry* pointers. HeapEntriesMap entries_; @@ -1018,6 +1016,9 @@ class HeapSnapshotGenerator { // Used during references extraction to mark heap objects that // are references via non-hidden properties. HeapObjectsSet known_references_; + // Used during snapshot generation. + int progress_counter_; + int progress_total_; friend class IndexedReferencesExtractor; friend class RootsReferencesExtractor; diff --git a/deps/v8/src/regexp.js b/deps/v8/src/regexp.js index d01d04f2e39..dd27266a947 100644 --- a/deps/v8/src/regexp.js +++ b/deps/v8/src/regexp.js @@ -120,22 +120,28 @@ function DoRegExpExec(regexp, string, index) { function BuildResultFromMatchInfo(lastMatchInfo, s) { var numResults = NUMBER_OF_CAPTURES(lastMatchInfo) >> 1; - var result = %_RegExpConstructResult(numResults, lastMatchInfo[CAPTURE0], s); - if (numResults === 1) { - var matchStart = lastMatchInfo[CAPTURE(0)]; - var matchEnd = lastMatchInfo[CAPTURE(1)]; - result[0] = SubString(s, matchStart, matchEnd); + var start = lastMatchInfo[CAPTURE0]; + var end = lastMatchInfo[CAPTURE1]; + var result = %_RegExpConstructResult(numResults, start, s); + if (start + 1 == end) { + result[0] = %_StringCharAt(s, start); } else { - for (var i = 0; i < numResults; i++) { - var matchStart = lastMatchInfo[CAPTURE(i << 1)]; - var matchEnd = lastMatchInfo[CAPTURE((i << 1) + 1)]; - if (matchStart != -1 && matchEnd != -1) { - result[i] = SubString(s, matchStart, matchEnd); + result[0] = %_SubString(s, start, end); + } + var j = REGEXP_FIRST_CAPTURE + 2; + for (var i = 1; i < numResults; i++) { + start = lastMatchInfo[j++]; + end = lastMatchInfo[j++]; + if (end != -1) { + if (start + 1 == end) { + result[i] = %_StringCharAt(s, start); } else { - // Make sure the element is present. Avoid reading the undefined - // property from the global object since this may change. - result[i] = void 0; + result[i] = %_SubString(s, start, end); } + } else { + // Make sure the element is present. Avoid reading the undefined + // property from the global object since this may change. + result[i] = void 0; } } return result; @@ -166,12 +172,7 @@ function RegExpExec(string) { } string = regExpInput; } - var s; - if (IS_STRING(string)) { - s = string; - } else { - s = ToString(string); - } + string = TO_STRING_INLINE(string); var lastIndex = this.lastIndex; // Conversion is required by the ES5 specification (RegExp.prototype.exec @@ -180,7 +181,7 @@ function RegExpExec(string) { var global = this.global; if (global) { - if (i < 0 || i > s.length) { + if (i < 0 || i > string.length) { this.lastIndex = 0; return null; } @@ -188,9 +189,9 @@ function RegExpExec(string) { i = 0; } - %_Log('regexp', 'regexp-exec,%0r,%1S,%2i', [this, s, lastIndex]); + %_Log('regexp', 'regexp-exec,%0r,%1S,%2i', [this, string, lastIndex]); // matchIndices is either null or the lastMatchInfo array. - var matchIndices = %_RegExpExec(this, s, i, lastMatchInfo); + var matchIndices = %_RegExpExec(this, string, i, lastMatchInfo); if (matchIndices === null) { if (global) this.lastIndex = 0; @@ -202,7 +203,7 @@ function RegExpExec(string) { if (global) { this.lastIndex = lastMatchInfo[CAPTURE1]; } - return BuildResultFromMatchInfo(matchIndices, s); + return BuildResultFromMatchInfo(matchIndices, string); } @@ -227,12 +228,7 @@ function RegExpTest(string) { string = regExpInput; } - var s; - if (IS_STRING(string)) { - s = string; - } else { - s = ToString(string); - } + string = TO_STRING_INLINE(string); var lastIndex = this.lastIndex; @@ -241,13 +237,13 @@ function RegExpTest(string) { var i = TO_INTEGER(lastIndex); if (this.global) { - if (i < 0 || i > s.length) { + if (i < 0 || i > string.length) { this.lastIndex = 0; return false; } - %_Log('regexp', 'regexp-exec,%0r,%1S,%2i', [this, s, lastIndex]); + %_Log('regexp', 'regexp-exec,%0r,%1S,%2i', [this, string, lastIndex]); // matchIndices is either null or the lastMatchInfo array. - var matchIndices = %_RegExpExec(this, s, i, lastMatchInfo); + var matchIndices = %_RegExpExec(this, string, i, lastMatchInfo); if (matchIndices === null) { this.lastIndex = 0; return false; @@ -269,11 +265,11 @@ function RegExpTest(string) { (this.ignoreCase ? 'i' : '') + (this.multiline ? 'm' : '')); } - if (!regexp_val.test(s)) return false; + if (!regexp_val.test(string)) return false; } - %_Log('regexp', 'regexp-exec,%0r,%1S,%2i', [this, s, lastIndex]); + %_Log('regexp', 'regexp-exec,%0r,%1S,%2i', [this, string, lastIndex]); // matchIndices is either null or the lastMatchInfo array. - var matchIndices = %_RegExpExec(this, s, 0, lastMatchInfo); + var matchIndices = %_RegExpExec(this, string, 0, lastMatchInfo); if (matchIndices === null) return false; lastMatchInfoOverride = null; return true; diff --git a/deps/v8/src/runtime-profiler.cc b/deps/v8/src/runtime-profiler.cc index 051dc51193b..3c0490f8ded 100644 --- a/deps/v8/src/runtime-profiler.cc +++ b/deps/v8/src/runtime-profiler.cc @@ -68,12 +68,18 @@ class PendingListNode : public Malloced { }; +enum SamplerState { + IN_NON_JS_STATE = 0, + IN_JS_STATE = 1 +}; + + // Optimization sampler constants. static const int kSamplerFrameCount = 2; static const int kSamplerFrameWeight[kSamplerFrameCount] = { 2, 1 }; static const int kSamplerWindowSize = 16; -static const int kSamplerTicksDelta = 32; +static const int kSamplerTicksBetweenThresholdAdjustment = 32; static const int kSamplerThresholdInit = 3; static const int kSamplerThresholdMin = 1; @@ -88,6 +94,11 @@ static const int kSizeLimit = 1500; static int sampler_threshold = kSamplerThresholdInit; static int sampler_threshold_size_factor = kSamplerThresholdSizeFactorInit; +static int sampler_ticks_until_threshold_adjustment = + kSamplerTicksBetweenThresholdAdjustment; + +// The ratio of ticks spent in JS code in percent. +static Atomic32 js_ratio; // The JSFunctions in the sampler window are not GC safe. Old-space // pointers are not cleared during mark-sweep collection and therefore @@ -261,40 +272,71 @@ void RuntimeProfiler::OptimizeNow() { // have a sample of the function, we mark it for optimizations // (eagerly or lazily). JSFunction* samples[kSamplerFrameCount]; - int count = 0; + int sample_count = 0; + int frame_count = 0; for (JavaScriptFrameIterator it; - count < kSamplerFrameCount && !it.done(); + frame_count++ < kSamplerFrameCount && !it.done(); it.Advance()) { JavaScriptFrame* frame = it.frame(); JSFunction* function = JSFunction::cast(frame->function()); - int function_size = function->shared()->SourceSize(); - int threshold_size_factor; - if (function_size > kSizeLimit) { - threshold_size_factor = sampler_threshold_size_factor; - } else { - threshold_size_factor = 1; + + // Adjust threshold each time we have processed + // a certain number of ticks. + if (sampler_ticks_until_threshold_adjustment > 0) { + sampler_ticks_until_threshold_adjustment--; + if (sampler_ticks_until_threshold_adjustment <= 0) { + // If the threshold is not already at the minimum + // modify and reset the ticks until next adjustment. + if (sampler_threshold > kSamplerThresholdMin) { + sampler_threshold -= kSamplerThresholdDelta; + sampler_ticks_until_threshold_adjustment = + kSamplerTicksBetweenThresholdAdjustment; + } + } } - int threshold = sampler_threshold * threshold_size_factor; - samples[count++] = function; if (function->IsMarkedForLazyRecompilation()) { Code* unoptimized = function->shared()->code(); int nesting = unoptimized->allow_osr_at_loop_nesting_level(); if (nesting == 0) AttemptOnStackReplacement(function); int new_nesting = Min(nesting + 1, Code::kMaxLoopNestingMarker); unoptimized->set_allow_osr_at_loop_nesting_level(new_nesting); - } else if (LookupSample(function) >= threshold) { - if (IsOptimizable(function)) { - Optimize(function, false, 0); - CompilationCache::MarkForEagerOptimizing(Handle<JSFunction>(function)); - } + } + + // Do not record non-optimizable functions. + if (!IsOptimizable(function)) continue; + samples[sample_count++] = function; + + int function_size = function->shared()->SourceSize(); + int threshold_size_factor = (function_size > kSizeLimit) + ? sampler_threshold_size_factor + : 1; + + int threshold = sampler_threshold * threshold_size_factor; + int current_js_ratio = NoBarrier_Load(&js_ratio); + + // Adjust threshold depending on the ratio of time spent + // in JS code. + if (current_js_ratio < 20) { + // If we spend less than 20% of the time in JS code, + // do not optimize. + continue; + } else if (current_js_ratio < 75) { + // Below 75% of time spent in JS code, only optimize very + // frequently used functions. + threshold *= 3; + } + + if (LookupSample(function) >= threshold) { + Optimize(function, false, 0); + CompilationCache::MarkForEagerOptimizing(Handle<JSFunction>(function)); } } // Add the collected functions as samples. It's important not to do // this as part of collecting them because this will interfere with // the sample lookup in case of recursive functions. - for (int i = 0; i < count; i++) { + for (int i = 0; i < sample_count; i++) { AddSample(samples[i], kSamplerFrameWeight[i]); } } @@ -308,7 +350,30 @@ void RuntimeProfiler::OptimizeSoon(JSFunction* function) { } +static void UpdateStateRatio(SamplerState current_state) { + static const int kStateWindowSize = 128; + static SamplerState state_window[kStateWindowSize]; + static int state_window_position = 0; + static int state_counts[2] = { kStateWindowSize, 0 }; + + SamplerState old_state = state_window[state_window_position]; + state_counts[old_state]--; + state_window[state_window_position] = current_state; + state_counts[current_state]++; + ASSERT(IsPowerOf2(kStateWindowSize)); + state_window_position = (state_window_position + 1) & + (kStateWindowSize - 1); + NoBarrier_Store(&js_ratio, state_counts[IN_JS_STATE] * 100 / + kStateWindowSize); +} + + void RuntimeProfiler::NotifyTick() { + // Record state sample. + SamplerState state = Top::IsInJSState() + ? IN_JS_STATE + : IN_NON_JS_STATE; + UpdateStateRatio(state); StackGuard::RequestRuntimeProfilerTick(); } @@ -341,6 +406,8 @@ void RuntimeProfiler::Setup() { void RuntimeProfiler::Reset() { sampler_threshold = kSamplerThresholdInit; + sampler_ticks_until_threshold_adjustment = + kSamplerTicksBetweenThresholdAdjustment; sampler_threshold_size_factor = kSamplerThresholdSizeFactorInit; } diff --git a/deps/v8/src/runtime.cc b/deps/v8/src/runtime.cc index add3ad92eaf..bd4b89077c3 100644 --- a/deps/v8/src/runtime.cc +++ b/deps/v8/src/runtime.cc @@ -4689,6 +4689,13 @@ static MaybeObject* QuoteJsonString(Vector<const Char> characters) { if (!new_alloc->ToObject(&new_object)) { return new_alloc; } + if (!Heap::new_space()->Contains(new_object)) { + // Even if our string is small enough to fit in new space we still have to + // handle it being allocated in old space as may happen in the third + // attempt. See CALL_AND_RETRY in heap-inl.h and similar code in + // CEntryStub::GenerateCore. + return SlowQuoteJsonString<Char, StringType>(characters); + } StringType* new_string = StringType::cast(new_object); ASSERT(Heap::new_space()->Contains(new_string)); @@ -4723,9 +4730,9 @@ static MaybeObject* QuoteJsonString(Vector<const Char> characters) { } *(write_cursor++) = '"'; - int final_length = + int final_length = static_cast<int>( write_cursor - reinterpret_cast<Char*>( - new_string->address() + SeqAsciiString::kHeaderSize); + new_string->address() + SeqAsciiString::kHeaderSize)); Heap::new_space()->ShrinkStringAtAllocationBoundary<StringType>(new_string, final_length); return new_string; @@ -6022,37 +6029,6 @@ static MaybeObject* Runtime_Math_log(Arguments args) { } -// Helper function to compute x^y, where y is known to be an -// integer. Uses binary decomposition to limit the number of -// multiplications; see the discussion in "Hacker's Delight" by Henry -// S. Warren, Jr., figure 11-6, page 213. -static double powi(double x, int y) { - ASSERT(y != kMinInt); - unsigned n = (y < 0) ? -y : y; - double m = x; - double p = 1; - while (true) { - if ((n & 1) != 0) p *= m; - n >>= 1; - if (n == 0) { - if (y < 0) { - // Unfortunately, we have to be careful when p has reached - // infinity in the computation, because sometimes the higher - // internal precision in the pow() implementation would have - // given us a finite p. This happens very rarely. - double result = 1.0 / p; - return (result == 0 && isinf(p)) - ? pow(x, static_cast<double>(y)) // Avoid pow(double, int). - : result; - } else { - return p; - } - } - m *= m; - } -} - - static MaybeObject* Runtime_Math_pow(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 2); @@ -6064,31 +6040,11 @@ static MaybeObject* Runtime_Math_pow(Arguments args) { // custom powi() function than the generic pow(). if (args[1]->IsSmi()) { int y = Smi::cast(args[1])->value(); - return Heap::NumberFromDouble(powi(x, y)); + return Heap::NumberFromDouble(power_double_int(x, y)); } CONVERT_DOUBLE_CHECKED(y, args[1]); - - if (!isinf(x)) { - if (y == 0.5) { - // It's not uncommon to use Math.pow(x, 0.5) to compute the - // square root of a number. To speed up such computations, we - // explictly check for this case and use the sqrt() function - // which is faster than pow(). - return Heap::AllocateHeapNumber(sqrt(x)); - } else if (y == -0.5) { - // Optimized using Math.pow(x, -0.5) == 1 / Math.pow(x, 0.5). - return Heap::AllocateHeapNumber(1.0 / sqrt(x)); - } - } - - if (y == 0) { - return Smi::FromInt(1); - } else if (isnan(y) || ((x == 1 || x == -1) && isinf(y))) { - return Heap::nan_value(); - } else { - return Heap::AllocateHeapNumber(pow(x, y)); - } + return Heap::AllocateHeapNumber(power_double_double(x, y)); } // Fast version of Math.pow if we know that y is not an integer and @@ -6099,11 +6055,11 @@ static MaybeObject* Runtime_Math_pow_cfunction(Arguments args) { CONVERT_DOUBLE_CHECKED(x, args[0]); CONVERT_DOUBLE_CHECKED(y, args[1]); if (y == 0) { - return Smi::FromInt(1); + return Smi::FromInt(1); } else if (isnan(y) || ((x == 1 || x == -1) && isinf(y))) { - return Heap::nan_value(); + return Heap::nan_value(); } else { - return Heap::AllocateHeapNumber(pow(x, y)); + return Heap::AllocateHeapNumber(pow(x, y)); } } @@ -7716,13 +7672,13 @@ static MaybeObject* Runtime_AllocateInNewSpace(Arguments args) { } -// Push an array unto an array of arrays if it is not already in the +// Push an object unto an array of objects if it is not already in the // array. Returns true if the element was pushed on the stack and // false otherwise. static MaybeObject* Runtime_PushIfAbsent(Arguments args) { ASSERT(args.length() == 2); CONVERT_CHECKED(JSArray, array, args[0]); - CONVERT_CHECKED(JSArray, element, args[1]); + CONVERT_CHECKED(JSObject, element, args[1]); RUNTIME_ASSERT(array->HasFastElements()); int length = Smi::cast(array->length())->value(); FixedArray* elements = FixedArray::cast(array->elements()); diff --git a/deps/v8/src/scanner-base.cc b/deps/v8/src/scanner-base.cc index 9e58c4e6371..b26fee01a72 100644 --- a/deps/v8/src/scanner-base.cc +++ b/deps/v8/src/scanner-base.cc @@ -35,12 +35,6 @@ namespace v8 { namespace internal { // ---------------------------------------------------------------------------- -// UTF16Buffer - -UTF16Buffer::UTF16Buffer() - : pos_(0), end_(kNoEndPosition) { } - -// ---------------------------------------------------------------------------- // LiteralCollector LiteralCollector::LiteralCollector() @@ -92,7 +86,7 @@ bool ScannerConstants::IsIdentifier(unibrow::CharacterStream* buffer) { // ---------------------------------------------------------------------------- // Scanner -Scanner::Scanner() : source_(NULL) {} +Scanner::Scanner() { } uc32 Scanner::ScanHexEscape(uc32 c, int length) { @@ -142,8 +136,7 @@ uc32 Scanner::ScanOctalEscape(uc32 c, int length) { // ---------------------------------------------------------------------------- // JavaScriptScanner -JavaScriptScanner::JavaScriptScanner() - : has_line_terminator_before_next_(false) {} +JavaScriptScanner::JavaScriptScanner() : Scanner() {} Token::Value JavaScriptScanner::Next() { @@ -503,12 +496,21 @@ void JavaScriptScanner::Scan() { void JavaScriptScanner::SeekForward(int pos) { - source_->SeekForward(pos - 1); - Advance(); - // This function is only called to seek to the location - // of the end of a function (at the "}" token). It doesn't matter - // whether there was a line terminator in the part we skip. - has_line_terminator_before_next_ = false; + // After this call, we will have the token at the given position as + // the "next" token. The "current" token will be invalid. + if (pos == next_.location.beg_pos) return; + int current_pos = source_pos(); + ASSERT_EQ(next_.location.end_pos, current_pos); + // Positions inside the lookahead token aren't supported. + ASSERT(pos >= current_pos); + if (pos != current_pos) { + source_->SeekForward(pos - source_->pos()); + Advance(); + // This function is only called to seek to the location + // of the end of a function (at the "}" token). It doesn't matter + // whether there was a line terminator in the part we skip. + has_line_terminator_before_next_ = false; + } Scan(); } diff --git a/deps/v8/src/scanner-base.h b/deps/v8/src/scanner-base.h index 3d344f306ca..c50b8f3ef62 100644 --- a/deps/v8/src/scanner-base.h +++ b/deps/v8/src/scanner-base.h @@ -52,31 +52,75 @@ inline int HexValue(uc32 c) { return -1; } -// ---------------------------------------------------------------------------- -// UTF16Buffer - scanner input source with pushback. -class UTF16Buffer { +// --------------------------------------------------------------------- +// Buffered stream of characters, using an internal UC16 buffer. + +class UC16CharacterStream { public: - UTF16Buffer(); - virtual ~UTF16Buffer() {} + UC16CharacterStream() : pos_(0) { } + virtual ~UC16CharacterStream() { } + + // Returns and advances past the next UC16 character in the input + // stream. If there are no more characters, it returns a negative + // value. + inline int32_t Advance() { + if (buffer_cursor_ < buffer_end_ || ReadBlock()) { + pos_++; + return *(buffer_cursor_++); + } + // Note: currently the following increment is necessary to avoid a + // parser problem! The scanner treats the final kEndOfInput as + // a character with a position, and does math relative to that + // position. + pos_++; - virtual void PushBack(uc32 ch) = 0; - // Returns a value < 0 when the buffer end is reached. - virtual uc32 Advance() = 0; - virtual void SeekForward(int pos) = 0; + return kEndOfInput; + } - int pos() const { return pos_; } + // Return the current position in the character stream. + // Starts at zero. + inline unsigned pos() const { return pos_; } + + // Skips forward past the next character_count UC16 characters + // in the input, or until the end of input if that comes sooner. + // Returns the number of characters actually skipped. If less + // than character_count, + inline unsigned SeekForward(unsigned character_count) { + unsigned buffered_chars = + static_cast<unsigned>(buffer_end_ - buffer_cursor_); + if (character_count <= buffered_chars) { + buffer_cursor_ += character_count; + pos_ += character_count; + return character_count; + } + return SlowSeekForward(character_count); + } - static const int kNoEndPosition = 1; + // Pushes back the most recently read UC16 character, i.e., + // the value returned by the most recent call to Advance. + // Must not be used right after calling SeekForward. + virtual void PushBack(uc16 character) = 0; protected: - // Initial value of end_ before the input stream is initialized. - - int pos_; // Current position in the buffer. - int end_; // Position where scanning should stop (EOF). + static const int32_t kEndOfInput = -1; + + // Ensures that the buffer_cursor_ points to the character at + // position pos_ of the input, if possible. If the position + // is at or after the end of the input, return false. If there + // are more characters available, return true. + virtual bool ReadBlock() = 0; + virtual unsigned SlowSeekForward(unsigned character_count) = 0; + + const uc16* buffer_cursor_; + const uc16* buffer_end_; + unsigned pos_; }; +// --------------------------------------------------------------------- +// Constants used by scanners. + class ScannerConstants : AllStatic { public: typedef unibrow::Utf8InputBuffer<1024> Utf8Decoder; @@ -277,7 +321,7 @@ class Scanner { // Low-level scanning support. void Advance() { c0_ = source_->Advance(); } void PushBack(uc32 ch) { - source_->PushBack(ch); + source_->PushBack(c0_); c0_ = ch; } @@ -307,8 +351,8 @@ class Scanner { TokenDesc current_; // desc for current token (as returned by Next()) TokenDesc next_; // desc for next token (one token look-ahead) - // Input stream. Must be initialized to an UTF16Buffer. - UTF16Buffer* source_; + // Input stream. Must be initialized to an UC16CharacterStream. + UC16CharacterStream* source_; // Buffer to hold literal values (identifiers, strings, numbers) // using '\x00'-terminated UTF-8 encoding. Handles allocation internally. diff --git a/deps/v8/src/scanner.cc b/deps/v8/src/scanner.cc index d22ebc741fd..47e9895cf42 100755 --- a/deps/v8/src/scanner.cc +++ b/deps/v8/src/scanner.cc @@ -36,63 +36,265 @@ namespace v8 { namespace internal { // ---------------------------------------------------------------------------- -// UTF16Buffer - -// CharacterStreamUTF16Buffer -CharacterStreamUTF16Buffer::CharacterStreamUTF16Buffer() - : pushback_buffer_(0), last_(0), stream_(NULL) { } +// BufferedUC16CharacterStreams + +BufferedUC16CharacterStream::BufferedUC16CharacterStream() + : UC16CharacterStream(), + pushback_limit_(NULL) { + // Initialize buffer as being empty. First read will fill the buffer. + buffer_cursor_ = buffer_; + buffer_end_ = buffer_; +} +BufferedUC16CharacterStream::~BufferedUC16CharacterStream() { } -void CharacterStreamUTF16Buffer::Initialize(Handle<String> data, - unibrow::CharacterStream* input, - int start_position, - int end_position) { - stream_ = input; - if (start_position > 0) { - SeekForward(start_position); +void BufferedUC16CharacterStream::PushBack(uc16 character) { + if (pushback_limit_ == NULL && buffer_cursor_ > buffer_) { + // buffer_ is writable, buffer_cursor_ is const pointer. + buffer_[--buffer_cursor_ - buffer_] = character; + pos_--; + return; } - end_ = end_position != kNoEndPosition ? end_position : kMaxInt; + SlowPushBack(character); } -void CharacterStreamUTF16Buffer::PushBack(uc32 ch) { - pushback_buffer()->Add(last_); - last_ = ch; +void BufferedUC16CharacterStream::SlowPushBack(uc16 character) { + // In pushback mode, the end of the buffer contains pushback, + // and the start of the buffer (from buffer start to pushback_limit_) + // contains valid data that comes just after the pushback. + // We NULL the pushback_limit_ if pushing all the way back to the + // start of the buffer. + + if (pushback_limit_ == NULL) { + // Enter pushback mode. + pushback_limit_ = buffer_end_; + buffer_end_ = buffer_ + kBufferSize; + buffer_cursor_ = buffer_end_; + } + ASSERT(pushback_limit_ > buffer_); + ASSERT(pos_ > 0); + buffer_[--buffer_cursor_ - buffer_] = character; + if (buffer_cursor_ == buffer_) { + pushback_limit_ = NULL; + } else if (buffer_cursor_ < pushback_limit_) { + pushback_limit_ = buffer_cursor_; + } pos_--; } -uc32 CharacterStreamUTF16Buffer::Advance() { - ASSERT(end_ != kNoEndPosition); - ASSERT(end_ >= 0); - // NOTE: It is of importance to Persian / Farsi resources that we do - // *not* strip format control characters in the scanner; see - // - // https://bugzilla.mozilla.org/show_bug.cgi?id=274152 - // - // So, even though ECMA-262, section 7.1, page 11, dictates that we - // must remove Unicode format-control characters, we do not. This is - // in line with how IE and SpiderMonkey handles it. - if (!pushback_buffer()->is_empty()) { - pos_++; - return last_ = pushback_buffer()->RemoveLast(); - } else if (stream_->has_more() && pos_ < end_) { - pos_++; - uc32 next = stream_->GetNext(); - return last_ = next; - } else { - // Note: currently the following increment is necessary to avoid a - // test-parser problem! - pos_++; - return last_ = static_cast<uc32>(-1); +bool BufferedUC16CharacterStream::ReadBlock() { + if (pushback_limit_ != NULL) { + buffer_cursor_ = buffer_; + buffer_end_ = pushback_limit_; + pushback_limit_ = NULL; + ASSERT(buffer_cursor_ != buffer_end_); + return true; } + unsigned length = FillBuffer(pos_, kBufferSize); + buffer_cursor_ = buffer_; + buffer_end_ = buffer_ + length; + return length > 0; } -void CharacterStreamUTF16Buffer::SeekForward(int pos) { - pos_ = pos; - ASSERT(pushback_buffer()->is_empty()); - stream_->Seek(pos); +unsigned BufferedUC16CharacterStream::SlowSeekForward(unsigned delta) { + // Leave pushback mode (i.e., ignore that there might be valid data + // in the buffer before the pushback_limit_ point). + pushback_limit_ = NULL; + return BufferSeekForward(delta); +} + +// ---------------------------------------------------------------------------- +// GenericStringUC16CharacterStream + + +GenericStringUC16CharacterStream::GenericStringUC16CharacterStream( + Handle<String> data, + unsigned start_position, + unsigned end_position) + : string_(data), + length_(end_position) { + ASSERT(end_position >= start_position); + buffer_cursor_ = buffer_; + buffer_end_ = buffer_; + pos_ = start_position; +} + + +GenericStringUC16CharacterStream::~GenericStringUC16CharacterStream() { } + + +unsigned GenericStringUC16CharacterStream::BufferSeekForward(unsigned delta) { + unsigned old_pos = pos_; + pos_ = Min(pos_ + delta, length_); + ReadBlock(); + return pos_ - old_pos; +} + + +unsigned GenericStringUC16CharacterStream::FillBuffer(unsigned from_pos, + unsigned length) { + if (from_pos >= length_) return 0; + if (from_pos + length > length_) { + length = length_ - from_pos; + } + String::WriteToFlat<uc16>(*string_, buffer_, from_pos, from_pos + length); + return length; +} + + +// ---------------------------------------------------------------------------- +// Utf8ToUC16CharacterStream +Utf8ToUC16CharacterStream::Utf8ToUC16CharacterStream(const byte* data, + unsigned length) + : BufferedUC16CharacterStream(), + raw_data_(data), + raw_data_length_(length), + raw_data_pos_(0), + raw_character_position_(0) { + ReadBlock(); +} + + +Utf8ToUC16CharacterStream::~Utf8ToUC16CharacterStream() { } + + +unsigned Utf8ToUC16CharacterStream::BufferSeekForward(unsigned delta) { + unsigned old_pos = pos_; + unsigned target_pos = pos_ + delta; + SetRawPosition(target_pos); + pos_ = raw_character_position_; + ReadBlock(); + return pos_ - old_pos; +} + + +unsigned Utf8ToUC16CharacterStream::FillBuffer(unsigned char_position, + unsigned length) { + static const unibrow::uchar kMaxUC16Character = 0xffff; + SetRawPosition(char_position); + if (raw_character_position_ != char_position) { + // char_position was not a valid position in the stream (hit the end + // while spooling to it). + return 0u; + } + unsigned i = 0; + while (i < length) { + if (raw_data_pos_ == raw_data_length_) break; + unibrow::uchar c = raw_data_[raw_data_pos_]; + if (c <= unibrow::Utf8::kMaxOneByteChar) { + raw_data_pos_++; + } else { + c = unibrow::Utf8::CalculateValue(raw_data_ + raw_data_pos_, + raw_data_length_ - raw_data_pos_, + &raw_data_pos_); + // Don't allow characters outside of the BMP. + if (c > kMaxUC16Character) { + c = unibrow::Utf8::kBadChar; + } + } + buffer_[i++] = static_cast<uc16>(c); + } + raw_character_position_ = char_position + i; + return i; +} + + +static const byte kUtf8MultiByteMask = 0xC0; +static const byte kUtf8MultiByteCharStart = 0xC0; +static const byte kUtf8MultiByteCharFollower = 0x80; + + +#ifdef DEBUG +static bool IsUtf8MultiCharacterStart(byte first_byte) { + return (first_byte & kUtf8MultiByteMask) == kUtf8MultiByteCharStart; +} +#endif + + +static bool IsUtf8MultiCharacterFollower(byte later_byte) { + return (later_byte & kUtf8MultiByteMask) == kUtf8MultiByteCharFollower; +} + + +// Move the cursor back to point at the preceding UTF-8 character start +// in the buffer. +static inline void Utf8CharacterBack(const byte* buffer, unsigned* cursor) { + byte character = buffer[--*cursor]; + if (character > unibrow::Utf8::kMaxOneByteChar) { + ASSERT(IsUtf8MultiCharacterFollower(character)); + // Last byte of a multi-byte character encoding. Step backwards until + // pointing to the first byte of the encoding, recognized by having the + // top two bits set. + while (IsUtf8MultiCharacterFollower(buffer[--*cursor])) { } + ASSERT(IsUtf8MultiCharacterStart(buffer[*cursor])); + } +} + + +// Move the cursor forward to point at the next following UTF-8 character start +// in the buffer. +static inline void Utf8CharacterForward(const byte* buffer, unsigned* cursor) { + byte character = buffer[(*cursor)++]; + if (character > unibrow::Utf8::kMaxOneByteChar) { + // First character of a multi-byte character encoding. + // The number of most-significant one-bits determines the length of the + // encoding: + // 110..... - (0xCx, 0xDx) one additional byte (minimum). + // 1110.... - (0xEx) two additional bytes. + // 11110... - (0xFx) three additional bytes (maximum). + ASSERT(IsUtf8MultiCharacterStart(character)); + // Additional bytes is: + // 1 if value in range 0xC0 .. 0xDF. + // 2 if value in range 0xE0 .. 0xEF. + // 3 if value in range 0xF0 .. 0xF7. + // Encode that in a single value. + unsigned additional_bytes = + ((0x3211u) >> (((character - 0xC0) >> 2) & 0xC)) & 0x03; + *cursor += additional_bytes; + ASSERT(!IsUtf8MultiCharacterFollower(buffer[1 + additional_bytes])); + } +} + + +void Utf8ToUC16CharacterStream::SetRawPosition(unsigned target_position) { + if (raw_character_position_ > target_position) { + // Spool backwards in utf8 buffer. + do { + Utf8CharacterBack(raw_data_, &raw_data_pos_); + raw_character_position_--; + } while (raw_character_position_ > target_position); + return; + } + // Spool forwards in the utf8 buffer. + while (raw_character_position_ < target_position) { + if (raw_data_pos_ == raw_data_length_) return; + Utf8CharacterForward(raw_data_, &raw_data_pos_); + raw_character_position_++; + } +} + + +// ---------------------------------------------------------------------------- +// ExternalTwoByteStringUC16CharacterStream + +ExternalTwoByteStringUC16CharacterStream:: + ~ExternalTwoByteStringUC16CharacterStream() { } + + +ExternalTwoByteStringUC16CharacterStream + ::ExternalTwoByteStringUC16CharacterStream( + Handle<ExternalTwoByteString> data, + int start_position, + int end_position) + : UC16CharacterStream(), + source_(data), + raw_data_(data->GetTwoByteData(start_position)) { + buffer_cursor_ = raw_data_, + buffer_end_ = raw_data_ + (end_position - start_position); + pos_ = start_position; } @@ -115,46 +317,19 @@ void Scanner::LiteralScope::Complete() { complete_ = true; } + // ---------------------------------------------------------------------------- // V8JavaScriptScanner -void V8JavaScriptScanner::Initialize(Handle<String> source, - int literal_flags) { - source_ = stream_initializer_.Init(source, NULL, 0, source->length()); - // Need to capture identifiers in order to recognize "get" and "set" - // in object literals. - literal_flags_ = literal_flags | kLiteralIdentifier; - Init(); - // Skip initial whitespace allowing HTML comment ends just like - // after a newline and scan first token. - has_line_terminator_before_next_ = true; - SkipWhiteSpace(); - Scan(); -} - - -void V8JavaScriptScanner::Initialize(Handle<String> source, - unibrow::CharacterStream* stream, - int literal_flags) { - source_ = stream_initializer_.Init(source, stream, - 0, UTF16Buffer::kNoEndPosition); - literal_flags_ = literal_flags | kLiteralIdentifier; - Init(); - // Skip initial whitespace allowing HTML comment ends just like - // after a newline and scan first token. - has_line_terminator_before_next_ = true; - SkipWhiteSpace(); - Scan(); -} +V8JavaScriptScanner::V8JavaScriptScanner() : JavaScriptScanner() { } -void V8JavaScriptScanner::Initialize(Handle<String> source, - int start_position, - int end_position, +void V8JavaScriptScanner::Initialize(UC16CharacterStream* source, int literal_flags) { - source_ = stream_initializer_.Init(source, NULL, - start_position, end_position); + source_ = source; literal_flags_ = literal_flags | kLiteralIdentifier; + // Need to capture identifiers in order to recognize "get" and "set" + // in object literals. Init(); // Skip initial whitespace allowing HTML comment ends just like // after a newline and scan first token. @@ -164,48 +339,14 @@ void V8JavaScriptScanner::Initialize(Handle<String> source, } -UTF16Buffer* StreamInitializer::Init(Handle<String> source, - unibrow::CharacterStream* stream, - int start_position, - int end_position) { - // Either initialize the scanner from a character stream or from a - // string. - ASSERT(source.is_null() || stream == NULL); - - // Initialize the source buffer. - if (!source.is_null() && StringShape(*source).IsExternalTwoByte()) { - two_byte_string_buffer_.Initialize( - Handle<ExternalTwoByteString>::cast(source), - start_position, - end_position); - return &two_byte_string_buffer_; - } else if (!source.is_null() && StringShape(*source).IsExternalAscii()) { - ascii_string_buffer_.Initialize( - Handle<ExternalAsciiString>::cast(source), - start_position, - end_position); - return &ascii_string_buffer_; - } else { - if (!source.is_null()) { - safe_string_input_buffer_.Reset(source.location()); - stream = &safe_string_input_buffer_; - } - char_stream_buffer_.Initialize(source, - stream, - start_position, - end_position); - return &char_stream_buffer_; - } -} - // ---------------------------------------------------------------------------- // JsonScanner -JsonScanner::JsonScanner() {} +JsonScanner::JsonScanner() : Scanner() { } -void JsonScanner::Initialize(Handle<String> source) { - source_ = stream_initializer_.Init(source, NULL, 0, source->length()); +void JsonScanner::Initialize(UC16CharacterStream* source) { + source_ = source; Init(); // Skip initial whitespace. SkipJsonWhiteSpace(); diff --git a/deps/v8/src/scanner.h b/deps/v8/src/scanner.h index adeea9b23a0..572778f8ac4 100644 --- a/deps/v8/src/scanner.h +++ b/deps/v8/src/scanner.h @@ -35,67 +35,97 @@ namespace v8 { namespace internal { -// UTF16 buffer to read characters from a character stream. -class CharacterStreamUTF16Buffer: public UTF16Buffer { +// A buffered character stream based on a random access character +// source (ReadBlock can be called with pos_ pointing to any position, +// even positions before the current). +class BufferedUC16CharacterStream: public UC16CharacterStream { public: - CharacterStreamUTF16Buffer(); - virtual ~CharacterStreamUTF16Buffer() {} - void Initialize(Handle<String> data, - unibrow::CharacterStream* stream, - int start_position, - int end_position); - virtual void PushBack(uc32 ch); - virtual uc32 Advance(); - virtual void SeekForward(int pos); - - private: - List<uc32> pushback_buffer_; - uc32 last_; - unibrow::CharacterStream* stream_; - - List<uc32>* pushback_buffer() { return &pushback_buffer_; } + BufferedUC16CharacterStream(); + virtual ~BufferedUC16CharacterStream(); + + virtual void PushBack(uc16 character); + + protected: + static const unsigned kBufferSize = 512; + static const unsigned kPushBackStepSize = 16; + + virtual unsigned SlowSeekForward(unsigned delta); + virtual bool ReadBlock(); + virtual void SlowPushBack(uc16 character); + + virtual unsigned BufferSeekForward(unsigned delta) = 0; + virtual unsigned FillBuffer(unsigned position, unsigned length) = 0; + + const uc16* pushback_limit_; + uc16 buffer_[kBufferSize]; }; -// UTF16 buffer to read characters from an external string. -template <typename StringType, typename CharType> -class ExternalStringUTF16Buffer: public UTF16Buffer { +// Generic string stream. +class GenericStringUC16CharacterStream: public BufferedUC16CharacterStream { public: - ExternalStringUTF16Buffer(); - virtual ~ExternalStringUTF16Buffer() {} - void Initialize(Handle<StringType> data, - int start_position, - int end_position); - virtual void PushBack(uc32 ch); - virtual uc32 Advance(); - virtual void SeekForward(int pos); - - private: - const CharType* raw_data_; // Pointer to the actual array of characters. + GenericStringUC16CharacterStream(Handle<String> data, + unsigned start_position, + unsigned end_position); + virtual ~GenericStringUC16CharacterStream(); + + protected: + virtual unsigned BufferSeekForward(unsigned delta); + virtual unsigned FillBuffer(unsigned position, unsigned length); + + Handle<String> string_; + unsigned start_position_; + unsigned length_; }; -// Initializes a UTF16Buffer as input stream, using one of a number -// of strategies depending on the available character sources. -class StreamInitializer { +// UC16 stream based on a literal UTF-8 string. +class Utf8ToUC16CharacterStream: public BufferedUC16CharacterStream { public: - UTF16Buffer* Init(Handle<String> source, - unibrow::CharacterStream* stream, - int start_position, - int end_position); - private: - // Different UTF16 buffers used to pull characters from. Based on input one of - // these will be initialized as the actual data source. - CharacterStreamUTF16Buffer char_stream_buffer_; - ExternalStringUTF16Buffer<ExternalTwoByteString, uint16_t> - two_byte_string_buffer_; - ExternalStringUTF16Buffer<ExternalAsciiString, char> ascii_string_buffer_; - - // Used to convert the source string into a character stream when a stream - // is not passed to the scanner. - SafeStringInputBuffer safe_string_input_buffer_; + Utf8ToUC16CharacterStream(const byte* data, unsigned length); + virtual ~Utf8ToUC16CharacterStream(); + + protected: + virtual unsigned BufferSeekForward(unsigned delta); + virtual unsigned FillBuffer(unsigned char_position, unsigned length); + void SetRawPosition(unsigned char_position); + + const byte* raw_data_; + unsigned raw_data_length_; // Measured in bytes, not characters. + unsigned raw_data_pos_; + // The character position of the character at raw_data[raw_data_pos_]. + // Not necessarily the same as pos_. + unsigned raw_character_position_; +}; + + +// UTF16 buffer to read characters from an external string. +class ExternalTwoByteStringUC16CharacterStream: public UC16CharacterStream { + public: + ExternalTwoByteStringUC16CharacterStream(Handle<ExternalTwoByteString> data, + int start_position, + int end_position); + virtual ~ExternalTwoByteStringUC16CharacterStream(); + + virtual void PushBack(uc16 character) { + ASSERT(buffer_cursor_ > raw_data_); + buffer_cursor_--; + pos_--; + } + protected: + virtual unsigned SlowSeekForward(unsigned delta) { + // Fast case always handles seeking. + return 0; + } + virtual bool ReadBlock() { + // Entire string is read at start. + return false; + } + Handle<ExternalTwoByteString> source_; + const uc16* raw_data_; // Pointer to the actual array of characters. }; + // ---------------------------------------------------------------------------- // V8JavaScriptScanner // JavaScript scanner getting its input from either a V8 String or a unicode @@ -103,19 +133,9 @@ class StreamInitializer { class V8JavaScriptScanner : public JavaScriptScanner { public: - V8JavaScriptScanner() {} - - // Initialize the Scanner to scan source. - void Initialize(Handle<String> source, int literal_flags = kAllLiterals); - void Initialize(Handle<String> source, - unibrow::CharacterStream* stream, - int literal_flags = kAllLiterals); - void Initialize(Handle<String> source, - int start_position, int end_position, + V8JavaScriptScanner(); + void Initialize(UC16CharacterStream* source, int literal_flags = kAllLiterals); - - protected: - StreamInitializer stream_initializer_; }; @@ -123,8 +143,7 @@ class JsonScanner : public Scanner { public: JsonScanner(); - // Initialize the Scanner to scan source. - void Initialize(Handle<String> source); + void Initialize(UC16CharacterStream* source); // Returns the next token. Token::Value Next(); @@ -138,7 +157,7 @@ class JsonScanner : public Scanner { // Recognizes all of the single-character tokens directly, or calls a function // to scan a number, string or identifier literal. // The only allowed whitespace characters between tokens are tab, - // carrige-return, newline and space. + // carriage-return, newline and space. void ScanJson(); // A JSON number (production JSONNumber) is a subset of the valid JavaScript @@ -159,60 +178,8 @@ class JsonScanner : public Scanner { // are the only valid JSON identifiers (productions JSONBooleanLiteral, // JSONNullLiteral). Token::Value ScanJsonIdentifier(const char* text, Token::Value token); - - StreamInitializer stream_initializer_; }; - -// ExternalStringUTF16Buffer -template <typename StringType, typename CharType> -ExternalStringUTF16Buffer<StringType, CharType>::ExternalStringUTF16Buffer() - : raw_data_(NULL) { } - - -template <typename StringType, typename CharType> -void ExternalStringUTF16Buffer<StringType, CharType>::Initialize( - Handle<StringType> data, - int start_position, - int end_position) { - ASSERT(!data.is_null()); - raw_data_ = data->resource()->data(); - - ASSERT(end_position <= data->length()); - if (start_position > 0) { - SeekForward(start_position); - } - end_ = - end_position != kNoEndPosition ? end_position : data->length(); -} - - -template <typename StringType, typename CharType> -uc32 ExternalStringUTF16Buffer<StringType, CharType>::Advance() { - if (pos_ < end_) { - return raw_data_[pos_++]; - } else { - // note: currently the following increment is necessary to avoid a - // test-parser problem! - pos_++; - return static_cast<uc32>(-1); - } -} - - -template <typename StringType, typename CharType> -void ExternalStringUTF16Buffer<StringType, CharType>::PushBack(uc32 ch) { - pos_--; - ASSERT(pos_ >= Scanner::kCharacterLookaheadBufferSize); - ASSERT(raw_data_[pos_ - Scanner::kCharacterLookaheadBufferSize] == ch); -} - - -template <typename StringType, typename CharType> -void ExternalStringUTF16Buffer<StringType, CharType>::SeekForward(int pos) { - pos_ = pos; -} - } } // namespace v8::internal #endif // V8_SCANNER_H_ diff --git a/deps/v8/src/serialize.cc b/deps/v8/src/serialize.cc index 6edc4fae813..00a601ffd95 100644 --- a/deps/v8/src/serialize.cc +++ b/deps/v8/src/serialize.cc @@ -486,6 +486,18 @@ void ExternalReferenceTable::PopulateTable() { UNCLASSIFIED, 36, "LDoubleConstant::one_half"); + Add(ExternalReference::address_of_negative_infinity().address(), + UNCLASSIFIED, + 37, + "LDoubleConstant::negative_infinity"); + Add(ExternalReference::power_double_double_function().address(), + UNCLASSIFIED, + 38, + "power_double_double_function"); + Add(ExternalReference::power_double_int_function().address(), + UNCLASSIFIED, + 39, + "power_double_int_function"); } diff --git a/deps/v8/src/spaces.cc b/deps/v8/src/spaces.cc index 369eb6fbda5..cdc682f879b 100644 --- a/deps/v8/src/spaces.cc +++ b/deps/v8/src/spaces.cc @@ -917,7 +917,7 @@ AtomicWord* MemoryAllocator::AllocatedChunksFinder( } more_fine_grained_table = new AtomicWord[words_needed]; for (int i = 0; i < words_needed; i++) { - more_fine_grained_table[i] = NULL; + more_fine_grained_table[i] = kUnusedChunkTableEntry; } Release_Store(&table[index], reinterpret_cast<AtomicWord>(more_fine_grained_table)); diff --git a/deps/v8/src/string.js b/deps/v8/src/string.js index 3b3c82bb721..576ffc85d84 100644 --- a/deps/v8/src/string.js +++ b/deps/v8/src/string.js @@ -101,28 +101,28 @@ function StringConcat() { // ECMA-262 section 15.5.4.7 -function StringIndexOf(searchString /* position */) { // length == 1 - var subject_str = TO_STRING_INLINE(this); - var pattern_str = TO_STRING_INLINE(searchString); - var subject_str_len = subject_str.length; - var pattern_str_len = pattern_str.length; +function StringIndexOf(pattern /* position */) { // length == 1 + var subject = TO_STRING_INLINE(this); + var pattern = TO_STRING_INLINE(pattern); + var subject_len = subject.length; + var pattern_len = pattern.length; var index = 0; if (%_ArgumentsLength() > 1) { var arg1 = %_Arguments(1); // position index = TO_INTEGER(arg1); } if (index < 0) index = 0; - if (index > subject_str_len) index = subject_str_len; - if (pattern_str_len + index > subject_str_len) return -1; - return %StringIndexOf(subject_str, pattern_str, index); + if (index > subject_len) index = subject_len; + if (pattern_len + index > subject_len) return -1; + return %StringIndexOf(subject, pattern, index); } // ECMA-262 section 15.5.4.8 -function StringLastIndexOf(searchString /* position */) { // length == 1 +function StringLastIndexOf(pat /* position */) { // length == 1 var sub = TO_STRING_INLINE(this); var subLength = sub.length; - var pat = TO_STRING_INLINE(searchString); + var pat = TO_STRING_INLINE(pat); var patLength = pat.length; var index = subLength - patLength; if (%_ArgumentsLength() > 1) { @@ -150,10 +150,8 @@ function StringLastIndexOf(searchString /* position */) { // length == 1 // do anything locale specific. function StringLocaleCompare(other) { if (%_ArgumentsLength() === 0) return 0; - - var this_str = TO_STRING_INLINE(this); - var other_str = TO_STRING_INLINE(other); - return %StringLocaleCompare(this_str, other_str); + return %StringLocaleCompare(TO_STRING_INLINE(this), + TO_STRING_INLINE(other)); } @@ -177,9 +175,7 @@ function StringMatch(regexp) { // otherwise we call the runtime system. function SubString(string, start, end) { // Use the one character string cache. - if (start + 1 == end) { - return %_StringCharAt(string, start); - } + if (start + 1 == end) return %_StringCharAt(string, start); return %_SubString(string, start, end); } @@ -208,7 +204,10 @@ function StringReplace(search, replace) { replace); } } else { - return StringReplaceRegExp(subject, search, replace); + return %StringReplaceRegExpWithString(subject, + search, + TO_STRING_INLINE(replace), + lastMatchInfo); } } @@ -224,7 +223,11 @@ function StringReplace(search, replace) { // Compute the string to replace with. if (IS_FUNCTION(replace)) { - builder.add(replace.call(null, search, start, subject)); + builder.add(%_CallFunction(%GetGlobalReceiver(), + search, + start, + subject, + replace)); } else { reusableMatchInfo[CAPTURE0] = start; reusableMatchInfo[CAPTURE1] = end; @@ -239,15 +242,6 @@ function StringReplace(search, replace) { } -// Helper function for regular expressions in String.prototype.replace. -function StringReplaceRegExp(subject, regexp, replace) { - return %StringReplaceRegExpWithString(subject, - regexp, - TO_STRING_INLINE(replace), - lastMatchInfo); -} - - // Expand the $-expressions in the string and return a new string with // the result. function ExpandReplacement(string, subject, matchInfo, builder) { @@ -408,9 +402,7 @@ function StringReplaceGlobalRegExpWithFunction(subject, regexp, replace) { lastMatchInfoOverride = override; var func_result = %_CallFunction(receiver, elem, match_start, subject, replace); - if (!IS_STRING(func_result)) { - func_result = NonStringToString(func_result); - } + func_result = TO_STRING_INLINE(func_result); res[i] = func_result; match_start += elem.length; } @@ -424,9 +416,7 @@ function StringReplaceGlobalRegExpWithFunction(subject, regexp, replace) { // Use the apply argument as backing for global RegExp properties. lastMatchInfoOverride = elem; var func_result = replace.apply(null, elem); - if (!IS_STRING(func_result)) { - func_result = NonStringToString(func_result); - } + func_result = TO_STRING_INLINE(func_result); res[i] = func_result; } i++; @@ -487,8 +477,7 @@ function StringSearch(re) { } else { regexp = new $RegExp(re); } - var s = TO_STRING_INLINE(this); - var match = DoRegExpExec(regexp, s, 0); + var match = DoRegExpExec(regexp, TO_STRING_INLINE(this), 0); if (match) { return match[CAPTURE0]; } @@ -576,14 +565,14 @@ function StringSplit(separator, limit) { while (true) { if (startIndex === length) { - result[result.length] = subject.slice(currentIndex, length); + result.push(subject.slice(currentIndex, length)); break; } var matchInfo = splitMatch(separator, subject, currentIndex, startIndex); if (IS_NULL(matchInfo)) { - result[result.length] = subject.slice(currentIndex, length); + result.push(subject.slice(currentIndex, length)); break; } @@ -595,17 +584,21 @@ function StringSplit(separator, limit) { continue; } - result[result.length] = SubString(subject, currentIndex, matchInfo[CAPTURE0]); + result.push(SubString(subject, currentIndex, matchInfo[CAPTURE0])); if (result.length === limit) break; - var num_captures = NUMBER_OF_CAPTURES(matchInfo); - for (var i = 2; i < num_captures; i += 2) { - var start = matchInfo[CAPTURE(i)]; - var end = matchInfo[CAPTURE(i + 1)]; - if (start != -1 && end != -1) { - result[result.length] = SubString(subject, start, end); + var matchinfo_len = NUMBER_OF_CAPTURES(matchInfo) + REGEXP_FIRST_CAPTURE; + for (var i = REGEXP_FIRST_CAPTURE + 2; i < matchinfo_len; ) { + var start = matchInfo[i++]; + var end = matchInfo[i++]; + if (end != -1) { + if (start + 1 == end) { + result.push(%_StringCharAt(subject, start)); + } else { + result.push(%_SubString(subject, start, end)); + } } else { - result[result.length] = void 0; + result.push(void 0); } if (result.length === limit) break outer_loop; } @@ -656,7 +649,9 @@ function StringSubstring(start, end) { } } - return SubString(s, start_i, end_i); + return (start_i + 1 == end_i + ? %_StringCharAt(s, start_i) + : %_SubString(s, start_i, end_i)); } @@ -694,7 +689,9 @@ function StringSubstr(start, n) { var end = start + len; if (end > s.length) end = s.length; - return SubString(s, start, end); + return (start + 1 == end + ? %_StringCharAt(s, start) + : %_SubString(s, start, end)); } diff --git a/deps/v8/src/v8natives.js b/deps/v8/src/v8natives.js index 50a2774d122..8e057037e4c 100644 --- a/deps/v8/src/v8natives.js +++ b/deps/v8/src/v8natives.js @@ -615,7 +615,13 @@ function DefineOwnProperty(obj, p, desc, should_throw) { } else { flag |= READ_ONLY; } - %DefineOrRedefineDataProperty(obj, p, desc.getValue(), flag); + var value = void 0; // Default value is undefined. + if (desc.hasValue()) { + value = desc.getValue(); + } else if (!IS_UNDEFINED(current)) { + value = current.getValue(); + } + %DefineOrRedefineDataProperty(obj, p, value, flag); } else { if (desc.hasGetter() && IS_FUNCTION(desc.getGet())) { %DefineOrRedefineAccessorProperty(obj, p, GETTER, desc.getGet(), flag); diff --git a/deps/v8/src/v8preparserdll-main.cc b/deps/v8/src/v8preparserdll-main.cc new file mode 100644 index 00000000000..c0344d344ab --- /dev/null +++ b/deps/v8/src/v8preparserdll-main.cc @@ -0,0 +1,39 @@ +// 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: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include <windows.h> + +#include "../include/v8-preparser.h" + +extern "C" { +BOOL WINAPI DllMain(HANDLE hinstDLL, + DWORD dwReason, + LPVOID lpvReserved) { + // Do nothing. + return TRUE; +} +} diff --git a/deps/v8/src/version.cc b/deps/v8/src/version.cc index d2166b4db62..7db4a4126ec 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 3 #define MINOR_VERSION 0 -#define BUILD_NUMBER 0 -#define PATCH_LEVEL 1 +#define BUILD_NUMBER 1 +#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 540593fef5d..456d0765b92 100644 --- a/deps/v8/src/x64/builtins-x64.cc +++ b/deps/v8/src/x64/builtins-x64.cc @@ -30,11 +30,13 @@ #if defined(V8_TARGET_ARCH_X64) #include "codegen-inl.h" -#include "macro-assembler.h" +#include "deoptimizer.h" +#include "full-codegen.h" namespace v8 { namespace internal { + #define __ ACCESS_MASM(masm) @@ -71,118 +73,509 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm, } -static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) { - __ push(rbp); - __ movq(rbp, rsp); +void Builtins::Generate_JSConstructCall(MacroAssembler* masm) { + // ----------- S t a t e ------------- + // -- rax: number of arguments + // -- rdi: constructor function + // ----------------------------------- - // Store the arguments adaptor context sentinel. - __ Push(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); + Label non_function_call; + // Check that function is not a smi. + __ JumpIfSmi(rdi, &non_function_call); + // Check that function is a JSFunction. + __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); + __ j(not_equal, &non_function_call); - // Push the function on the stack. - __ push(rdi); + // Jump to the function-specific construct stub. + __ movq(rbx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); + __ movq(rbx, FieldOperand(rbx, SharedFunctionInfo::kConstructStubOffset)); + __ lea(rbx, FieldOperand(rbx, Code::kHeaderSize)); + __ jmp(rbx); - // Preserve the number of arguments on the stack. Must preserve both - // rax and rbx because these registers are used when copying the - // arguments and the receiver. - __ Integer32ToSmi(rcx, rax); - __ push(rcx); + // rdi: called object + // rax: number of arguments + __ bind(&non_function_call); + // Set expected number of arguments to zero (not changing rax). + __ movq(rbx, Immediate(0)); + __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR); + __ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)), + RelocInfo::CODE_TARGET); } -static void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) { - // Retrieve the number of arguments from the stack. Number is a Smi. - __ movq(rbx, Operand(rbp, ArgumentsAdaptorFrameConstants::kLengthOffset)); +static void Generate_JSConstructStubHelper(MacroAssembler* masm, + bool is_api_function, + bool count_constructions) { + // Should never count constructions for api objects. + ASSERT(!is_api_function || !count_constructions); - // Leave the frame. - __ movq(rsp, rbp); - __ pop(rbp); + // Enter a construct frame. + __ EnterConstructFrame(); - // Remove caller arguments from the stack. + // Store a smi-tagged arguments count on the stack. + __ Integer32ToSmi(rax, rax); + __ push(rax); + + // Push the function to invoke on the stack. + __ push(rdi); + + // Try to allocate the object without transitioning into C code. If any of the + // preconditions is not met, the code bails out to the runtime call. + Label rt_call, allocated; + if (FLAG_inline_new) { + Label undo_allocation; + +#ifdef ENABLE_DEBUGGER_SUPPORT + ExternalReference debug_step_in_fp = + ExternalReference::debug_step_in_fp_address(); + __ movq(kScratchRegister, debug_step_in_fp); + __ cmpq(Operand(kScratchRegister, 0), Immediate(0)); + __ j(not_equal, &rt_call); +#endif + + // Verified that the constructor is a JSFunction. + // Load the initial map and verify that it is in fact a map. + // rdi: constructor + __ movq(rax, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset)); + // Will both indicate a NULL and a Smi + ASSERT(kSmiTag == 0); + __ JumpIfSmi(rax, &rt_call); + // rdi: constructor + // rax: initial map (if proven valid below) + __ CmpObjectType(rax, MAP_TYPE, rbx); + __ j(not_equal, &rt_call); + + // Check that the constructor is not constructing a JSFunction (see comments + // in Runtime_NewObject in runtime.cc). In which case the initial map's + // instance type would be JS_FUNCTION_TYPE. + // rdi: constructor + // rax: initial map + __ CmpInstanceType(rax, JS_FUNCTION_TYPE); + __ j(equal, &rt_call); + + if (count_constructions) { + Label allocate; + // Decrease generous allocation count. + __ movq(rcx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); + __ decb(FieldOperand(rcx, SharedFunctionInfo::kConstructionCountOffset)); + __ j(not_zero, &allocate); + + __ push(rax); + __ push(rdi); + + __ push(rdi); // constructor + // The call will replace the stub, so the countdown is only done once. + __ CallRuntime(Runtime::kFinalizeInstanceSize, 1); + + __ pop(rdi); + __ pop(rax); + + __ bind(&allocate); + } + + // Now allocate the JSObject on the heap. + __ movzxbq(rdi, FieldOperand(rax, Map::kInstanceSizeOffset)); + __ shl(rdi, Immediate(kPointerSizeLog2)); + // rdi: size of new object + __ AllocateInNewSpace(rdi, + rbx, + rdi, + no_reg, + &rt_call, + NO_ALLOCATION_FLAGS); + // Allocated the JSObject, now initialize the fields. + // rax: initial map + // rbx: JSObject (not HeapObject tagged - the actual address). + // rdi: start of next object + __ movq(Operand(rbx, JSObject::kMapOffset), rax); + __ LoadRoot(rcx, Heap::kEmptyFixedArrayRootIndex); + __ movq(Operand(rbx, JSObject::kPropertiesOffset), rcx); + __ movq(Operand(rbx, JSObject::kElementsOffset), rcx); + // Set extra fields in the newly allocated object. + // rax: initial map + // rbx: JSObject + // rdi: start of next object + { Label loop, entry; + // To allow for truncation. + if (count_constructions) { + __ LoadRoot(rdx, Heap::kOnePointerFillerMapRootIndex); + } else { + __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex); + } + __ lea(rcx, Operand(rbx, JSObject::kHeaderSize)); + __ jmp(&entry); + __ bind(&loop); + __ movq(Operand(rcx, 0), rdx); + __ addq(rcx, Immediate(kPointerSize)); + __ bind(&entry); + __ cmpq(rcx, rdi); + __ j(less, &loop); + } + + // Add the object tag to make the JSObject real, so that we can continue and + // jump into the continuation code at any time from now on. Any failures + // need to undo the allocation, so that the heap is in a consistent state + // and verifiable. + // rax: initial map + // rbx: JSObject + // rdi: start of next object + __ or_(rbx, Immediate(kHeapObjectTag)); + + // Check if a non-empty properties array is needed. + // Allocate and initialize a FixedArray if it is. + // rax: initial map + // rbx: JSObject + // rdi: start of next object + // Calculate total properties described map. + __ movzxbq(rdx, FieldOperand(rax, Map::kUnusedPropertyFieldsOffset)); + __ movzxbq(rcx, FieldOperand(rax, Map::kPreAllocatedPropertyFieldsOffset)); + __ addq(rdx, rcx); + // Calculate unused properties past the end of the in-object properties. + __ movzxbq(rcx, FieldOperand(rax, Map::kInObjectPropertiesOffset)); + __ subq(rdx, rcx); + // Done if no extra properties are to be allocated. + __ j(zero, &allocated); + __ Assert(positive, "Property allocation count failed."); + + // Scale the number of elements by pointer size and add the header for + // FixedArrays to the start of the next object calculation from above. + // rbx: JSObject + // rdi: start of next object (will be start of FixedArray) + // rdx: number of elements in properties array + __ AllocateInNewSpace(FixedArray::kHeaderSize, + times_pointer_size, + rdx, + rdi, + rax, + no_reg, + &undo_allocation, + RESULT_CONTAINS_TOP); + + // Initialize the FixedArray. + // rbx: JSObject + // rdi: FixedArray + // rdx: number of elements + // rax: start of next object + __ LoadRoot(rcx, Heap::kFixedArrayMapRootIndex); + __ movq(Operand(rdi, HeapObject::kMapOffset), rcx); // setup the map + __ Integer32ToSmi(rdx, rdx); + __ movq(Operand(rdi, FixedArray::kLengthOffset), rdx); // and length + + // Initialize the fields to undefined. + // rbx: JSObject + // rdi: FixedArray + // rax: start of next object + // rdx: number of elements + { Label loop, entry; + __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex); + __ lea(rcx, Operand(rdi, FixedArray::kHeaderSize)); + __ jmp(&entry); + __ bind(&loop); + __ movq(Operand(rcx, 0), rdx); + __ addq(rcx, Immediate(kPointerSize)); + __ bind(&entry); + __ cmpq(rcx, rax); + __ j(below, &loop); + } + + // Store the initialized FixedArray into the properties field of + // the JSObject + // rbx: JSObject + // rdi: FixedArray + __ or_(rdi, Immediate(kHeapObjectTag)); // add the heap tag + __ movq(FieldOperand(rbx, JSObject::kPropertiesOffset), rdi); + + + // Continue with JSObject being successfully allocated + // rbx: JSObject + __ jmp(&allocated); + + // Undo the setting of the new top so that the heap is verifiable. For + // example, the map's unused properties potentially do not match the + // allocated objects unused properties. + // rbx: JSObject (previous new top) + __ bind(&undo_allocation); + __ UndoAllocationInNewSpace(rbx); + } + + // Allocate the new receiver object using the runtime call. + // rdi: function (constructor) + __ bind(&rt_call); + // Must restore rdi (constructor) before calling runtime. + __ movq(rdi, Operand(rsp, 0)); + __ push(rdi); + __ CallRuntime(Runtime::kNewObject, 1); + __ movq(rbx, rax); // store result in rbx + + // New object allocated. + // rbx: newly allocated object + __ bind(&allocated); + // Retrieve the function from the stack. + __ pop(rdi); + + // Retrieve smi-tagged arguments count from the stack. + __ movq(rax, Operand(rsp, 0)); + __ SmiToInteger32(rax, rax); + + // Push the allocated receiver to the stack. We need two copies + // because we may have to return the original one and the calling + // conventions dictate that the called function pops the receiver. + __ push(rbx); + __ push(rbx); + + // Setup pointer to last argument. + __ lea(rbx, Operand(rbp, StandardFrameConstants::kCallerSPOffset)); + + // Copy arguments and receiver to the expression stack. + Label loop, entry; + __ movq(rcx, rax); + __ jmp(&entry); + __ bind(&loop); + __ push(Operand(rbx, rcx, times_pointer_size, 0)); + __ bind(&entry); + __ decq(rcx); + __ j(greater_equal, &loop); + + // Call the function. + if (is_api_function) { + __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); + Handle<Code> code = Handle<Code>( + Builtins::builtin(Builtins::HandleApiCallConstruct)); + ParameterCount expected(0); + __ InvokeCode(code, expected, expected, + RelocInfo::CODE_TARGET, CALL_FUNCTION); + } else { + ParameterCount actual(rax); + __ InvokeFunction(rdi, actual, CALL_FUNCTION); + } + + // Restore context from the frame. + __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); + + // If the result is an object (in the ECMA sense), we should get rid + // of the receiver and use the result; see ECMA-262 section 13.2.2-7 + // on page 74. + Label use_receiver, exit; + // If the result is a smi, it is *not* an object in the ECMA sense. + __ JumpIfSmi(rax, &use_receiver); + + // If the type of the result (stored in its map) is less than + // FIRST_JS_OBJECT_TYPE, it is not an object in the ECMA sense. + __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rcx); + __ j(above_equal, &exit); + + // Throw away the result of the constructor invocation and use the + // on-stack receiver as the result. + __ bind(&use_receiver); + __ movq(rax, Operand(rsp, 0)); + + // Restore the arguments count and leave the construct frame. + __ bind(&exit); + __ movq(rbx, Operand(rsp, kPointerSize)); // get arguments count + __ LeaveConstructFrame(); + + // Remove caller arguments from the stack and return. __ pop(rcx); SmiIndex index = masm->SmiToIndex(rbx, rbx, kPointerSizeLog2); __ lea(rsp, Operand(rsp, index.reg, index.scale, 1 * kPointerSize)); __ push(rcx); + __ IncrementCounter(&Counters::constructed_objects, 1); + __ ret(0); } -void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { - // ----------- S t a t e ------------- - // -- rax : actual number of arguments - // -- rbx : expected number of arguments - // -- rdx : code entry to call - // ----------------------------------- +void Builtins::Generate_JSConstructStubCountdown(MacroAssembler* masm) { + Generate_JSConstructStubHelper(masm, false, true); +} - Label invoke, dont_adapt_arguments; - __ IncrementCounter(&Counters::arguments_adaptors, 1); - Label enough, too_few; - __ cmpq(rax, rbx); - __ j(less, &too_few); - __ cmpq(rbx, Immediate(SharedFunctionInfo::kDontAdaptArgumentsSentinel)); - __ j(equal, &dont_adapt_arguments); +void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { + Generate_JSConstructStubHelper(masm, false, false); +} - { // Enough parameters: Actual >= expected. - __ bind(&enough); - EnterArgumentsAdaptorFrame(masm); - // Copy receiver and all expected arguments. - const int offset = StandardFrameConstants::kCallerSPOffset; - __ lea(rax, Operand(rbp, rax, times_pointer_size, offset)); - __ movq(rcx, Immediate(-1)); // account for receiver +void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { + Generate_JSConstructStubHelper(masm, true, false); +} - Label copy; - __ bind(©); - __ incq(rcx); - __ push(Operand(rax, 0)); - __ subq(rax, Immediate(kPointerSize)); - __ cmpq(rcx, rbx); - __ j(less, ©); - __ jmp(&invoke); - } - { // Too few parameters: Actual < expected. - __ bind(&too_few); - EnterArgumentsAdaptorFrame(masm); +static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, + bool is_construct) { + // Expects five C++ function parameters. + // - Address entry (ignored) + // - JSFunction* function ( + // - Object* receiver + // - int argc + // - Object*** argv + // (see Handle::Invoke in execution.cc). - // Copy receiver and all actual arguments. - const int offset = StandardFrameConstants::kCallerSPOffset; - __ lea(rdi, Operand(rbp, rax, times_pointer_size, offset)); - __ movq(rcx, Immediate(-1)); // account for receiver + // Platform specific argument handling. After this, the stack contains + // an internal frame and the pushed function and receiver, and + // register rax and rbx holds the argument count and argument array, + // while rdi holds the function pointer and rsi the context. +#ifdef _WIN64 + // MSVC parameters in: + // rcx : entry (ignored) + // rdx : function + // r8 : receiver + // r9 : argc + // [rsp+0x20] : argv - Label copy; - __ bind(©); - __ incq(rcx); - __ push(Operand(rdi, 0)); - __ subq(rdi, Immediate(kPointerSize)); - __ cmpq(rcx, rax); - __ j(less, ©); + // Clear the context before we push it when entering the JS frame. + __ xor_(rsi, rsi); + __ EnterInternalFrame(); - // Fill remaining expected arguments with undefined values. - Label fill; - __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex); - __ bind(&fill); - __ incq(rcx); - __ push(kScratchRegister); - __ cmpq(rcx, rbx); - __ j(less, &fill); + // Load the function context into rsi. + __ movq(rsi, FieldOperand(rdx, JSFunction::kContextOffset)); - // Restore function pointer. - __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); + // Push the function and the receiver onto the stack. + __ push(rdx); + __ push(r8); + + // Load the number of arguments and setup pointer to the arguments. + __ movq(rax, r9); + // Load the previous frame pointer to access C argument on stack + __ movq(kScratchRegister, Operand(rbp, 0)); + __ movq(rbx, Operand(kScratchRegister, EntryFrameConstants::kArgvOffset)); + // Load the function pointer into rdi. + __ movq(rdi, rdx); +#else // _WIN64 + // GCC parameters in: + // rdi : entry (ignored) + // rsi : function + // rdx : receiver + // rcx : argc + // r8 : argv + + __ movq(rdi, rsi); + // rdi : function + + // Clear the context before we push it when entering the JS frame. + __ xor_(rsi, rsi); + // Enter an internal frame. + __ EnterInternalFrame(); + + // Push the function and receiver and setup the context. + __ push(rdi); + __ push(rdx); + __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); + + // Load the number of arguments and setup pointer to the arguments. + __ movq(rax, rcx); + __ movq(rbx, r8); +#endif // _WIN64 + + // Current stack contents: + // [rsp + 2 * kPointerSize ... ]: Internal frame + // [rsp + kPointerSize] : function + // [rsp] : receiver + // Current register contents: + // rax : argc + // rbx : argv + // rsi : context + // rdi : function + + // Copy arguments to the stack in a loop. + // Register rbx points to array of pointers to handle locations. + // Push the values of these handles. + Label loop, entry; + __ xor_(rcx, rcx); // Set loop variable to 0. + __ jmp(&entry); + __ bind(&loop); + __ movq(kScratchRegister, Operand(rbx, rcx, times_pointer_size, 0)); + __ push(Operand(kScratchRegister, 0)); // dereference handle + __ addq(rcx, Immediate(1)); + __ bind(&entry); + __ cmpq(rcx, rax); + __ j(not_equal, &loop); + + // Invoke the code. + if (is_construct) { + // Expects rdi to hold function pointer. + __ Call(Handle<Code>(Builtins::builtin(Builtins::JSConstructCall)), + RelocInfo::CODE_TARGET); + } else { + ParameterCount actual(rax); + // Function must be in rdi. + __ InvokeFunction(rdi, actual, CALL_FUNCTION); } - // Call the entry point. - __ bind(&invoke); - __ call(rdx); + // Exit the JS frame. Notice that this also removes the empty + // context and the function left on the stack by the code + // invocation. + __ LeaveInternalFrame(); + // TODO(X64): Is argument correct? Is there a receiver to remove? + __ ret(1 * kPointerSize); // remove receiver +} - // Leave frame and return. - LeaveArgumentsAdaptorFrame(masm); - __ ret(0); - // ------------------------------------------- - // Dont adapt arguments. - // ------------------------------------------- - __ bind(&dont_adapt_arguments); - __ jmp(rdx); +void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) { + Generate_JSEntryTrampolineHelper(masm, false); +} + + +void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) { + Generate_JSEntryTrampolineHelper(masm, true); +} + + +void Builtins::Generate_LazyCompile(MacroAssembler* masm) { + // Enter an internal frame. + __ EnterInternalFrame(); + + // Push a copy of the function onto the stack. + __ push(rdi); + + __ push(rdi); // Function is also the parameter to the runtime call. + __ CallRuntime(Runtime::kLazyCompile, 1); + __ pop(rdi); + + // Tear down temporary frame. + __ LeaveInternalFrame(); + + // Do a tail-call of the compiled function. + __ lea(rcx, FieldOperand(rax, Code::kHeaderSize)); + __ jmp(rcx); +} + + +void Builtins::Generate_LazyRecompile(MacroAssembler* masm) { + // Enter an internal frame. + __ EnterInternalFrame(); + + // Push a copy of the function onto the stack. + __ push(rdi); + + __ push(rdi); // Function is also the parameter to the runtime call. + __ CallRuntime(Runtime::kLazyRecompile, 1); + + // Restore function and tear down temporary frame. + __ pop(rdi); + __ LeaveInternalFrame(); + + // Do a tail-call of the compiled function. + __ lea(rcx, FieldOperand(rax, Code::kHeaderSize)); + __ jmp(rcx); +} + + +static void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm, + Deoptimizer::BailoutType type) { + __ int3(); +} + +void Builtins::Generate_NotifyDeoptimized(MacroAssembler* masm) { + Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::EAGER); +} + + +void Builtins::Generate_NotifyLazyDeoptimized(MacroAssembler* masm) { + Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::EAGER); +} + + +void Builtins::Generate_NotifyOSR(MacroAssembler* masm) { + __ int3(); } @@ -450,17 +843,6 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) { } -// Load the built-in Array function from the current context. -static void GenerateLoadArrayFunction(MacroAssembler* masm, Register result) { - // Load the global context. - __ movq(result, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX))); - __ movq(result, FieldOperand(result, GlobalObject::kGlobalContextOffset)); - // Load the Array function from the global context. - __ movq(result, - Operand(result, Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX))); -} - - // Number of empty elements to allocate for an empty array. static const int kPreallocatedArrayElements = 4; @@ -813,7 +1195,7 @@ void Builtins::Generate_ArrayCode(MacroAssembler* masm) { Label generic_array_code; // Get the Array function. - GenerateLoadArrayFunction(masm, rdi); + __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, rdi); if (FLAG_debug_code) { // Initial map for the builtin Array function shoud be a map. @@ -850,7 +1232,7 @@ void Builtins::Generate_ArrayConstructCode(MacroAssembler* masm) { if (FLAG_debug_code) { // The array construct code is only set for the builtin Array function which // does always have a map. - GenerateLoadArrayFunction(masm, rbx); + __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, rbx); __ cmpq(rdi, rbx); __ Check(equal, "Unexpected Array function"); // Initial map for the builtin Array function should be a map. @@ -882,504 +1264,118 @@ void Builtins::Generate_StringConstructCode(MacroAssembler* masm) { } -void Builtins::Generate_JSConstructCall(MacroAssembler* masm) { - // ----------- S t a t e ------------- - // -- rax: number of arguments - // -- rdi: constructor function - // ----------------------------------- - - Label non_function_call; - // Check that function is not a smi. - __ JumpIfSmi(rdi, &non_function_call); - // Check that function is a JSFunction. - __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); - __ j(not_equal, &non_function_call); - - // Jump to the function-specific construct stub. - __ movq(rbx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); - __ movq(rbx, FieldOperand(rbx, SharedFunctionInfo::kConstructStubOffset)); - __ lea(rbx, FieldOperand(rbx, Code::kHeaderSize)); - __ jmp(rbx); - - // rdi: called object - // rax: number of arguments - __ bind(&non_function_call); - // Set expected number of arguments to zero (not changing rax). - __ movq(rbx, Immediate(0)); - __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR); - __ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)), - RelocInfo::CODE_TARGET); -} - - -static void Generate_JSConstructStubHelper(MacroAssembler* masm, - bool is_api_function, - bool count_constructions) { - // Should never count constructions for api objects. - ASSERT(!is_api_function || !count_constructions); - - // Enter a construct frame. - __ EnterConstructFrame(); - - // Store a smi-tagged arguments count on the stack. - __ Integer32ToSmi(rax, rax); - __ push(rax); - - // Push the function to invoke on the stack. - __ push(rdi); - - // Try to allocate the object without transitioning into C code. If any of the - // preconditions is not met, the code bails out to the runtime call. - Label rt_call, allocated; - if (FLAG_inline_new) { - Label undo_allocation; - -#ifdef ENABLE_DEBUGGER_SUPPORT - ExternalReference debug_step_in_fp = - ExternalReference::debug_step_in_fp_address(); - __ movq(kScratchRegister, debug_step_in_fp); - __ cmpq(Operand(kScratchRegister, 0), Immediate(0)); - __ j(not_equal, &rt_call); -#endif - - // Verified that the constructor is a JSFunction. - // Load the initial map and verify that it is in fact a map. - // rdi: constructor - __ movq(rax, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset)); - // Will both indicate a NULL and a Smi - ASSERT(kSmiTag == 0); - __ JumpIfSmi(rax, &rt_call); - // rdi: constructor - // rax: initial map (if proven valid below) - __ CmpObjectType(rax, MAP_TYPE, rbx); - __ j(not_equal, &rt_call); - - // Check that the constructor is not constructing a JSFunction (see comments - // in Runtime_NewObject in runtime.cc). In which case the initial map's - // instance type would be JS_FUNCTION_TYPE. - // rdi: constructor - // rax: initial map - __ CmpInstanceType(rax, JS_FUNCTION_TYPE); - __ j(equal, &rt_call); - - if (count_constructions) { - Label allocate; - // Decrease generous allocation count. - __ movq(rcx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); - __ decb(FieldOperand(rcx, SharedFunctionInfo::kConstructionCountOffset)); - __ j(not_zero, &allocate); - - __ push(rax); - __ push(rdi); - - __ push(rdi); // constructor - // The call will replace the stub, so the countdown is only done once. - __ CallRuntime(Runtime::kFinalizeInstanceSize, 1); - - __ pop(rdi); - __ pop(rax); - - __ bind(&allocate); - } - - // Now allocate the JSObject on the heap. - __ movzxbq(rdi, FieldOperand(rax, Map::kInstanceSizeOffset)); - __ shl(rdi, Immediate(kPointerSizeLog2)); - // rdi: size of new object - __ AllocateInNewSpace(rdi, - rbx, - rdi, - no_reg, - &rt_call, - NO_ALLOCATION_FLAGS); - // Allocated the JSObject, now initialize the fields. - // rax: initial map - // rbx: JSObject (not HeapObject tagged - the actual address). - // rdi: start of next object - __ movq(Operand(rbx, JSObject::kMapOffset), rax); - __ LoadRoot(rcx, Heap::kEmptyFixedArrayRootIndex); - __ movq(Operand(rbx, JSObject::kPropertiesOffset), rcx); - __ movq(Operand(rbx, JSObject::kElementsOffset), rcx); - // Set extra fields in the newly allocated object. - // rax: initial map - // rbx: JSObject - // rdi: start of next object - { Label loop, entry; - // To allow for truncation. - if (count_constructions) { - __ LoadRoot(rdx, Heap::kOnePointerFillerMapRootIndex); - } else { - __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex); - } - __ lea(rcx, Operand(rbx, JSObject::kHeaderSize)); - __ jmp(&entry); - __ bind(&loop); - __ movq(Operand(rcx, 0), rdx); - __ addq(rcx, Immediate(kPointerSize)); - __ bind(&entry); - __ cmpq(rcx, rdi); - __ j(less, &loop); - } - - // Add the object tag to make the JSObject real, so that we can continue and - // jump into the continuation code at any time from now on. Any failures - // need to undo the allocation, so that the heap is in a consistent state - // and verifiable. - // rax: initial map - // rbx: JSObject - // rdi: start of next object - __ or_(rbx, Immediate(kHeapObjectTag)); - - // Check if a non-empty properties array is needed. - // Allocate and initialize a FixedArray if it is. - // rax: initial map - // rbx: JSObject - // rdi: start of next object - // Calculate total properties described map. - __ movzxbq(rdx, FieldOperand(rax, Map::kUnusedPropertyFieldsOffset)); - __ movzxbq(rcx, FieldOperand(rax, Map::kPreAllocatedPropertyFieldsOffset)); - __ addq(rdx, rcx); - // Calculate unused properties past the end of the in-object properties. - __ movzxbq(rcx, FieldOperand(rax, Map::kInObjectPropertiesOffset)); - __ subq(rdx, rcx); - // Done if no extra properties are to be allocated. - __ j(zero, &allocated); - __ Assert(positive, "Property allocation count failed."); - - // Scale the number of elements by pointer size and add the header for - // FixedArrays to the start of the next object calculation from above. - // rbx: JSObject - // rdi: start of next object (will be start of FixedArray) - // rdx: number of elements in properties array - __ AllocateInNewSpace(FixedArray::kHeaderSize, - times_pointer_size, - rdx, - rdi, - rax, - no_reg, - &undo_allocation, - RESULT_CONTAINS_TOP); - - // Initialize the FixedArray. - // rbx: JSObject - // rdi: FixedArray - // rdx: number of elements - // rax: start of next object - __ LoadRoot(rcx, Heap::kFixedArrayMapRootIndex); - __ movq(Operand(rdi, HeapObject::kMapOffset), rcx); // setup the map - __ Integer32ToSmi(rdx, rdx); - __ movq(Operand(rdi, FixedArray::kLengthOffset), rdx); // and length - - // Initialize the fields to undefined. - // rbx: JSObject - // rdi: FixedArray - // rax: start of next object - // rdx: number of elements - { Label loop, entry; - __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex); - __ lea(rcx, Operand(rdi, FixedArray::kHeaderSize)); - __ jmp(&entry); - __ bind(&loop); - __ movq(Operand(rcx, 0), rdx); - __ addq(rcx, Immediate(kPointerSize)); - __ bind(&entry); - __ cmpq(rcx, rax); - __ j(below, &loop); - } - - // Store the initialized FixedArray into the properties field of - // the JSObject - // rbx: JSObject - // rdi: FixedArray - __ or_(rdi, Immediate(kHeapObjectTag)); // add the heap tag - __ movq(FieldOperand(rbx, JSObject::kPropertiesOffset), rdi); - - - // Continue with JSObject being successfully allocated - // rbx: JSObject - __ jmp(&allocated); +static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) { + __ push(rbp); + __ movq(rbp, rsp); - // Undo the setting of the new top so that the heap is verifiable. For - // example, the map's unused properties potentially do not match the - // allocated objects unused properties. - // rbx: JSObject (previous new top) - __ bind(&undo_allocation); - __ UndoAllocationInNewSpace(rbx); - } + // Store the arguments adaptor context sentinel. + __ Push(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); - // Allocate the new receiver object using the runtime call. - // rdi: function (constructor) - __ bind(&rt_call); - // Must restore rdi (constructor) before calling runtime. - __ movq(rdi, Operand(rsp, 0)); + // Push the function on the stack. __ push(rdi); - __ CallRuntime(Runtime::kNewObject, 1); - __ movq(rbx, rax); // store result in rbx - - // New object allocated. - // rbx: newly allocated object - __ bind(&allocated); - // Retrieve the function from the stack. - __ pop(rdi); - // Retrieve smi-tagged arguments count from the stack. - __ movq(rax, Operand(rsp, 0)); - __ SmiToInteger32(rax, rax); - - // Push the allocated receiver to the stack. We need two copies - // because we may have to return the original one and the calling - // conventions dictate that the called function pops the receiver. - __ push(rbx); - __ push(rbx); - - // Setup pointer to last argument. - __ lea(rbx, Operand(rbp, StandardFrameConstants::kCallerSPOffset)); - - // Copy arguments and receiver to the expression stack. - Label loop, entry; - __ movq(rcx, rax); - __ jmp(&entry); - __ bind(&loop); - __ push(Operand(rbx, rcx, times_pointer_size, 0)); - __ bind(&entry); - __ decq(rcx); - __ j(greater_equal, &loop); - - // Call the function. - if (is_api_function) { - __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); - Handle<Code> code = Handle<Code>( - Builtins::builtin(Builtins::HandleApiCallConstruct)); - ParameterCount expected(0); - __ InvokeCode(code, expected, expected, - RelocInfo::CODE_TARGET, CALL_FUNCTION); - } else { - ParameterCount actual(rax); - __ InvokeFunction(rdi, actual, CALL_FUNCTION); - } - - // Restore context from the frame. - __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); + // Preserve the number of arguments on the stack. Must preserve both + // rax and rbx because these registers are used when copying the + // arguments and the receiver. + __ Integer32ToSmi(rcx, rax); + __ push(rcx); +} - // If the result is an object (in the ECMA sense), we should get rid - // of the receiver and use the result; see ECMA-262 section 13.2.2-7 - // on page 74. - Label use_receiver, exit; - // If the result is a smi, it is *not* an object in the ECMA sense. - __ JumpIfSmi(rax, &use_receiver); - // If the type of the result (stored in its map) is less than - // FIRST_JS_OBJECT_TYPE, it is not an object in the ECMA sense. - __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rcx); - __ j(above_equal, &exit); - - // Throw away the result of the constructor invocation and use the - // on-stack receiver as the result. - __ bind(&use_receiver); - __ movq(rax, Operand(rsp, 0)); +static void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) { + // Retrieve the number of arguments from the stack. Number is a Smi. + __ movq(rbx, Operand(rbp, ArgumentsAdaptorFrameConstants::kLengthOffset)); - // Restore the arguments count and leave the construct frame. - __ bind(&exit); - __ movq(rbx, Operand(rsp, kPointerSize)); // get arguments count - __ LeaveConstructFrame(); + // Leave the frame. + __ movq(rsp, rbp); + __ pop(rbp); - // Remove caller arguments from the stack and return. + // Remove caller arguments from the stack. __ pop(rcx); SmiIndex index = masm->SmiToIndex(rbx, rbx, kPointerSizeLog2); __ lea(rsp, Operand(rsp, index.reg, index.scale, 1 * kPointerSize)); __ push(rcx); - __ IncrementCounter(&Counters::constructed_objects, 1); - __ ret(0); -} - - -void Builtins::Generate_JSConstructStubCountdown(MacroAssembler* masm) { - Generate_JSConstructStubHelper(masm, false, true); } -void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { - Generate_JSConstructStubHelper(masm, false, false); -} - - -void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { - Generate_JSConstructStubHelper(masm, true, false); -} - - -static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, - bool is_construct) { - // Expects five C++ function parameters. - // - Address entry (ignored) - // - JSFunction* function ( - // - Object* receiver - // - int argc - // - Object*** argv - // (see Handle::Invoke in execution.cc). - - // Platform specific argument handling. After this, the stack contains - // an internal frame and the pushed function and receiver, and - // register rax and rbx holds the argument count and argument array, - // while rdi holds the function pointer and rsi the context. -#ifdef _WIN64 - // MSVC parameters in: - // rcx : entry (ignored) - // rdx : function - // r8 : receiver - // r9 : argc - // [rsp+0x20] : argv - - // Clear the context before we push it when entering the JS frame. - __ xor_(rsi, rsi); - __ EnterInternalFrame(); - - // Load the function context into rsi. - __ movq(rsi, FieldOperand(rdx, JSFunction::kContextOffset)); - - // Push the function and the receiver onto the stack. - __ push(rdx); - __ push(r8); - - // Load the number of arguments and setup pointer to the arguments. - __ movq(rax, r9); - // Load the previous frame pointer to access C argument on stack - __ movq(kScratchRegister, Operand(rbp, 0)); - __ movq(rbx, Operand(kScratchRegister, EntryFrameConstants::kArgvOffset)); - // Load the function pointer into rdi. - __ movq(rdi, rdx); -#else // _WIN64 - // GCC parameters in: - // rdi : entry (ignored) - // rsi : function - // rdx : receiver - // rcx : argc - // r8 : argv - - __ movq(rdi, rsi); - // rdi : function - - // Clear the context before we push it when entering the JS frame. - __ xor_(rsi, rsi); - // Enter an internal frame. - __ EnterInternalFrame(); +void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { + // ----------- S t a t e ------------- + // -- rax : actual number of arguments + // -- rbx : expected number of arguments + // -- rdx : code entry to call + // ----------------------------------- - // Push the function and receiver and setup the context. - __ push(rdi); - __ push(rdx); - __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); + Label invoke, dont_adapt_arguments; + __ IncrementCounter(&Counters::arguments_adaptors, 1); - // Load the number of arguments and setup pointer to the arguments. - __ movq(rax, rcx); - __ movq(rbx, r8); -#endif // _WIN64 + Label enough, too_few; + __ cmpq(rax, rbx); + __ j(less, &too_few); + __ cmpq(rbx, Immediate(SharedFunctionInfo::kDontAdaptArgumentsSentinel)); + __ j(equal, &dont_adapt_arguments); - // Current stack contents: - // [rsp + 2 * kPointerSize ... ]: Internal frame - // [rsp + kPointerSize] : function - // [rsp] : receiver - // Current register contents: - // rax : argc - // rbx : argv - // rsi : context - // rdi : function + { // Enough parameters: Actual >= expected. + __ bind(&enough); + EnterArgumentsAdaptorFrame(masm); - // Copy arguments to the stack in a loop. - // Register rbx points to array of pointers to handle locations. - // Push the values of these handles. - Label loop, entry; - __ xor_(rcx, rcx); // Set loop variable to 0. - __ jmp(&entry); - __ bind(&loop); - __ movq(kScratchRegister, Operand(rbx, rcx, times_pointer_size, 0)); - __ push(Operand(kScratchRegister, 0)); // dereference handle - __ addq(rcx, Immediate(1)); - __ bind(&entry); - __ cmpq(rcx, rax); - __ j(not_equal, &loop); + // Copy receiver and all expected arguments. + const int offset = StandardFrameConstants::kCallerSPOffset; + __ lea(rax, Operand(rbp, rax, times_pointer_size, offset)); + __ movq(rcx, Immediate(-1)); // account for receiver - // Invoke the code. - if (is_construct) { - // Expects rdi to hold function pointer. - __ Call(Handle<Code>(Builtins::builtin(Builtins::JSConstructCall)), - RelocInfo::CODE_TARGET); - } else { - ParameterCount actual(rax); - // Function must be in rdi. - __ InvokeFunction(rdi, actual, CALL_FUNCTION); + Label copy; + __ bind(©); + __ incq(rcx); + __ push(Operand(rax, 0)); + __ subq(rax, Immediate(kPointerSize)); + __ cmpq(rcx, rbx); + __ j(less, ©); + __ jmp(&invoke); } - // Exit the JS frame. Notice that this also removes the empty - // context and the function left on the stack by the code - // invocation. - __ LeaveInternalFrame(); - // TODO(X64): Is argument correct? Is there a receiver to remove? - __ ret(1 * kPointerSize); // remove receiver -} - - -void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) { - Generate_JSEntryTrampolineHelper(masm, false); -} - - -void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) { - Generate_JSEntryTrampolineHelper(masm, true); -} - - -void Builtins::Generate_LazyCompile(MacroAssembler* masm) { - // Enter an internal frame. - __ EnterInternalFrame(); - - // Push a copy of the function onto the stack. - __ push(rdi); - - __ push(rdi); // Function is also the parameter to the runtime call. - __ CallRuntime(Runtime::kLazyCompile, 1); - __ pop(rdi); - - // Tear down temporary frame. - __ LeaveInternalFrame(); - - // Do a tail-call of the compiled function. - __ lea(rcx, FieldOperand(rax, Code::kHeaderSize)); - __ jmp(rcx); -} - - -void Builtins::Generate_LazyRecompile(MacroAssembler* masm) { - // Enter an internal frame. - __ EnterInternalFrame(); - - // Push a copy of the function onto the stack. - __ push(rdi); - - __ push(rdi); // Function is also the parameter to the runtime call. - __ CallRuntime(Runtime::kLazyRecompile, 1); - - // Restore function and tear down temporary frame. - __ pop(rdi); - __ LeaveInternalFrame(); + { // Too few parameters: Actual < expected. + __ bind(&too_few); + EnterArgumentsAdaptorFrame(masm); - // Do a tail-call of the compiled function. - __ lea(rcx, FieldOperand(rax, Code::kHeaderSize)); - __ jmp(rcx); -} + // Copy receiver and all actual arguments. + const int offset = StandardFrameConstants::kCallerSPOffset; + __ lea(rdi, Operand(rbp, rax, times_pointer_size, offset)); + __ movq(rcx, Immediate(-1)); // account for receiver + Label copy; + __ bind(©); + __ incq(rcx); + __ push(Operand(rdi, 0)); + __ subq(rdi, Immediate(kPointerSize)); + __ cmpq(rcx, rax); + __ j(less, ©); -void Builtins::Generate_NotifyDeoptimized(MacroAssembler* masm) { - __ int3(); -} + // Fill remaining expected arguments with undefined values. + Label fill; + __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex); + __ bind(&fill); + __ incq(rcx); + __ push(kScratchRegister); + __ cmpq(rcx, rbx); + __ j(less, &fill); + // Restore function pointer. + __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); + } -void Builtins::Generate_NotifyLazyDeoptimized(MacroAssembler* masm) { - __ int3(); -} + // Call the entry point. + __ bind(&invoke); + __ call(rdx); + // Leave frame and return. + LeaveArgumentsAdaptorFrame(masm); + __ ret(0); -void Builtins::Generate_NotifyOSR(MacroAssembler* masm) { - __ int3(); + // ------------------------------------------- + // Dont adapt arguments. + // ------------------------------------------- + __ bind(&dont_adapt_arguments); + __ jmp(rdx); } @@ -1388,6 +1384,8 @@ void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) { } +#undef __ + } } // namespace v8::internal #endif // V8_TARGET_ARCH_X64 diff --git a/deps/v8/src/x64/full-codegen-x64.cc b/deps/v8/src/x64/full-codegen-x64.cc index 574688c14df..355cf916626 100644 --- a/deps/v8/src/x64/full-codegen-x64.cc +++ b/deps/v8/src/x64/full-codegen-x64.cc @@ -839,7 +839,9 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { __ bind(&update_each); __ movq(result_register(), rbx); // Perform the assignment as if via '='. - EmitAssignment(stmt->each()); + { EffectContext context(this); + EmitAssignment(stmt->each(), stmt->AssignmentId()); + } // Generate code for the body of the loop. Visit(stmt->body()); @@ -1521,7 +1523,7 @@ void FullCodeGenerator::EmitBinaryOp(Token::Value op, } -void FullCodeGenerator::EmitAssignment(Expression* expr) { +void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_id) { // Invalid left-hand sides are rewritten to have a 'throw // ReferenceError' on the left-hand side. if (!expr->IsValidLeftHandSide()) { @@ -1569,6 +1571,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) { break; } } + context()->Plug(rax); } @@ -1641,8 +1644,6 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, } __ bind(&done); } - - context()->Plug(rax); } @@ -1679,10 +1680,9 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { __ push(Operand(rsp, kPointerSize)); // Receiver is under value. __ CallRuntime(Runtime::kToFastProperties, 1); __ pop(rax); - context()->DropAndPlug(1, rax); - } else { - context()->Plug(rax); + __ Drop(1); } + context()->Plug(rax); } @@ -3127,6 +3127,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { { EffectContext context(this); EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), Token::ASSIGN); + context.Plug(rax); } // For all contexts except kEffect: We have the result on // top of the stack. @@ -3137,6 +3138,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { // Perform the assignment as if via '='. EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), Token::ASSIGN); + context()->Plug(rax); } break; case NAMED_PROPERTY: { diff --git a/deps/v8/src/x64/lithium-x64.h b/deps/v8/src/x64/lithium-x64.h index 0c1559be443..f66ec1689c9 100644 --- a/deps/v8/src/x64/lithium-x64.h +++ b/deps/v8/src/x64/lithium-x64.h @@ -216,11 +216,6 @@ class LChunk: public ZoneObject { return 0; } - int NearestNextGapPos(int index) const { - UNIMPLEMENTED(); - return 0; - } - void MarkEmptyBlocks() { UNIMPLEMENTED(); } #ifdef DEBUG diff --git a/deps/v8/src/x64/macro-assembler-x64.cc b/deps/v8/src/x64/macro-assembler-x64.cc index 5bb5ffd9917..1df9b4750ce 100644 --- a/deps/v8/src/x64/macro-assembler-x64.cc +++ b/deps/v8/src/x64/macro-assembler-x64.cc @@ -2250,6 +2250,31 @@ void MacroAssembler::LoadContext(Register dst, int context_chain_length) { } +void MacroAssembler::LoadGlobalFunction(int index, Register function) { + // Load the global or builtins object from the current context. + movq(function, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX))); + // Load the global context from the global or builtins object. + movq(function, FieldOperand(function, GlobalObject::kGlobalContextOffset)); + // Load the function from the global context. + movq(function, Operand(function, Context::SlotOffset(index))); +} + + +void MacroAssembler::LoadGlobalFunctionInitialMap(Register function, + Register map) { + // Load the initial map. The global functions all have initial maps. + movq(map, FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); + if (FLAG_debug_code) { + Label ok, fail; + CheckMap(map, Factory::meta_map(), &fail, false); + jmp(&ok); + bind(&fail); + Abort("Global functions must have initial map"); + bind(&ok); + } +} + + int MacroAssembler::ArgumentStackSlotsForCFunctionCall(int num_arguments) { // On Windows 64 stack slots are reserved by the caller for all arguments // including the ones passed in registers, and space is always allocated for diff --git a/deps/v8/src/x64/macro-assembler-x64.h b/deps/v8/src/x64/macro-assembler-x64.h index 348191ee254..d8f2fba42a7 100644 --- a/deps/v8/src/x64/macro-assembler-x64.h +++ b/deps/v8/src/x64/macro-assembler-x64.h @@ -772,6 +772,13 @@ class MacroAssembler: public Assembler { // Find the function context up the context chain. void LoadContext(Register dst, int context_chain_length); + // Load the global function with the given index. + void LoadGlobalFunction(int index, Register function); + + // Load the initial map from the global function. The registers + // function and map can be the same. + void LoadGlobalFunctionInitialMap(Register function, Register map); + // --------------------------------------------------------------------------- // Runtime calls diff --git a/deps/v8/test/cctest/cctest.status b/deps/v8/test/cctest/cctest.status index 4f1bcdc8adf..d7f02b95d83 100644 --- a/deps/v8/test/cctest/cctest.status +++ b/deps/v8/test/cctest/cctest.status @@ -42,9 +42,6 @@ test-api/ApplyInterruption: PASS || TIMEOUT # when snapshot is on, so I am marking it PASS || FAIL test-heap-profiler/HeapSnapshotsDiff: PASS || FAIL -# BUG(3260336): Flaky test. May be timing related. -test-profile-generator/RecordStackTraceAtStartProfiling: 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-heap-profiler.cc b/deps/v8/test/cctest/test-heap-profiler.cc index ac4afb2517c..ad242fe79c1 100644 --- a/deps/v8/test/cctest/test-heap-profiler.cc +++ b/deps/v8/test/cctest/test-heap-profiler.cc @@ -1211,4 +1211,51 @@ TEST(HeapSnapshotGetNodeById) { CHECK_EQ(NULL, snapshot->GetNodeById(0x1000000UL)); } + +namespace { + +class TestActivityControl : public v8::ActivityControl { + public: + explicit TestActivityControl(int abort_count) + : done_(0), total_(0), abort_count_(abort_count) {} + ControlOption ReportProgressValue(int done, int total) { + done_ = done; + total_ = total; + return --abort_count_ != 0 ? kContinue : kAbort; + } + int done() { return done_; } + int total() { return total_; } + + private: + int done_; + int total_; + int abort_count_; +}; +} + +TEST(TakeHeapSnapshotAborting) { + v8::HandleScope scope; + LocalContext env; + + const int snapshots_count = v8::HeapProfiler::GetSnapshotsCount(); + TestActivityControl aborting_control(3); + const v8::HeapSnapshot* no_snapshot = + v8::HeapProfiler::TakeSnapshot(v8::String::New("abort"), + v8::HeapSnapshot::kFull, + &aborting_control); + CHECK_EQ(NULL, no_snapshot); + CHECK_EQ(snapshots_count, v8::HeapProfiler::GetSnapshotsCount()); + CHECK_GT(aborting_control.total(), aborting_control.done()); + + TestActivityControl control(-1); // Don't abort. + const v8::HeapSnapshot* snapshot = + v8::HeapProfiler::TakeSnapshot(v8::String::New("full"), + v8::HeapSnapshot::kFull, + &control); + CHECK_NE(NULL, snapshot); + CHECK_EQ(snapshots_count + 1, v8::HeapProfiler::GetSnapshotsCount()); + CHECK_EQ(control.total(), control.done()); + CHECK_GT(control.total(), 0); +} + #endif // ENABLE_LOGGING_AND_PROFILING diff --git a/deps/v8/test/cctest/test-log-utils.cc b/deps/v8/test/cctest/test-log-utils.cc index c99d770d42a..861be12ce86 100644 --- a/deps/v8/test/cctest/test-log-utils.cc +++ b/deps/v8/test/cctest/test-log-utils.cc @@ -12,7 +12,6 @@ using v8::internal::CStrVector; using v8::internal::EmbeddedVector; using v8::internal::LogDynamicBuffer; -using v8::internal::LogRecordCompressor; using v8::internal::MutableCStrVector; using v8::internal::ScopedVector; using v8::internal::Vector; @@ -138,173 +137,4 @@ TEST(DynaBufSealing) { CHECK_EQ(0, ReadData(&dynabuf, 100 + seal_size, &buf)); } - -TEST(CompressorStore) { - LogRecordCompressor comp(2); - const Vector<const char> empty = CStrVector(""); - CHECK(comp.Store(empty)); - CHECK(!comp.Store(empty)); - CHECK(!comp.Store(empty)); - const Vector<const char> aaa = CStrVector("aaa"); - CHECK(comp.Store(aaa)); - CHECK(!comp.Store(aaa)); - CHECK(!comp.Store(aaa)); - CHECK(comp.Store(empty)); - CHECK(!comp.Store(empty)); - CHECK(!comp.Store(empty)); -} - - -void CheckCompression(LogRecordCompressor* comp, - const Vector<const char>& after) { - EmbeddedVector<char, 100> result; - CHECK(comp->RetrievePreviousCompressed(&result)); - CHECK_EQ(after, result); -} - - -void CheckCompression(LogRecordCompressor* comp, - const char* after) { - CheckCompression(comp, CStrVector(after)); -} - - -TEST(CompressorNonCompressed) { - LogRecordCompressor comp(0); - CHECK(!comp.RetrievePreviousCompressed(NULL)); - const Vector<const char> empty = CStrVector(""); - CHECK(comp.Store(empty)); - CHECK(!comp.RetrievePreviousCompressed(NULL)); - const Vector<const char> a_x_20 = CStrVector("aaaaaaaaaaaaaaaaaaaa"); - CHECK(comp.Store(a_x_20)); - CheckCompression(&comp, empty); - CheckCompression(&comp, empty); - CHECK(comp.Store(empty)); - CheckCompression(&comp, a_x_20); - CheckCompression(&comp, a_x_20); -} - - -TEST(CompressorSingleLine) { - LogRecordCompressor comp(1); - const Vector<const char> string_1 = CStrVector("eee,ddd,ccc,bbb,aaa"); - CHECK(comp.Store(string_1)); - const Vector<const char> string_2 = CStrVector("fff,ddd,ccc,bbb,aaa"); - CHECK(comp.Store(string_2)); - // string_1 hasn't been compressed. - CheckCompression(&comp, string_1); - CheckCompression(&comp, string_1); - const Vector<const char> string_3 = CStrVector("hhh,ggg,ccc,bbb,aaa"); - CHECK(comp.Store(string_3)); - // string_2 compressed using string_1. - CheckCompression(&comp, "fff#1:3"); - CheckCompression(&comp, "fff#1:3"); - CHECK(!comp.Store(string_3)); - // Expecting no changes. - CheckCompression(&comp, "fff#1:3"); - CHECK(!comp.Store(string_3)); - // Expecting no changes. - CheckCompression(&comp, "fff#1:3"); - const Vector<const char> string_4 = CStrVector("iii,hhh,ggg,ccc,bbb,aaa"); - CHECK(comp.Store(string_4)); - // string_3 compressed using string_2. - CheckCompression(&comp, "hhh,ggg#1:7"); - const Vector<const char> string_5 = CStrVector("nnn,mmm,lll,kkk,jjj"); - CHECK(comp.Store(string_5)); - // string_4 compressed using string_3. - CheckCompression(&comp, "iii,#1"); - const Vector<const char> string_6 = CStrVector("nnn,mmmmmm,lll,kkk,jjj"); - CHECK(comp.Store(string_6)); - // string_5 hasn't been compressed. - CheckCompression(&comp, string_5); - CHECK(comp.Store(string_5)); - // string_6 compressed using string_5. - CheckCompression(&comp, "nnn,mmm#1:4"); - const Vector<const char> string_7 = CStrVector("nnnnnn,mmm,lll,kkk,jjj"); - CHECK(comp.Store(string_7)); - // string_5 compressed using string_6. - CheckCompression(&comp, "nnn,#1:7"); - const Vector<const char> string_8 = CStrVector("xxn,mmm,lll,kkk,jjj"); - CHECK(comp.Store(string_8)); - // string_7 compressed using string_5. - CheckCompression(&comp, "nnn#1"); - const Vector<const char> string_9 = - CStrVector("aaaaaaaaaaaaa,bbbbbbbbbbbbbbbbb"); - CHECK(comp.Store(string_9)); - // string_8 compressed using string_7. - CheckCompression(&comp, "xx#1:5"); - const Vector<const char> string_10 = - CStrVector("aaaaaaaaaaaaa,cccccccbbbbbbbbbb"); - CHECK(comp.Store(string_10)); - // string_9 hasn't been compressed. - CheckCompression(&comp, string_9); - CHECK(comp.Store(string_1)); - // string_10 compressed using string_9. - CheckCompression(&comp, "aaaaaaaaaaaaa,ccccccc#1:21"); -} - - - -TEST(CompressorMultiLines) { - const int kWindowSize = 3; - LogRecordCompressor comp(kWindowSize); - const Vector<const char> string_1 = CStrVector("eee,ddd,ccc,bbb,aaa"); - CHECK(comp.Store(string_1)); - const Vector<const char> string_2 = CStrVector("iii,hhh,ggg,fff,aaa"); - CHECK(comp.Store(string_2)); - const Vector<const char> string_3 = CStrVector("mmm,lll,kkk,jjj,aaa"); - CHECK(comp.Store(string_3)); - const Vector<const char> string_4 = CStrVector("nnn,hhh,ggg,fff,aaa"); - CHECK(comp.Store(string_4)); - const Vector<const char> string_5 = CStrVector("ooo,lll,kkk,jjj,aaa"); - CHECK(comp.Store(string_5)); - // string_4 compressed using string_2. - CheckCompression(&comp, "nnn#2:3"); - CHECK(comp.Store(string_1)); - // string_5 compressed using string_3. - CheckCompression(&comp, "ooo#2:3"); - CHECK(comp.Store(string_4)); - // string_1 is out of buffer by now, so it shouldn't be compressed. - CHECK_GE(3, kWindowSize); - CheckCompression(&comp, string_1); - CHECK(comp.Store(string_2)); - // string_4 compressed using itself. - CheckCompression(&comp, "#3"); -} - - -TEST(CompressorBestSelection) { - LogRecordCompressor comp(3); - const Vector<const char> string_1 = CStrVector("eee,ddd,ccc,bbb,aaa"); - CHECK(comp.Store(string_1)); - const Vector<const char> string_2 = CStrVector("ddd,ccc,bbb,aaa"); - CHECK(comp.Store(string_2)); - const Vector<const char> string_3 = CStrVector("fff,eee,ddd,ccc,bbb,aaa"); - CHECK(comp.Store(string_3)); - // string_2 compressed using string_1. - CheckCompression(&comp, "#1:4"); - const Vector<const char> string_4 = CStrVector("nnn,hhh,ggg,fff,aaa"); - CHECK(comp.Store(string_4)); - // Compressing string_3 using string_1 gives a better compression than - // using string_2. - CheckCompression(&comp, "fff,#2"); -} - - -TEST(CompressorCompressibility) { - LogRecordCompressor comp(2); - const Vector<const char> string_1 = CStrVector("eee,ddd,ccc,bbb,aaa"); - CHECK(comp.Store(string_1)); - const Vector<const char> string_2 = CStrVector("ccc,bbb,aaa"); - CHECK(comp.Store(string_2)); - const Vector<const char> string_3 = CStrVector("aaa"); - CHECK(comp.Store(string_3)); - // string_2 compressed using string_1. - CheckCompression(&comp, "#1:8"); - const Vector<const char> string_4 = CStrVector("xxx"); - CHECK(comp.Store(string_4)); - // string_3 can't be compressed using string_2 --- too short. - CheckCompression(&comp, string_3); -} - #endif // ENABLE_LOGGING_AND_PROFILING diff --git a/deps/v8/test/cctest/test-parsing.cc b/deps/v8/test/cctest/test-parsing.cc index badbab5eeb1..e642d1b622b 100755 --- a/deps/v8/test/cctest/test-parsing.cc +++ b/deps/v8/test/cctest/test-parsing.cc @@ -260,10 +260,12 @@ TEST(StandAlonePreParser) { uintptr_t stack_limit = i::StackGuard::real_climit(); for (int i = 0; programs[i]; i++) { const char* program = programs[i]; - unibrow::Utf8InputBuffer<256> stream(program, strlen(program)); + i::Utf8ToUC16CharacterStream stream( + reinterpret_cast<const i::byte*>(program), + static_cast<unsigned>(strlen(program))); i::CompleteParserRecorder log; i::V8JavaScriptScanner scanner; - scanner.Initialize(i::Handle<i::String>::null(), &stream); + scanner.Initialize(&stream); v8::preparser::PreParser::PreParseResult result = v8::preparser::PreParser::PreParseProgram(&scanner, @@ -289,9 +291,10 @@ TEST(RegressChromium62639) { // and then used the invalid currently scanned literal. This always // failed in debug mode, and sometimes crashed in release mode. - unibrow::Utf8InputBuffer<256> stream(program, strlen(program)); + i::Utf8ToUC16CharacterStream stream(reinterpret_cast<const i::byte*>(program), + static_cast<unsigned>(strlen(program))); i::ScriptDataImpl* data = - i::ParserApi::PreParse(i::Handle<i::String>::null(), &stream, NULL); + i::ParserApi::PreParse(&stream, NULL); CHECK(data->HasError()); delete data; } @@ -310,10 +313,10 @@ TEST(Regress928) { "try { } catch (e) { var foo = function () { /* first */ } }" "var bar = function () { /* second */ }"; - unibrow::Utf8InputBuffer<256> stream(program, strlen(program)); + i::Utf8ToUC16CharacterStream stream(reinterpret_cast<const i::byte*>(program), + static_cast<unsigned>(strlen(program))); i::ScriptDataImpl* data = - i::ParserApi::PartialPreParse(i::Handle<i::String>::null(), - &stream, NULL); + i::ParserApi::PartialPreParse(&stream, NULL); CHECK(!data->HasError()); data->Initialize(); @@ -347,10 +350,12 @@ TEST(PreParseOverflow) { uintptr_t stack_limit = i::StackGuard::real_climit(); - unibrow::Utf8InputBuffer<256> stream(*program, strlen(*program)); + i::Utf8ToUC16CharacterStream stream( + reinterpret_cast<const i::byte*>(*program), + static_cast<unsigned>(kProgramSize)); i::CompleteParserRecorder log; i::V8JavaScriptScanner scanner; - scanner.Initialize(i::Handle<i::String>::null(), &stream); + scanner.Initialize(&stream); v8::preparser::PreParser::PreParseResult result = @@ -360,3 +365,283 @@ TEST(PreParseOverflow) { stack_limit); CHECK_EQ(v8::preparser::PreParser::kPreParseStackOverflow, result); } + + +class TestExternalResource: public v8::String::ExternalStringResource { + public: + explicit TestExternalResource(uint16_t* data, int length) + : data_(data), length_(static_cast<size_t>(length)) { } + + ~TestExternalResource() { } + + const uint16_t* data() const { + return data_; + } + + size_t length() const { + return length_; + } + private: + uint16_t* data_; + size_t length_; +}; + + +#define CHECK_EQU(v1, v2) CHECK_EQ(static_cast<int>(v1), static_cast<int>(v2)) + +void TestCharacterStream(const char* ascii_source, + unsigned length, + unsigned start = 0, + unsigned end = 0) { + if (end == 0) end = length; + unsigned sub_length = end - start; + i::HandleScope test_scope; + i::SmartPointer<i::uc16> uc16_buffer(new i::uc16[length]); + for (unsigned i = 0; i < length; i++) { + uc16_buffer[i] = static_cast<i::uc16>(ascii_source[i]); + } + i::Vector<const char> ascii_vector(ascii_source, static_cast<int>(length)); + i::Handle<i::String> ascii_string( + i::Factory::NewStringFromAscii(ascii_vector)); + TestExternalResource resource(*uc16_buffer, length); + i::Handle<i::String> uc16_string( + i::Factory::NewExternalStringFromTwoByte(&resource)); + + i::ExternalTwoByteStringUC16CharacterStream uc16_stream( + i::Handle<i::ExternalTwoByteString>::cast(uc16_string), start, end); + i::GenericStringUC16CharacterStream string_stream(ascii_string, start, end); + i::Utf8ToUC16CharacterStream utf8_stream( + reinterpret_cast<const i::byte*>(ascii_source), end); + utf8_stream.SeekForward(start); + + unsigned i = start; + while (i < end) { + // Read streams one char at a time + CHECK_EQU(i, uc16_stream.pos()); + CHECK_EQU(i, string_stream.pos()); + CHECK_EQU(i, utf8_stream.pos()); + int32_t c0 = ascii_source[i]; + int32_t c1 = uc16_stream.Advance(); + int32_t c2 = string_stream.Advance(); + int32_t c3 = utf8_stream.Advance(); + i++; + CHECK_EQ(c0, c1); + CHECK_EQ(c0, c2); + CHECK_EQ(c0, c3); + CHECK_EQU(i, uc16_stream.pos()); + CHECK_EQU(i, string_stream.pos()); + CHECK_EQU(i, utf8_stream.pos()); + } + while (i > start + sub_length / 4) { + // Pushback, re-read, pushback again. + int32_t c0 = ascii_source[i - 1]; + CHECK_EQU(i, uc16_stream.pos()); + CHECK_EQU(i, string_stream.pos()); + CHECK_EQU(i, utf8_stream.pos()); + uc16_stream.PushBack(c0); + string_stream.PushBack(c0); + utf8_stream.PushBack(c0); + i--; + CHECK_EQU(i, uc16_stream.pos()); + CHECK_EQU(i, string_stream.pos()); + CHECK_EQU(i, utf8_stream.pos()); + int32_t c1 = uc16_stream.Advance(); + int32_t c2 = string_stream.Advance(); + int32_t c3 = utf8_stream.Advance(); + i++; + CHECK_EQU(i, uc16_stream.pos()); + CHECK_EQU(i, string_stream.pos()); + CHECK_EQU(i, utf8_stream.pos()); + CHECK_EQ(c0, c1); + CHECK_EQ(c0, c2); + CHECK_EQ(c0, c3); + uc16_stream.PushBack(c0); + string_stream.PushBack(c0); + utf8_stream.PushBack(c0); + i--; + CHECK_EQU(i, uc16_stream.pos()); + CHECK_EQU(i, string_stream.pos()); + CHECK_EQU(i, utf8_stream.pos()); + } + unsigned halfway = start + sub_length / 2; + uc16_stream.SeekForward(halfway - i); + string_stream.SeekForward(halfway - i); + utf8_stream.SeekForward(halfway - i); + i = halfway; + CHECK_EQU(i, uc16_stream.pos()); + CHECK_EQU(i, string_stream.pos()); + CHECK_EQU(i, utf8_stream.pos()); + + while (i < end) { + // Read streams one char at a time + CHECK_EQU(i, uc16_stream.pos()); + CHECK_EQU(i, string_stream.pos()); + CHECK_EQU(i, utf8_stream.pos()); + int32_t c0 = ascii_source[i]; + int32_t c1 = uc16_stream.Advance(); + int32_t c2 = string_stream.Advance(); + int32_t c3 = utf8_stream.Advance(); + i++; + CHECK_EQ(c0, c1); + CHECK_EQ(c0, c2); + CHECK_EQ(c0, c3); + CHECK_EQU(i, uc16_stream.pos()); + CHECK_EQU(i, string_stream.pos()); + CHECK_EQU(i, utf8_stream.pos()); + } + + int32_t c1 = uc16_stream.Advance(); + int32_t c2 = string_stream.Advance(); + int32_t c3 = utf8_stream.Advance(); + CHECK_LT(c1, 0); + CHECK_LT(c2, 0); + CHECK_LT(c3, 0); +} + + +TEST(CharacterStreams) { + v8::HandleScope handles; + v8::Persistent<v8::Context> context = v8::Context::New(); + v8::Context::Scope context_scope(context); + + TestCharacterStream("abc\0\n\r\x7f", 7); + static const unsigned kBigStringSize = 4096; + char buffer[kBigStringSize + 1]; + for (unsigned i = 0; i < kBigStringSize; i++) { + buffer[i] = static_cast<char>(i & 0x7f); + } + TestCharacterStream(buffer, kBigStringSize); + + TestCharacterStream(buffer, kBigStringSize, 576, 3298); + + TestCharacterStream("\0", 1); + TestCharacterStream("", 0); +} + + +TEST(Utf8CharacterStream) { + static const unsigned kMaxUC16CharU = unibrow::Utf8::kMaxThreeByteChar; + static const int kMaxUC16Char = static_cast<int>(kMaxUC16CharU); + + static const int kAllUtf8CharsSize = + (unibrow::Utf8::kMaxOneByteChar + 1) + + (unibrow::Utf8::kMaxTwoByteChar - unibrow::Utf8::kMaxOneByteChar) * 2 + + (unibrow::Utf8::kMaxThreeByteChar - unibrow::Utf8::kMaxTwoByteChar) * 3; + static const unsigned kAllUtf8CharsSizeU = + static_cast<unsigned>(kAllUtf8CharsSize); + + char buffer[kAllUtf8CharsSizeU]; + unsigned cursor = 0; + for (int i = 0; i <= kMaxUC16Char; i++) { + cursor += unibrow::Utf8::Encode(buffer + cursor, i); + } + ASSERT(cursor == kAllUtf8CharsSizeU); + + i::Utf8ToUC16CharacterStream stream(reinterpret_cast<const i::byte*>(buffer), + kAllUtf8CharsSizeU); + for (int i = 0; i <= kMaxUC16Char; i++) { + CHECK_EQU(i, stream.pos()); + int32_t c = stream.Advance(); + CHECK_EQ(i, c); + CHECK_EQU(i + 1, stream.pos()); + } + for (int i = kMaxUC16Char; i >= 0; i--) { + CHECK_EQU(i + 1, stream.pos()); + stream.PushBack(i); + CHECK_EQU(i, stream.pos()); + } + int i = 0; + while (stream.pos() < kMaxUC16CharU) { + CHECK_EQU(i, stream.pos()); + unsigned progress = stream.SeekForward(12); + i += progress; + int32_t c = stream.Advance(); + if (i <= kMaxUC16Char) { + CHECK_EQ(i, c); + } else { + CHECK_EQ(-1, c); + } + i += 1; + CHECK_EQU(i, stream.pos()); + } +} + +#undef CHECK_EQU + +void TestStreamScanner(i::UC16CharacterStream* stream, + i::Token::Value* expected_tokens, + int skip_pos = 0, // Zero means not skipping. + int skip_to = 0) { + i::V8JavaScriptScanner scanner; + scanner.Initialize(stream, i::JavaScriptScanner::kAllLiterals); + + int i = 0; + do { + i::Token::Value expected = expected_tokens[i]; + i::Token::Value actual = scanner.Next(); + CHECK_EQ(i::Token::String(expected), i::Token::String(actual)); + if (scanner.location().end_pos == skip_pos) { + scanner.SeekForward(skip_to); + } + i++; + } while (expected_tokens[i] != i::Token::ILLEGAL); +} + +TEST(StreamScanner) { + const char* str1 = "{ foo get for : */ <- \n\n /*foo*/ bib"; + i::Utf8ToUC16CharacterStream stream1(reinterpret_cast<const i::byte*>(str1), + static_cast<unsigned>(strlen(str1))); + i::Token::Value expectations1[] = { + i::Token::LBRACE, + i::Token::IDENTIFIER, + i::Token::IDENTIFIER, + i::Token::FOR, + i::Token::COLON, + i::Token::MUL, + i::Token::DIV, + i::Token::LT, + i::Token::SUB, + i::Token::IDENTIFIER, + i::Token::EOS, + i::Token::ILLEGAL + }; + TestStreamScanner(&stream1, expectations1, 0, 0); + + const char* str2 = "case default const {THIS\nPART\nSKIPPED} do"; + i::Utf8ToUC16CharacterStream stream2(reinterpret_cast<const i::byte*>(str2), + static_cast<unsigned>(strlen(str2))); + i::Token::Value expectations2[] = { + i::Token::CASE, + i::Token::DEFAULT, + i::Token::CONST, + i::Token::LBRACE, + // Skipped part here + i::Token::RBRACE, + i::Token::DO, + i::Token::EOS, + i::Token::ILLEGAL + }; + ASSERT_EQ('{', str2[19]); + ASSERT_EQ('}', str2[37]); + TestStreamScanner(&stream2, expectations2, 20, 37); + + const char* str3 = "{}}}}"; + i::Token::Value expectations3[] = { + i::Token::LBRACE, + i::Token::RBRACE, + i::Token::RBRACE, + i::Token::RBRACE, + i::Token::RBRACE, + i::Token::EOS, + i::Token::ILLEGAL + }; + // Skip zero-four RBRACEs. + for (int i = 0; i <= 4; i++) { + expectations3[6 - i] = i::Token::ILLEGAL; + expectations3[5 - i] = i::Token::EOS; + i::Utf8ToUC16CharacterStream stream3( + reinterpret_cast<const i::byte*>(str3), + static_cast<unsigned>(strlen(str3))); + TestStreamScanner(&stream3, expectations3, 1, 1 + i); + } +} diff --git a/deps/v8/test/cctest/test-profile-generator.cc b/deps/v8/test/cctest/test-profile-generator.cc index a0733ef685b..f849d404aeb 100644 --- a/deps/v8/test/cctest/test-profile-generator.cc +++ b/deps/v8/test/cctest/test-profile-generator.cc @@ -782,12 +782,16 @@ TEST(RecordStackTraceAtStartProfiling) { CpuProfiler::GetProfile(NULL, 0); const ProfileTree* topDown = profile->top_down(); const ProfileNode* current = topDown->root(); + const_cast<ProfileNode*>(current)->Print(0); // The tree should look like this: // (root) // (anonymous function) // a // b // c + // There can also be: + // startProfiling + // if the sampler managed to get a tick. current = PickChild(current, "(anonymous function)"); CHECK_NE(NULL, const_cast<ProfileNode*>(current)); current = PickChild(current, "a"); @@ -796,7 +800,12 @@ TEST(RecordStackTraceAtStartProfiling) { CHECK_NE(NULL, const_cast<ProfileNode*>(current)); current = PickChild(current, "c"); CHECK_NE(NULL, const_cast<ProfileNode*>(current)); - CHECK_EQ(0, current->children()->length()); + CHECK(current->children()->length() == 0 || + current->children()->length() == 1); + if (current->children()->length() == 1) { + current = PickChild(current, "startProfiling"); + CHECK_EQ(0, current->children()->length()); + } } diff --git a/deps/v8/test/cctest/test-regexp.cc b/deps/v8/test/cctest/test-regexp.cc index 3bf24a8ab1b..3e6709aef43 100644 --- a/deps/v8/test/cctest/test-regexp.cc +++ b/deps/v8/test/cctest/test-regexp.cc @@ -173,6 +173,9 @@ TEST(Parser) { CHECK_PARSE_EQ("[a-b-c]", "[a-b - c]"); CHECK_PARSE_EQ("[\\d]", "[0-9]"); CHECK_PARSE_EQ("[x\\dz]", "[x 0-9 z]"); + CHECK_PARSE_EQ("[\\d-z]", "[0-9 - z]"); + CHECK_PARSE_EQ("[\\d-\\d]", "[0-9 - 0-9]"); + CHECK_PARSE_EQ("[z-\\d]", "[z - 0-9]"); CHECK_PARSE_EQ("\\cj\\cJ\\ci\\cI\\ck\\cK", "'\\x0a\\x0a\\x09\\x09\\x0b\\x0b'"); CHECK_PARSE_EQ("\\c!", "'c!'"); diff --git a/deps/v8/test/mjsunit/mjsunit.status b/deps/v8/test/mjsunit/mjsunit.status index 24d9603b6ba..75a5a02150b 100644 --- a/deps/v8/test/mjsunit/mjsunit.status +++ b/deps/v8/test/mjsunit/mjsunit.status @@ -104,6 +104,11 @@ regress/regress-create-exception: SKIP regress/regress-3218915: SKIP regress/regress-3247124: SKIP +############################################################################## +[ $arch == arm && $crankshaft ] + +# Test that currently fail with crankshaft on ARM. +compiler/simple-osr: FAIL ############################################################################## [ $arch == mips ] diff --git a/deps/v8/test/mjsunit/object-define-property.js b/deps/v8/test/mjsunit/object-define-property.js index b258aa75bf3..780c720b510 100644 --- a/deps/v8/test/mjsunit/object-define-property.js +++ b/deps/v8/test/mjsunit/object-define-property.js @@ -866,4 +866,36 @@ assertFalse(desc.writable); assertFalse(desc.enumerable); assertFalse(desc.configurable); +// See issue 968: http://code.google.com/p/v8/issues/detail?id=968 +var o = { x : 42 }; +Object.defineProperty(o, "x", { writable: false }); +assertEquals(42, o.x); +o.x = 37; +assertEquals(42, o.x); + +o = { x : 42 }; +Object.defineProperty(o, "x", {}); +assertEquals(42, o.x); +o.x = 37; +// Writability is preserved. +assertEquals(37, o.x); + +var o = { }; +Object.defineProperty(o, "x", { writable: false }); +assertEquals(undefined, o.x); +o.x = 37; +assertEquals(undefined, o.x); + +o = { get x() { return 87; } }; +Object.defineProperty(o, "x", { writable: false }); +assertEquals(undefined, o.x); +o.x = 37; +assertEquals(undefined, o.x); + +// Ignore inherited properties. +o = { __proto__ : { x : 87 } }; +Object.defineProperty(o, "x", { writable: false }); +assertEquals(undefined, o.x); +o.x = 37; +assertEquals(undefined, o.x); diff --git a/deps/v8/test/mjsunit/regexp.js b/deps/v8/test/mjsunit/regexp.js index 59c3ba8d287..4c1d2e315f8 100644 --- a/deps/v8/test/mjsunit/regexp.js +++ b/deps/v8/test/mjsunit/regexp.js @@ -110,6 +110,44 @@ assertFalse(re.test("\\]")); assertFalse(re.test("\x03]")); // I.e., read as \cc +// Test that we handle \s and \S correctly inside some bizarre +// character classes. +re = /[\s-:]/; +assertTrue(re.test('-')); +assertTrue(re.test(':')); +assertTrue(re.test(' ')); +assertTrue(re.test('\t')); +assertTrue(re.test('\n')); +assertFalse(re.test('a')); +assertFalse(re.test('Z')); + +re = /[\S-:]/; +assertTrue(re.test('-')); +assertTrue(re.test(':')); +assertFalse(re.test(' ')); +assertFalse(re.test('\t')); +assertFalse(re.test('\n')); +assertTrue(re.test('a')); +assertTrue(re.test('Z')); + +re = /[^\s-:]/; +assertFalse(re.test('-')); +assertFalse(re.test(':')); +assertFalse(re.test(' ')); +assertFalse(re.test('\t')); +assertFalse(re.test('\n')); +assertTrue(re.test('a')); +assertTrue(re.test('Z')); + +re = /[^\S-:]/; +assertFalse(re.test('-')); +assertFalse(re.test(':')); +assertTrue(re.test(' ')); +assertTrue(re.test('\t')); +assertTrue(re.test('\n')); +assertFalse(re.test('a')); +assertFalse(re.test('Z')); + re = /[\s]/; assertFalse(re.test('-')); assertFalse(re.test(':')); @@ -164,6 +202,17 @@ assertFalse(re.test('\n')); assertFalse(re.test('a')); assertFalse(re.test('Z')); +// First - is treated as range operator, second as literal minus. +// This follows the specification in parsing, but doesn't throw on +// the \s at the beginning of the range. +re = /[\s-0-9]/; +assertTrue(re.test(' ')); +assertTrue(re.test('\xA0')); +assertTrue(re.test('-')); +assertTrue(re.test('0')); +assertTrue(re.test('9')); +assertFalse(re.test('1')); + // Test beginning and end of line assertions with or without the // multiline flag. re = /^\d+/; @@ -610,46 +659,3 @@ assertEquals(["bc"], re.exec("zimzomzumbc")); assertFalse(re.test("c")); assertFalse(re.test("")); - -function testInvalidRange(str) { - try { - RegExp(str).test("x"); - } catch (e) { - return; - } - assetUnreachable("Allowed invalid range in " + str); -} - -function testValidRange(str) { - try { - RegExp(str).test("x"); - } catch (e) { - assertUnreachable("Shouldn't fail parsing: " + str + ", was: " + e); - } -} - -testInvalidRange("[\\d-z]"); -testInvalidRange("[z-\\d]"); -testInvalidRange("[\\d-\\d]"); -testInvalidRange("[z-x]"); // Larger value first. -testInvalidRange("[x-\\d-\\d]"); - -testValidRange("[x-z]"); -testValidRange("[!--\d]"); // Second "-" is end of range. -testValidRange("[\d-]"); -testValidRange("[-\d]"); -testValidRange("[-\d-]"); -testValidRange("[^-\d-]"); -testValidRange("[^-\d-]"); -testValidRange("[0-9-\w]"); - -// Escaped dashes do not count as range operators. -testValidRange("[\\d\\-z]"); -testValidRange("[z\\-\\d]"); -testValidRange("[\\d\\-\\d]"); -testValidRange("[z\\-x]"); -testValidRange("[x\\-\\d\\-\\d]"); - - - - diff --git a/deps/v8/test/mjsunit/regress/regress-962.js b/deps/v8/test/mjsunit/regress/regress-962.js new file mode 100644 index 00000000000..c0a2fdc7164 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-962.js @@ -0,0 +1,53 @@ +// 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: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +function L(scope) { this.s = new Object(); } + +L.prototype.c = function() { return true; } + +function F() { + this.l = [new L, new L]; +} + +F.prototype.foo = function () { + var f, d = arguments, + e, b = this.l, + g; + for (e = 0; e < b.length; e++) { + g = b[e]; + f = g.c.apply(g.s, d); + if (f === false) { + break + } + } + return f +} + + +var ctx = new F; + +for (var i = 0; i < 10000000; i++) ctx.foo(); diff --git a/deps/v8/test/mjsunit/regress/regress-969.js b/deps/v8/test/mjsunit/regress/regress-969.js new file mode 100644 index 00000000000..c2ba0ac9e8e --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-969.js @@ -0,0 +1,127 @@ +// 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: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Regression test for bugs when deoptimizing after assignments in effect +// contexts. + +// Bug 989 is that there was an extra value on the expression stack when +// deoptimizing after an assignment in effect context (the value of the +// assignment was lingering). This is hard to observe in the unoptimized +// code. +// +// This test uses comma expressions to put assignments in effect contexts, +// references to deleted global variables to force deoptimization, and +// function calls to observe an extra value. + +function first(x, y) { return x; } +var y = 0; +var o = {}; +o.x = 0; +o[0] = 0; + +// Assignment to global variable. +x0 = 0; +function test0() { return first((y = 1, typeof x0), 2); } +// Call the function once to compile it. +assertEquals('number', test0()); +// Delete to force deoptimization on the next call. +delete x0; +assertEquals('undefined', test0()); + +// Compound assignment to global variable. +x1 = 0; +function test1() { return first((y += 1, typeof x1), 2); } +assertEquals('number', test1(), 'test1 before'); +delete x1; +assertEquals('undefined', test1(), 'test1 after'); + +// Pre and post-increment of global variable. +x2 = 0; +function test2() { return first((++y, typeof x2), 2); } +assertEquals('number', test2(), 'test2 before'); +delete x2; +assertEquals('undefined', test2(), 'test2 after'); + +x3 = 0; +function test3() { return first((y++, typeof x3), 2); } +assertEquals('number', test3(), 'test3 before'); +delete x3; +assertEquals('undefined', test3(), 'test3 after'); + + +// Assignment, compound assignment, and pre and post-increment of named +// properties. +x4 = 0; +function test4() { return first((o.x = 1, typeof x4), 2); } +assertEquals('number', test4()); +delete x4; +assertEquals('undefined', test4()); + +x5 = 0; +function test5() { return first((o.x += 1, typeof x5), 2); } +assertEquals('number', test5()); +delete x5; +assertEquals('undefined', test5()); + +x6 = 0; +function test6() { return first((++o.x, typeof x6), 2); } +assertEquals('number', test6()); +delete x6; +assertEquals('undefined', test6()); + +x7 = 0; +function test7() { return first((o.x++, typeof x7), 2); } +assertEquals('number', test7()); +delete x7; +assertEquals('undefined', test7()); + + +// Assignment, compound assignment, and pre and post-increment of indexed +// properties. +x8 = 0; +function test8(index) { return first((o[index] = 1, typeof x8), 2); } +assertEquals('number', test8()); +delete x8; +assertEquals('undefined', test8()); + +x9 = 0; +function test9(index) { return first((o[index] += 1, typeof x9), 2); } +assertEquals('number', test9()); +delete x9; +assertEquals('undefined', test9()); + +x10 = 0; +function test10(index) { return first((++o[index], typeof x10), 2); } +assertEquals('number', test10()); +delete x10; +assertEquals('undefined', test10()); + +x11 = 0; +function test11(index) { return first((o[index]++, typeof x11), 2); } +assertEquals('number', test11()); +delete x11; +assertEquals('undefined', test11()); diff --git a/deps/v8/test/mjsunit/third_party/regexp-pcre.js b/deps/v8/test/mjsunit/third_party/regexp-pcre.js index d9fa976855d..dcb1b320fdc 100644 --- a/deps/v8/test/mjsunit/third_party/regexp-pcre.js +++ b/deps/v8/test/mjsunit/third_party/regexp-pcre.js @@ -962,7 +962,7 @@ res[882] = /[az-]+/; res[883] = /[a\-z]+/; res[884] = /[a-z]+/; res[885] = /[\d-]+/; -// res[886] - Disabled after making [\d-z] invalid to be compatible with JSC. +res[886] = /[\d-z]+/; res[887] = /\x5c/; res[888] = /\x20Z/; res[889] = /ab{3cd/; @@ -1346,7 +1346,7 @@ res[1266] = /((Z)+|A)*/; res[1267] = /(Z()|A)*/; res[1268] = /(Z(())|A)*/; res[1269] = /a*/g; -// res[1270] disabled after making /^[\d-a]/ invalid to be compatible with JSC. +res[1270] = /^[\d-a]/; res[1271] = /[[:space:]]+/; res[1272] = /[[:blank:]]+/; res[1273] = /[\s]+/; @@ -2530,7 +2530,7 @@ assertEquals(null, res[431].exec("a\x0db ", 882)); assertEquals(null, res[431].exec("a\x85b", 883)); assertThrows("var re = /(?-+a)/;", 884); assertEquals(null, res[443].exec("aaaa", 885)); -// assertEquals(null, res[443].exec("bacxxx", 886)); +assertEquals(null, res[443].exec("bacxxx", 886)); assertEquals(null, res[443].exec("bbaccxxx ", 887)); assertEquals(null, res[443].exec("bbbacccxx", 888)); assertEquals(null, res[443].exec("aaaa", 889)); @@ -4391,10 +4391,9 @@ assertEquals("abcdxyz", res[884].exec("abcdxyz"), 2743); assertEquals("12-34", res[885].exec("12-34"), 2744); assertEquals(null, res[885].exec("*** Failers", 2745)); assertEquals(null, res[885].exec("aaa", 2746)); -// Disabled. To be compatible with JSC, the regexp is no longer valid. -// assertEquals("12-34z", res[886].exec("12-34z"), 2747); -// assertEquals(null, res[886].exec("*** Failers", 2748)); -// assertEquals(null, res[886].exec("aaa", 2749)); +assertEquals("12-34z", res[886].exec("12-34z"), 2747); +assertEquals(null, res[886].exec("*** Failers", 2748)); +assertEquals(null, res[886].exec("aaa", 2749)); assertEquals("\\", res[887].exec("\\\\"), 2750); assertEquals(" Z", res[888].exec("the Zoo"), 2751); assertEquals(null, res[888].exec("*** Failers", 2752)); @@ -5356,12 +5355,11 @@ assertEquals("", res[1269].exec("-things"), 3707); assertEquals("", res[1269].exec("0digit"), 3708); assertEquals("", res[1269].exec("*** Failers"), 3709); assertEquals("", res[1269].exec("bcdef "), 3710); -// Disabled. To be compatible with JSC, the RegExp is no longer valid. -// assertEquals("a", res[1270].exec("abcde"), 3711); -// assertEquals("-", res[1270].exec("-things"), 3712); -// assertEquals("0", res[1270].exec("0digit"), 3713); -// assertEquals(null, res[1270].exec("*** Failers", 3714)); -// assertEquals(null, res[1270].exec("bcdef ", 3715)); +assertEquals("a", res[1270].exec("abcde"), 3711); +assertEquals("-", res[1270].exec("-things"), 3712); +assertEquals("0", res[1270].exec("0digit"), 3713); +assertEquals(null, res[1270].exec("*** Failers", 3714)); +assertEquals(null, res[1270].exec("bcdef ", 3715)); assertEquals(null, res[1271].exec("> \x09\n\x0c\x0d\x0b<", 3716)); assertEquals(null, res[1271].exec(" ", 3717)); assertEquals(null, res[1272].exec("> \x09\n\x0c\x0d\x0b<", 3718)); diff --git a/deps/v8/test/mjsunit/tools/logreader.js b/deps/v8/test/mjsunit/tools/logreader.js deleted file mode 100644 index 485990eaa1d..00000000000 --- a/deps/v8/test/mjsunit/tools/logreader.js +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2009 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: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Load CSV Parser and Log Reader implementations from <project root>/tools. -// Files: tools/csvparser.js tools/logreader.js - - -(function testAddressParser() { - var reader = new devtools.profiler.LogReader({}); - var parser = reader.createAddressParser('test'); - - // Test that 0x values are parsed, and prevAddresses_ are untouched. - assertFalse('test' in reader.prevAddresses_); - assertEquals(0, parser('0x0')); - assertFalse('test' in reader.prevAddresses_); - assertEquals(0x100, parser('0x100')); - assertFalse('test' in reader.prevAddresses_); - assertEquals(0xffffffff, parser('0xffffffff')); - assertFalse('test' in reader.prevAddresses_); - - // Test that values that has no '+' or '-' prefix are parsed - // and saved to prevAddresses_. - assertEquals(0, parser('0')); - assertEquals(0, reader.prevAddresses_.test); - assertEquals(0x100, parser('100')); - assertEquals(0x100, reader.prevAddresses_.test); - assertEquals(0xffffffff, parser('ffffffff')); - assertEquals(0xffffffff, reader.prevAddresses_.test); - - // Test that values prefixed with '+' or '-' are treated as deltas, - // and prevAddresses_ is updated. - // Set base value. - assertEquals(0x100, parser('100')); - assertEquals(0x100, reader.prevAddresses_.test); - assertEquals(0x200, parser('+100')); - assertEquals(0x200, reader.prevAddresses_.test); - assertEquals(0x100, parser('-100')); - assertEquals(0x100, reader.prevAddresses_.test); -})(); - - -(function testAddressParser() { - var reader = new devtools.profiler.LogReader({}); - - assertEquals([0x10000000, 0x10001000, 0xffff000, 0x10000000], - reader.processStack(0x10000000, 0, ['overflow', - '+1000', '-2000', '+1000'])); -})(); - - -(function testExpandBackRef() { - var reader = new devtools.profiler.LogReader({}); - - assertEquals('aaaaaaaa', reader.expandBackRef_('aaaaaaaa')); - assertEquals('aaaaaaaa', reader.expandBackRef_('#1')); - assertEquals('bbbbaaaa', reader.expandBackRef_('bbbb#2:4')); - assertEquals('"#1:1"', reader.expandBackRef_('"#1:1"')); -})(); diff --git a/deps/v8/test/mozilla/mozilla.status b/deps/v8/test/mozilla/mozilla.status index b1e9ba7d4df..320efe73942 100644 --- a/deps/v8/test/mozilla/mozilla.status +++ b/deps/v8/test/mozilla/mozilla.status @@ -53,6 +53,9 @@ def FAIL_OK = FAIL, OKAY # time to do so. js1_5/Regress/regress-271716-n: SKIP +# BUG(960): This test has an insane amount of output when it times out, +# messing up ability to see other failures on the waterfall. +js1_5/extensions/regress-342960: SKIP # This test uses a unitialized variable. A Bug has been filed: # https://bugzilla.mozilla.org/show_bug.cgi?id=575575 @@ -289,10 +292,6 @@ js1_2/regexp/RegExp_multiline_as_array: FAIL_OK js1_2/regexp/beginLine: FAIL_OK js1_2/regexp/endLine: FAIL_OK -# To be compatible with JSC, we no longer accept [\d-x], [x-\d] or -# [\d-\d] as valid ranges. -ecma_3/RegExp/regress-375715-02: FAIL -js1_5/extensions/regress-351463-01: FAIL # To be compatible with safari typeof a regexp yields 'function'; # in firefox it yields 'object'. diff --git a/deps/v8/test/sputnik/README b/deps/v8/test/sputnik/README index 3d39a67e43e..94c689bd287 100644 --- a/deps/v8/test/sputnik/README +++ b/deps/v8/test/sputnik/README @@ -1,6 +1,6 @@ To run the sputniktests you must check out the test suite from googlecode.com. The test expectations are currently relative to version 28. To get the tests run the following command within -v8/tests/sputnik/ +v8/test/sputnik/ svn co http://sputniktests.googlecode.com/svn/trunk/ -r28 sputniktests diff --git a/deps/v8/tools/gyp/v8.gyp b/deps/v8/tools/gyp/v8.gyp index df8f5473a17..456fb3c3317 100644 --- a/deps/v8/tools/gyp/v8.gyp +++ b/deps/v8/tools/gyp/v8.gyp @@ -196,6 +196,38 @@ }, }, { + 'target_name': 'v8_preparser', + 'include_dirs': [ + '../../include', + '../../src', + ], + 'sources': [ + '../../src/allocation.cc', + '../../src/hashmap.cc', + '../../src/preparse-data.cc', + '../../src/preparser.cc', + '../../src/preparser-api.cc', + '../../src/scanner-base.cc', + '../../src/token.cc', + '../../src/unicode.cc', + ], + 'conditions': [ + ['OS=="win" and component=="shared_library"', { + 'sources': [ '../../src/v8preparserdll-main.cc' ], + 'defines': [ 'BUILDING_V8_SHARED' ], + 'direct_dependent_settings': { + 'defines': [ 'USING_V8_SHARED' ] + }, + 'type': '<(component)', + } , { + 'type': 'none' + }], + ['OS!="win"', { + 'type': '<(library)' + }], + ] + }, + { 'target_name': 'v8_snapshot', 'type': '<(library)', 'conditions': [ diff --git a/deps/v8/tools/logreader.js b/deps/v8/tools/logreader.js index b2aca73d218..50e3aa45c51 100644 --- a/deps/v8/tools/logreader.js +++ b/deps/v8/tools/logreader.js @@ -46,36 +46,6 @@ devtools.profiler.LogReader = function(dispatchTable) { * @type {Array.<Object>} */ this.dispatchTable_ = dispatchTable; - this.dispatchTable_['alias'] = - { parsers: [null, null], processor: this.processAlias_ }; - this.dispatchTable_['repeat'] = - { parsers: [parseInt, 'var-args'], processor: this.processRepeat_, - backrefs: true }; - - /** - * A key-value map for aliases. Translates short name -> full name. - * @type {Object} - */ - this.aliases_ = {}; - - /** - * A key-value map for previous address values. - * @type {Object} - */ - this.prevAddresses_ = {}; - - /** - * A key-value map for events than can be backreference-compressed. - * @type {Object} - */ - this.backRefsCommands_ = {}; - this.initBackRefsCommands_(); - - /** - * Back references for decompression. - * @type {Array.<string>} - */ - this.backRefs_ = []; /** * Current line. @@ -92,42 +62,6 @@ devtools.profiler.LogReader = function(dispatchTable) { /** - * Creates a parser for an address entry. - * - * @param {string} addressTag Address tag to perform offset decoding. - * @return {function(string):number} Address parser. - */ -devtools.profiler.LogReader.prototype.createAddressParser = function( - addressTag) { - var self = this; - return (function (str) { - var value = parseInt(str, 16); - var firstChar = str.charAt(0); - if (firstChar == '+' || firstChar == '-') { - var addr = self.prevAddresses_[addressTag]; - addr += value; - self.prevAddresses_[addressTag] = addr; - return addr; - } else if (firstChar != '0' || str.charAt(1) != 'x') { - self.prevAddresses_[addressTag] = value; - } - return value; - }); -}; - - -/** - * Expands an alias symbol, if applicable. - * - * @param {string} symbol Symbol to expand. - * @return {string} Expanded symbol, or the input symbol itself. - */ -devtools.profiler.LogReader.prototype.expandAlias = function(symbol) { - return symbol in this.aliases_ ? this.aliases_[symbol] : symbol; -}; - - -/** * Used for printing error messages. * * @param {string} str Error message. @@ -234,68 +168,6 @@ devtools.profiler.LogReader.prototype.dispatchLogRow_ = function(fields) { /** - * Decompresses a line if it was backreference-compressed. - * - * @param {string} line Possibly compressed line. - * @return {string} Decompressed line. - * @private - */ -devtools.profiler.LogReader.prototype.expandBackRef_ = function(line) { - var backRefPos; - // Filter out case when a regexp is created containing '#'. - if (line.charAt(line.length - 1) != '"' - && (backRefPos = line.lastIndexOf('#')) != -1) { - var backRef = line.substr(backRefPos + 1); - var backRefIdx = parseInt(backRef, 10) - 1; - var colonPos = backRef.indexOf(':'); - var backRefStart = - colonPos != -1 ? parseInt(backRef.substr(colonPos + 1), 10) : 0; - line = line.substr(0, backRefPos) + - this.backRefs_[backRefIdx].substr(backRefStart); - } - this.backRefs_.unshift(line); - if (this.backRefs_.length > 10) { - this.backRefs_.length = 10; - } - return line; -}; - - -/** - * Initializes the map of backward reference compressible commands. - * @private - */ -devtools.profiler.LogReader.prototype.initBackRefsCommands_ = function() { - for (var event in this.dispatchTable_) { - var dispatch = this.dispatchTable_[event]; - if (dispatch && dispatch.backrefs) { - this.backRefsCommands_[event] = true; - } - } -}; - - -/** - * Processes alias log record. Adds an alias to a corresponding map. - * - * @param {string} symbol Short name. - * @param {string} expansion Long name. - * @private - */ -devtools.profiler.LogReader.prototype.processAlias_ = function( - symbol, expansion) { - if (expansion in this.dispatchTable_) { - this.dispatchTable_[symbol] = this.dispatchTable_[expansion]; - if (expansion in this.backRefsCommands_) { - this.backRefsCommands_[symbol] = true; - } - } else { - this.aliases_[symbol] = expansion; - } -}; - - -/** * Processes log lines. * * @param {Array.<string>} lines Log lines. @@ -308,10 +180,6 @@ devtools.profiler.LogReader.prototype.processLog_ = function(lines) { continue; } try { - if (line.charAt(0) == '#' || - line.substr(0, line.indexOf(',')) in this.backRefsCommands_) { - line = this.expandBackRef_(line); - } var fields = this.csvParser_.parseLine(line); this.dispatchLogRow_(fields); } catch (e) { @@ -319,20 +187,3 @@ devtools.profiler.LogReader.prototype.processLog_ = function(lines) { } } }; - - -/** - * Processes repeat log record. Expands it according to calls count and - * invokes processing. - * - * @param {number} count Count. - * @param {Array.<string>} cmd Parsed command. - * @private - */ -devtools.profiler.LogReader.prototype.processRepeat_ = function(count, cmd) { - // Replace the repeat-prefixed command from backrefs list with a non-prefixed. - this.backRefs_[0] = cmd.join(','); - for (var i = 0; i < count; ++i) { - this.dispatchLogRow_(cmd); - } -}; diff --git a/deps/v8/tools/test.py b/deps/v8/tools/test.py index 6aa98318797..810f8f6394d 100755 --- a/deps/v8/tools/test.py +++ b/deps/v8/tools/test.py @@ -729,6 +729,9 @@ class Variable(Expression): if self.name in env: return ListSet([env[self.name]]) else: return Nothing() + def Evaluate(self, env, defs): + return env[self.name] + class Outcome(Expression): @@ -1175,6 +1178,9 @@ def BuildOptions(): result.add_option("--nostress", help="Don't run crankshaft --always-opt --stress-op test", default=False, action="store_true") + result.add_option("--crankshaft", + help="Run with the --crankshaft flag", + default=False, action="store_true") return result @@ -1209,6 +1215,11 @@ def ProcessOptions(options): VARIANT_FLAGS = [['--stress-opt', '--always-opt']] if options.nostress: VARIANT_FLAGS = [[],['--nocrankshaft']] + if options.crankshaft: + if options.special_command: + options.special_command += " --crankshaft" + else: + options.special_command = "@--crankshaft" return True @@ -1359,7 +1370,8 @@ def Main(): 'mode': mode, 'system': utils.GuessOS(), 'arch': options.arch, - 'simulator': options.simulator + 'simulator': options.simulator, + 'crankshaft': options.crankshaft } test_list = root.ListTests([], path, context, mode) unclassified_tests += test_list diff --git a/deps/v8/tools/tickprocessor.js b/deps/v8/tools/tickprocessor.js index a3e14c3ae58..87864d12062 100644 --- a/deps/v8/tools/tickprocessor.js +++ b/deps/v8/tools/tickprocessor.js @@ -60,18 +60,17 @@ function inherits(childCtor, parentCtor) { function SnapshotLogProcessor() { devtools.profiler.LogReader.call(this, { 'code-creation': { - parsers: [null, this.createAddressParser('code'), parseInt, null], - processor: this.processCodeCreation, backrefs: true }, - 'code-move': { parsers: [this.createAddressParser('code'), - this.createAddressParser('code-move-to')], - processor: this.processCodeMove, backrefs: true }, - 'code-delete': { parsers: [this.createAddressParser('code')], - processor: this.processCodeDelete, backrefs: true }, + parsers: [null, parseInt, parseInt, null], + processor: this.processCodeCreation }, + 'code-move': { parsers: [parseInt, parseInt], + processor: this.processCodeMove }, + 'code-delete': { parsers: [parseInt], + processor: this.processCodeDelete }, 'function-creation': null, 'function-move': null, 'function-delete': null, - 'snapshot-pos': { parsers: [this.createAddressParser('code'), parseInt], - processor: this.processSnapshotPosition, backrefs: true }}); + 'snapshot-pos': { parsers: [parseInt, parseInt], + processor: this.processSnapshotPosition }}); Profile.prototype.handleUnknownCode = function(operation, addr) { var op = devtools.profiler.Profile.Operation; @@ -95,8 +94,7 @@ inherits(SnapshotLogProcessor, devtools.profiler.LogReader); SnapshotLogProcessor.prototype.processCodeCreation = function( type, start, size, name) { - var entry = this.profile_.addCode( - this.expandAlias(type), name, start, size); + var entry = this.profile_.addCode(type, name, start, size); }; @@ -133,33 +131,28 @@ function TickProcessor( 'shared-library': { parsers: [null, parseInt, parseInt], processor: this.processSharedLibrary }, 'code-creation': { - parsers: [null, this.createAddressParser('code'), parseInt, null], - processor: this.processCodeCreation, backrefs: true }, - 'code-move': { parsers: [this.createAddressParser('code'), - this.createAddressParser('code-move-to')], - processor: this.processCodeMove, backrefs: true }, - 'code-delete': { parsers: [this.createAddressParser('code')], - processor: this.processCodeDelete, backrefs: true }, - 'function-creation': { parsers: [this.createAddressParser('code'), - this.createAddressParser('function-obj')], - processor: this.processFunctionCreation, backrefs: true }, - 'function-move': { parsers: [this.createAddressParser('code'), - this.createAddressParser('code-move-to')], - processor: this.processFunctionMove, backrefs: true }, - 'function-delete': { parsers: [this.createAddressParser('code')], - processor: this.processFunctionDelete, backrefs: true }, - 'snapshot-pos': { parsers: [this.createAddressParser('code'), parseInt], - processor: this.processSnapshotPosition, backrefs: true }, - 'tick': { parsers: [this.createAddressParser('code'), - this.createAddressParser('stack'), - this.createAddressParser('func'), parseInt, 'var-args'], - processor: this.processTick, backrefs: true }, + parsers: [null, parseInt, parseInt, null], + processor: this.processCodeCreation }, + 'code-move': { parsers: [parseInt, parseInt], + processor: this.processCodeMove }, + 'code-delete': { parsers: [parseInt], + processor: this.processCodeDelete }, + 'function-creation': { parsers: [parseInt, parseInt], + processor: this.processFunctionCreation }, + 'function-move': { parsers: [parseInt, parseInt], + processor: this.processFunctionMove }, + 'function-delete': { parsers: [parseInt], + processor: this.processFunctionDelete }, + 'snapshot-pos': { parsers: [parseInt, parseInt], + processor: this.processSnapshotPosition }, + 'tick': { parsers: [parseInt, parseInt, parseInt, parseInt, 'var-args'], + processor: this.processTick }, 'heap-sample-begin': { parsers: [null, null, parseInt], processor: this.processHeapSampleBegin }, 'heap-sample-end': { parsers: [null, null], processor: this.processHeapSampleEnd }, 'heap-js-prod-item': { parsers: [null, 'var-args'], - processor: this.processJSProducer, backrefs: true }, + processor: this.processJSProducer }, // Ignored events. 'profiler': null, 'heap-sample-stats': null, @@ -294,8 +287,7 @@ TickProcessor.prototype.processSharedLibrary = function( TickProcessor.prototype.processCodeCreation = function( type, start, size, name) { name = this.deserializedEntriesNames_[start] || name; - var entry = this.profile_.addCode( - this.expandAlias(type), name, start, size); + var entry = this.profile_.addCode(type, name, start, size); }; diff --git a/deps/v8/tools/visual_studio/v8_base.vcproj b/deps/v8/tools/visual_studio/v8_base.vcproj index fc61f46a1c9..e53b3fc350e 100644 --- a/deps/v8/tools/visual_studio/v8_base.vcproj +++ b/deps/v8/tools/visual_studio/v8_base.vcproj @@ -1,1232 +1,1280 @@ <?xml version="1.0" encoding="Windows-1252"?> <VisualStudioProject - ProjectType="Visual C++" - Version="8.00" - Name="v8_base" - ProjectGUID="{EC8B7909-62AF-470D-A75D-E1D89C837142}" - RootNamespace="v8_base" - Keyword="Win32Proj" - > - <Platforms> - <Platform - Name="Win32" - /> - </Platforms> - <ToolFiles> - </ToolFiles> - <Configurations> - <Configuration - Name="Debug|Win32" - ConfigurationType="4" - InheritedPropertySheets=".\common.vsprops;.\ia32.vsprops;.\debug.vsprops" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - <Configuration - Name="Release|Win32" - ConfigurationType="4" - InheritedPropertySheets=".\common.vsprops;.\ia32.vsprops;.\release.vsprops" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - </Configurations> - <References> - </References> - <Files> - <Filter - Name="src" - > - <File - RelativePath="..\..\src\accessors.cc" - > - </File> - <File - RelativePath="..\..\src\accessors.h" - > - </File> - <File - RelativePath="..\..\src\allocation.cc" - > - </File> - <File - RelativePath="..\..\src\allocation.h" - > - </File> - <File - RelativePath="..\..\src\api.cc" - > - </File> - <File - RelativePath="..\..\src\api.h" - > - </File> - <File - RelativePath="..\..\src\arguments.h" - > - </File> - <File - RelativePath="..\..\src\ia32\assembler-ia32-inl.h" - > - </File> - <File - RelativePath="..\..\src\ia32\assembler-ia32.cc" - > - </File> - <File - RelativePath="..\..\src\ia32\assembler-ia32.h" - > - </File> - <File - RelativePath="..\..\src\regexp-macro-assembler-irregexp-inl.h" - > - </File> - <File - RelativePath="..\..\src\regexp-stack.h" - > - </File> - <File - RelativePath="..\..\src\assembler.cc" - > - </File> - <File - RelativePath="..\..\src\assembler.h" - > - </File> - <File - RelativePath="..\..\src\ast-inl.h" - > - </File> - <File - RelativePath="..\..\src\ast.cc" - > - </File> - <File - RelativePath="..\..\src\ast.h" - > - </File> - <File - RelativePath="..\..\src\bignum.cc" - > - </File> - <File - RelativePath="..\..\src\bignum.h" - > - </File> - <File - RelativePath="..\..\src\bignum-dtoa.cc" - > - </File> - <File - RelativePath="..\..\src\bignum-dtoa.h" - > - </File> - <File - RelativePath="..\..\src\bootstrapper.cc" - > - </File> - <File - RelativePath="..\..\src\bootstrapper.h" - > - </File> - <File - RelativePath="..\..\src\ia32\builtins-ia32.cc" - > - </File> - <File - RelativePath="..\..\src\builtins.cc" - > - </File> - <File - RelativePath="..\..\src\builtins.h" - > - </File> - <File - RelativePath="..\..\src\bytecodes-irregexp.h" - > - </File> - <File - RelativePath="..\..\src\cached-powers.cc" - > - </File> - <File - RelativePath="..\..\src\cached-powers.h" - > - </File> - <File - RelativePath="..\..\src\char-predicates-inl.h" - > - </File> - <File - RelativePath="..\..\src\char-predicates.h" - > - </File> - <File - RelativePath="..\..\src\checks.cc" - > - </File> - <File - RelativePath="..\..\src\checks.h" - > - </File> - <File - RelativePath="..\..\src\circular-queue-inl.h" - > - </File> - <File - RelativePath="..\..\src\circular-queue.cc" - > - </File> - <File - RelativePath="..\..\src\circular-queue.h" - > - </File> - <File - RelativePath="..\..\src\code-stubs.cc" - > - </File> - <File - RelativePath="..\..\src\code-stubs.h" - > - </File> - <File - RelativePath="..\..\src\ia32\code-stubs-ia32.cc" - > - </File> - <File - RelativePath="..\..\src\ia32\code-stubs-ia32.h" - > - </File> - <File - RelativePath="..\..\src\code.h" - > - </File> - <File - RelativePath="..\..\src\ia32\codegen-ia32.cc" - > - </File> - <File - RelativePath="..\..\src\ia32\codegen-ia32.h" - > - </File> - <File - RelativePath="..\..\src\codegen-inl.h" - > - </File> - <File - RelativePath="..\..\src\codegen.cc" - > - </File> - <File - RelativePath="..\..\src\codegen.h" - > - </File> - <File - RelativePath="..\..\src\compilation-cache.cc" - > - </File> - <File - RelativePath="..\..\src\compilation-cache.h" - > - </File> - <File - RelativePath="..\..\src\compiler.cc" - > - </File> - <File - RelativePath="..\..\src\compiler.h" - > - </File> - <File - RelativePath="..\..\src\contexts.cc" - > - </File> - <File - RelativePath="..\..\src\contexts.h" - > - </File> - <File - RelativePath="..\..\src\conversions-inl.h" - > - </File> - <File - RelativePath="..\..\src\conversions.cc" - > - </File> - <File - RelativePath="..\..\src\conversions.h" - > - </File> - <File - RelativePath="..\..\src\counters.cc" - > - </File> - <File - RelativePath="..\..\src\counters.h" - > - </File> - <File - RelativePath="..\..\src\ia32\cpu-ia32.cc" - > - </File> - <File - RelativePath="..\..\src\cpu.h" - > - </File> - <File - RelativePath="..\..\src\cpu-profiler.cc" - > - </File> - <File - RelativePath="..\..\src\cpu-profiler.h" - > - </File> - <File - RelativePath="..\..\src\cpu-profiler-inl.h" - > - </File> - <File - RelativePath="..\..\src\data-flow.cc" - > - </File> - <File - RelativePath="..\..\src\data-flow.h" - > - </File> - <File - RelativePath="..\..\src\dateparser.cc" - > - </File> - <File - RelativePath="..\..\src\dateparser.h" - > - </File> - <File - RelativePath="..\..\src\debug-agent.cc" - > - </File> - <File - RelativePath="..\..\src\debug-agent.h" - > - </File> - <File - RelativePath="..\..\src\ia32\debug-ia32.cc" - > - </File> - <File - RelativePath="..\..\src\debug.cc" - > - </File> - <File - RelativePath="..\..\src\debug.h" - > - </File> - <File - RelativePath="..\..\src\disassembler.cc" - > - </File> - <File - RelativePath="..\..\src\disassembler.h" - > - </File> - <File - RelativePath="..\..\src\diy-fp.cc" - > - </File> - <File - RelativePath="..\..\src\diy-fp.h" - > - </File> - <File - RelativePath="..\..\src\double.h" - > - </File> - <File - RelativePath="..\..\src\dtoa.cc" - > - </File> - <File - RelativePath="..\..\src\dtoa.h" - > - </File> - <File - RelativePath="..\..\src\execution.cc" - > - </File> - <File - RelativePath="..\..\src\execution.h" - > - </File> - <File - RelativePath="..\..\src\factory.cc" - > - </File> - <File - RelativePath="..\..\src\factory.h" - > - </File> - <File - RelativePath="..\..\src\fast-dtoa.cc" - > - </File> - <File - RelativePath="..\..\src\fast-dtoa.h" - > - </File> - <File - RelativePath="..\..\src\fixed-dtoa.cc" - > - </File> - <File - RelativePath="..\..\src\fixed-dtoa.h" - > - </File> - <File - RelativePath="..\..\src\flags.cc" - > - </File> - <File - RelativePath="..\..\src\flags.h" - > - </File> - <File - RelativePath="..\..\src\frame-element.cc" - > - </File> - <File - RelativePath="..\..\src\frame-element.h" - > - </File> - <File - RelativePath="..\..\src\ia32\frames-ia32.cc" - > - </File> - <File - RelativePath="..\..\src\ia32\frames-ia32.h" - > - </File> - <File - RelativePath="..\..\src\frames-inl.h" - > - </File> - <File - RelativePath="..\..\src\frames.cc" - > - </File> - <File - RelativePath="..\..\src\frames.h" - > - </File> - <File - RelativePath="..\..\src\ia32\full-codegen-ia32.cc" - > - </File> - <File - RelativePath="..\..\src\full-codegen.cc" - > - </File> - <File - RelativePath="..\..\src\full-codegen.h" - > - </File> - <File - RelativePath="..\..\src\func-name-inferrer.cc" - > - </File> - <File - RelativePath="..\..\src\func-name-inferrer.h" - > - </File> - <File - RelativePath="..\..\src\global-handles.cc" - > - </File> - <File - RelativePath="..\..\src\global-handles.h" - > - </File> - <File - RelativePath="..\..\src\globals.h" - > - </File> - <File - RelativePath="..\..\src\handles-inl.h" - > - </File> - <File - RelativePath="..\..\src\handles.cc" - > - </File> - <File - RelativePath="..\..\src\handles.h" - > - </File> - <File - RelativePath="..\..\src\hashmap.cc" - > - </File> - <File - RelativePath="..\..\src\hashmap.h" - > - </File> - <File - RelativePath="..\..\src\heap-inl.h" - > - </File> - <File - RelativePath="..\..\src\heap.cc" - > - </File> - <File - RelativePath="..\..\src\heap.h" - > - </File> - <File - RelativePath="..\..\src\heap-profiler.cc" - > - </File> - <File - RelativePath="..\..\src\heap-profiler.h" - > - </File> - <File - RelativePath="..\..\src\hydrogen.cc" - > - </File> - <File - RelativePath="..\..\src\hydrogen.h" - > - </File> - <File - RelativePath="..\..\src\hydrogen-instructions.cc" - > - </File> - <File - RelativePath="..\..\src\hydrogen-instructions.h" - > - </File> - <File - RelativePath="..\..\src\ia32\ic-ia32.cc" - > - </File> - <File - RelativePath="..\..\src\ic-inl.h" - > - </File> - <File - RelativePath="..\..\src\ic.cc" - > - </File> - <File - RelativePath="..\..\src\ic.h" - > - </File> - <File - RelativePath="..\..\src\interceptors.h" - > - </File> - <File - RelativePath="..\..\src\interpreter-irregexp.cc" - > - </File> - <File - RelativePath="..\..\src\interpreter-irregexp.h" - > - </File> - <File - RelativePath="..\..\src\jump-target.h" - > - </File> - <File - RelativePath="..\..\src\jump-target-inl.h" - > - </File> - <File - RelativePath="..\..\src\jump-target-heavy-inl.h" - > - </File> - <File - RelativePath="..\..\src\jump-target-heavy.h" - > - </File> - <File - RelativePath="..\..\src\jump-target.cc" - > - </File> - <File - RelativePath="..\..\src\ia32\jump-target-ia32.cc" - > - </File> - <File - RelativePath="..\..\src\jump-target-heavy.cc" - > - </File> - <File - RelativePath="..\..\src\jsregexp.cc" - > - </File> - <File - RelativePath="..\..\src\jsregexp.h" - > - </File> - <File - RelativePath="..\..\src\list-inl.h" - > - </File> - <File - RelativePath="..\..\src\list.h" - > - </File> - <File - RelativePath="..\..\src\liveedit.cc" - > - </File> - <File - RelativePath="..\..\src\liveedit.h" - > - </File> - <File - RelativePath="..\..\src\log.cc" - > - </File> - <File - RelativePath="..\..\src\log-inl.h" - > - </File> - <File - RelativePath="..\..\src\log.h" - > - </File> - <File - RelativePath="..\..\src\log-utils.cc" - > - </File> - <File - RelativePath="..\..\src\log-utils.h" - > - </File> - <File - RelativePath="..\..\src\ia32\macro-assembler-ia32.cc" - > - </File> - <File - RelativePath="..\..\src\ia32\macro-assembler-ia32.h" - > - </File> - <File - RelativePath="..\..\src\macro-assembler.h" - > - </File> - <File - RelativePath="..\..\src\mark-compact.cc" - > - </File> - <File - RelativePath="..\..\src\mark-compact.h" - > - </File> - <File - RelativePath="..\..\src\memory.h" - > - </File> - <File - RelativePath="..\..\src\messages.cc" - > - </File> - <File - RelativePath="..\..\src\messages.h" - > - </File> - <File - RelativePath="..\..\src\natives.h" - > - </File> - <File - RelativePath="..\..\src\objects-debug.cc" - > - <FileConfiguration - Name="Release|Win32" - ExcludedFromBuild="true" - > - <Tool - Name="VCCLCompilerTool" - /> - </FileConfiguration> - </File> - <File - RelativePath="..\..\src\objects-inl.h" - > - </File> - <File - RelativePath="..\..\src\objects-visiting.cc" - > - </File> - <File - RelativePath="..\..\src\objects-visiting.h" - > - </File> + ProjectType="Visual C++" + Version="8.00" + Name="v8_base" + ProjectGUID="{EC8B7909-62AF-470D-A75D-E1D89C837142}" + RootNamespace="v8_base" + Keyword="Win32Proj" + > + <Platforms> + <Platform + Name="Win32" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|Win32" + ConfigurationType="4" + InheritedPropertySheets=".\common.vsprops;.\ia32.vsprops;.\debug.vsprops" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLibrarianTool" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Release|Win32" + ConfigurationType="4" + InheritedPropertySheets=".\common.vsprops;.\ia32.vsprops;.\release.vsprops" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLibrarianTool" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <Filter + Name="src" + > + <File + RelativePath="..\..\src\accessors.cc" + > + </File> + <File + RelativePath="..\..\src\accessors.h" + > + </File> + <File + RelativePath="..\..\src\allocation.cc" + > + </File> + <File + RelativePath="..\..\src\allocation.h" + > + </File> + <File + RelativePath="..\..\src\api.cc" + > + </File> + <File + RelativePath="..\..\src\api.h" + > + </File> + <File + RelativePath="..\..\src\atomicops_internals_x86_msvc.h" + > + </File> + <File + RelativePath="..\..\src\arguments.h" + > + </File> + <File + RelativePath="..\..\src\ia32\assembler-ia32-inl.h" + > + </File> + <File + RelativePath="..\..\src\ia32\assembler-ia32.cc" + > + </File> + <File + RelativePath="..\..\src\ia32\assembler-ia32.h" + > + </File> + <File + RelativePath="..\..\src\regexp-macro-assembler-irregexp-inl.h" + > + </File> + <File + RelativePath="..\..\src\regexp-stack.h" + > + </File> + <File + RelativePath="..\..\src\assembler.cc" + > + </File> + <File + RelativePath="..\..\src\assembler.h" + > + </File> + <File + RelativePath="..\..\src\ast-inl.h" + > + </File> + <File + RelativePath="..\..\src\ast.cc" + > + </File> + <File + RelativePath="..\..\src\ast.h" + > + </File> + <File + RelativePath="..\..\src\bignum.cc" + > + </File> + <File + RelativePath="..\..\src\bignum.h" + > + </File> + <File + RelativePath="..\..\src\bignum-dtoa.cc" + > + </File> + <File + RelativePath="..\..\src\bignum-dtoa.h" + > + </File> + <File + RelativePath="..\..\src\bootstrapper.cc" + > + </File> + <File + RelativePath="..\..\src\bootstrapper.h" + > + </File> + <File + RelativePath="..\..\src\ia32\builtins-ia32.cc" + > + </File> + <File + RelativePath="..\..\src\builtins.cc" + > + </File> + <File + RelativePath="..\..\src\builtins.h" + > + </File> + <File + RelativePath="..\..\src\bytecodes-irregexp.h" + > + </File> + <File + RelativePath="..\..\src\cached-powers.cc" + > + </File> + <File + RelativePath="..\..\src\cached-powers.h" + > + </File> + <File + RelativePath="..\..\src\char-predicates-inl.h" + > + </File> + <File + RelativePath="..\..\src\char-predicates.h" + > + </File> + <File + RelativePath="..\..\src\checks.cc" + > + </File> + <File + RelativePath="..\..\src\checks.h" + > + </File> + <File + RelativePath="..\..\src\circular-queue-inl.h" + > + </File> + <File + RelativePath="..\..\src\circular-queue.cc" + > + </File> + <File + RelativePath="..\..\src\circular-queue.h" + > + </File> + <File + RelativePath="..\..\src\code-stubs.cc" + > + </File> + <File + RelativePath="..\..\src\code-stubs.h" + > + </File> + <File + RelativePath="..\..\src\ia32\code-stubs-ia32.cc" + > + </File> + <File + RelativePath="..\..\src\ia32\code-stubs-ia32.h" + > + </File> + <File + RelativePath="..\..\src\code.h" + > + </File> + <File + RelativePath="..\..\src\ia32\codegen-ia32.cc" + > + </File> + <File + RelativePath="..\..\src\ia32\codegen-ia32.h" + > + </File> + <File + RelativePath="..\..\src\codegen-inl.h" + > + </File> + <File + RelativePath="..\..\src\codegen.cc" + > + </File> + <File + RelativePath="..\..\src\codegen.h" + > + </File> + <File + RelativePath="..\..\src\compilation-cache.cc" + > + </File> + <File + RelativePath="..\..\src\compilation-cache.h" + > + </File> + <File + RelativePath="..\..\src\compiler.cc" + > + </File> + <File + RelativePath="..\..\src\compiler.h" + > + </File> + <File + RelativePath="..\..\src\contexts.cc" + > + </File> + <File + RelativePath="..\..\src\contexts.h" + > + </File> + <File + RelativePath="..\..\src\conversions-inl.h" + > + </File> + <File + RelativePath="..\..\src\conversions.cc" + > + </File> + <File + RelativePath="..\..\src\conversions.h" + > + </File> + <File + RelativePath="..\..\src\counters.cc" + > + </File> + <File + RelativePath="..\..\src\counters.h" + > + </File> + <File + RelativePath="..\..\src\ia32\cpu-ia32.cc" + > + </File> + <File + RelativePath="..\..\src\cpu.h" + > + </File> + <File + RelativePath="..\..\src\cpu-profiler.cc" + > + </File> + <File + RelativePath="..\..\src\cpu-profiler.h" + > + </File> + <File + RelativePath="..\..\src\cpu-profiler-inl.h" + > + </File> + <File + RelativePath="..\..\src\data-flow.cc" + > + </File> + <File + RelativePath="..\..\src\data-flow.h" + > + </File> + <File + RelativePath="..\..\src\dateparser.cc" + > + </File> + <File + RelativePath="..\..\src\dateparser.h" + > + </File> + <File + RelativePath="..\..\src\debug-agent.cc" + > + </File> + <File + RelativePath="..\..\src\debug-agent.h" + > + </File> + <File + RelativePath="..\..\src\ia32\debug-ia32.cc" + > + </File> + <File + RelativePath="..\..\src\debug.cc" + > + </File> + <File + RelativePath="..\..\src\debug.h" + > + </File> + <File + RelativePath="..\..\src\ia32\deoptimizer-ia32.cc" + > + </File> + <File + RelativePath="..\..\src\deoptimizer.cc" + > + </File> + <File + RelativePath="..\..\src\deoptimizer.h" + > + </File> + <File + RelativePath="..\..\src\disassembler.cc" + > + </File> + <File + RelativePath="..\..\src\disassembler.h" + > + </File> + <File + RelativePath="..\..\src\diy-fp.cc" + > + </File> + <File + RelativePath="..\..\src\diy-fp.h" + > + </File> + <File + RelativePath="..\..\src\double.h" + > + </File> + <File + RelativePath="..\..\src\dtoa.cc" + > + </File> + <File + RelativePath="..\..\src\dtoa.h" + > + </File> + <File + RelativePath="..\..\src\execution.cc" + > + </File> + <File + RelativePath="..\..\src\execution.h" + > + </File> + <File + RelativePath="..\..\src\factory.cc" + > + </File> + <File + RelativePath="..\..\src\factory.h" + > + </File> + <File + RelativePath="..\..\src\fast-dtoa.cc" + > + </File> + <File + RelativePath="..\..\src\fast-dtoa.h" + > + </File> + <File + RelativePath="..\..\src\fixed-dtoa.cc" + > + </File> + <File + RelativePath="..\..\src\fixed-dtoa.h" + > + </File> + <File + RelativePath="..\..\src\flags.cc" + > + </File> + <File + RelativePath="..\..\src\flags.h" + > + </File> + <File + RelativePath="..\..\src\frame-element.cc" + > + </File> + <File + RelativePath="..\..\src\frame-element.h" + > + </File> + <File + RelativePath="..\..\src\ia32\frames-ia32.cc" + > + </File> + <File + RelativePath="..\..\src\ia32\frames-ia32.h" + > + </File> + <File + RelativePath="..\..\src\frames-inl.h" + > + </File> + <File + RelativePath="..\..\src\frames.cc" + > + </File> + <File + RelativePath="..\..\src\frames.h" + > + </File> + <File + RelativePath="..\..\src\ia32\full-codegen-ia32.cc" + > + </File> + <File + RelativePath="..\..\src\full-codegen.cc" + > + </File> + <File + RelativePath="..\..\src\full-codegen.h" + > + </File> + <File + RelativePath="..\..\src\func-name-inferrer.cc" + > + </File> + <File + RelativePath="..\..\src\func-name-inferrer.h" + > + </File> + <File + RelativePath="..\..\src\global-handles.cc" + > + </File> + <File + RelativePath="..\..\src\global-handles.h" + > + </File> + <File + RelativePath="..\..\src\globals.h" + > + </File> + <File + RelativePath="..\..\src\handles-inl.h" + > + </File> + <File + RelativePath="..\..\src\handles.cc" + > + </File> + <File + RelativePath="..\..\src\handles.h" + > + </File> + <File + RelativePath="..\..\src\hashmap.cc" + > + </File> + <File + RelativePath="..\..\src\hashmap.h" + > + </File> + <File + RelativePath="..\..\src\heap-inl.h" + > + </File> + <File + RelativePath="..\..\src\heap.cc" + > + </File> + <File + RelativePath="..\..\src\heap.h" + > + </File> + <File + RelativePath="..\..\src\hydrogen.cc" + > + </File> + <File + RelativePath="..\..\src\hydrogen.h" + > + </File> + <File + RelativePath="..\..\src\heap-profiler.cc" + > + </File> + <File + RelativePath="..\..\src\heap-profiler.h" + > + </File> + <File + RelativePath="..\..\src\hydrogen.cc" + > + </File> + <File + RelativePath="..\..\src\hydrogen.h" + > + </File> + <File + RelativePath="..\..\src\hydrogen-instructions.cc" + > + </File> + <File + RelativePath="..\..\src\hydrogen-instructions.h" + > + </File> + <File + RelativePath="..\..\src\ia32\ic-ia32.cc" + > + </File> + <File + RelativePath="..\..\src\ic-inl.h" + > + </File> + <File + RelativePath="..\..\src\ic.cc" + > + </File> + <File + RelativePath="..\..\src\ic.h" + > + </File> + <File + RelativePath="..\..\src\interceptors.h" + > + </File> + <File + RelativePath="..\..\src\interpreter-irregexp.cc" + > + </File> + <File + RelativePath="..\..\src\interpreter-irregexp.h" + > + </File> + <File + RelativePath="..\..\src\jump-target.h" + > + </File> + <File + RelativePath="..\..\src\jump-target-inl.h" + > + </File> + <File + RelativePath="..\..\src\jump-target-heavy-inl.h" + > + </File> + <File + RelativePath="..\..\src\jump-target-heavy.h" + > + </File> + <File + RelativePath="..\..\src\jump-target.cc" + > + </File> + <File + RelativePath="..\..\src\ia32\jump-target-ia32.cc" + > + </File> + <File + RelativePath="..\..\src\jump-target-heavy.cc" + > + </File> + <File + RelativePath="..\..\src\jsregexp.cc" + > + </File> + <File + RelativePath="..\..\src\jsregexp.h" + > + </File> + <File + RelativePath="..\..\src\list-inl.h" + > + </File> + <File + RelativePath="..\..\src\list.h" + > + </File> + <File + RelativePath="..\..\src\lithium-allocator.cc" + > + </File> + <File + RelativePath="..\..\src\lithium-allocator.h" + > + </File> + <File + RelativePath="..\..\src\ia32\lithium-ia32.cc" + > + </File> + <File + RelativePath="..\..\src\ia32\lithium-ia32.h" + > + </File> + <File + RelativePath="..\..\src\ia32\lithium-codegen-ia32.cc" + > + </File> + <File + RelativePath="..\..\src\ia32\lithium-codegen-ia32.h" + > + </File> + <File + RelativePath="..\..\src\liveedit.cc" + > + </File> + <File + RelativePath="..\..\src\liveedit.h" + > + </File> + <File + RelativePath="..\..\src\log.cc" + > + </File> + <File + RelativePath="..\..\src\log-inl.h" + > + </File> + <File + RelativePath="..\..\src\log.h" + > + </File> + <File + RelativePath="..\..\src\log-utils.cc" + > + </File> + <File + RelativePath="..\..\src\log-utils.h" + > + </File> + <File + RelativePath="..\..\src\ia32\macro-assembler-ia32.cc" + > + </File> + <File + RelativePath="..\..\src\ia32\macro-assembler-ia32.h" + > + </File> + <File + RelativePath="..\..\src\macro-assembler.h" + > + </File> + <File + RelativePath="..\..\src\mark-compact.cc" + > + </File> + <File + RelativePath="..\..\src\mark-compact.h" + > + </File> + <File + RelativePath="..\..\src\memory.h" + > + </File> + <File + RelativePath="..\..\src\messages.cc" + > + </File> + <File + RelativePath="..\..\src\messages.h" + > + </File> + <File + RelativePath="..\..\src\natives.h" + > + </File> + <File + RelativePath="..\..\src\objects-debug.cc" + > + <FileConfiguration + Name="Release|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCLCompilerTool" + /> + </FileConfiguration> + </File> + <File + RelativePath="..\..\src\objects-inl.h" + > + </File> + <File + RelativePath="..\..\src\objects-visiting.cc" + > + </File> + <File + RelativePath="..\..\src\objects-visiting.h" + > + </File> - <File - RelativePath="..\..\src\objects.cc" - > - </File> - <File - RelativePath="..\..\src\objects.h" - > - </File> - <File - RelativePath="..\..\src\oprofile-agent.cc" - > - </File> - <File - RelativePath="..\..\src\oprofile-agent.h" - > - </File> - <File - RelativePath="..\..\src\parser.cc" - > - </File> - <File - RelativePath="..\..\src\parser.h" - > - </File> - <File - RelativePath="..\..\src\preparser.cc" - > - </File> - <File - RelativePath="..\..\src\preparser.h" - > - </File> - <File - RelativePath="..\..\src\preparse-data.cc" - > - </File> - <File - RelativePath="..\..\src\preparse-data.h" - > - </File> - <File - RelativePath="..\..\src\profile-generator.cc" - > - </File> - <File - RelativePath="..\..\src\profile-generator.h" - > - </File> - <File - RelativePath="..\..\src\profile-generator-inl.h" - > - </File> - <File - RelativePath="..\..\src\platform-win32.cc" - > - </File> - <File - RelativePath="..\..\src\platform.h" - > - </File> - <File - RelativePath="..\..\src\prettyprinter.cc" - > - <FileConfiguration - Name="Release|Win32" - ExcludedFromBuild="true" - > - <Tool - Name="VCCLCompilerTool" - /> - </FileConfiguration> - </File> - <File - RelativePath="..\..\src\prettyprinter.h" - > - </File> - <File - RelativePath="..\..\src\property.cc" - > - </File> - <File - RelativePath="..\..\src\property.h" - > - </File> - <File - RelativePath="..\..\src\ia32\regexp-macro-assembler-ia32.cc" - > - </File> - <File - RelativePath="..\..\src\ia32\regexp-macro-assembler-ia32.h" - > - </File> - <File - RelativePath="..\..\src\regexp-macro-assembler-irregexp.cc" - > - </File> - <File - RelativePath="..\..\src\regexp-macro-assembler-irregexp.h" - > - </File> - <File - RelativePath="..\..\src\regexp-macro-assembler.cc" - > - </File> - <File - RelativePath="..\..\src\regexp-macro-assembler.h" - > - </File> - <File - RelativePath="..\..\src\regexp-macro-assembler-tracer.cc" - > - </File> - <File - RelativePath="..\..\src\regexp-macro-assembler-tracer.h" - > - </File> - <File - RelativePath="..\..\src\regexp-stack.cc" - > - </File> - <File - RelativePath="..\..\src\register-allocator.h" - > - </File> - <File - RelativePath="..\..\src\register-allocator.cc" - > - </File> - <File - RelativePath="..\..\src\ia32\register-allocator-ia32.cc" - > - </File> - <File - RelativePath="..\..\src\rewriter.cc" - > - </File> - <File - RelativePath="..\..\src\rewriter.h" - > - </File> - <File - RelativePath="..\..\src\runtime.cc" - > - </File> - <File - RelativePath="..\..\src\runtime.h" - > - </File> - <File - RelativePath="..\..\src\runtime-profiler.cc" - > - </File> - <File - RelativePath="..\..\src\runtime-profiler.h" - > - </File> - <File - RelativePath="..\..\src\safepoint-table.cc" - > - </File> - <File - RelativePath="..\..\src\safepoint-table.h" - > - </File> - <File - RelativePath="..\..\src\scanner-base.cc" - > - </File> - <File - RelativePath="..\..\src\scanner-base.h" - > - </File> - <File - RelativePath="..\..\src\scanner.cc" - > - </File> - <File - RelativePath="..\..\src\scanner.h" - > - </File> - <File - RelativePath="..\..\src\scopeinfo.cc" - > - </File> - <File - RelativePath="..\..\src\scopeinfo.h" - > - </File> - <File - RelativePath="..\..\src\scopes.cc" - > - </File> - <File - RelativePath="..\..\src\scopes.h" - > - </File> - <File - RelativePath="..\..\src\serialize.cc" - > - </File> - <File - RelativePath="..\..\src\serialize.h" - > - </File> - <File - RelativePath="..\..\src\shell.h" - > - </File> - <File - RelativePath="..\..\src\snapshot-common.cc" - > - </File> - <File - RelativePath="..\..\src\snapshot.h" - > - </File> - <File - RelativePath="..\..\src\spaces-inl.h" - > - </File> - <File - RelativePath="..\..\src\spaces.cc" - > - </File> - <File - RelativePath="..\..\src\spaces.h" - > - </File> - <File - RelativePath="..\..\src\string-search.cc" - > - </File> - <File - RelativePath="..\..\src\string-search.h" - > - </File> - <File - RelativePath="..\..\src\string-stream.cc" - > - </File> - <File - RelativePath="..\..\src\string-stream.h" - > - </File> - <File - RelativePath="..\..\src\strtod.cc" - > - </File> - <File - RelativePath="..\..\src\strtod.h" - > - </File> - <File - RelativePath="..\..\src\ia32\stub-cache-ia32.cc" - > - </File> - <File - RelativePath="..\..\src\stub-cache.cc" - > - </File> - <File - RelativePath="..\..\src\stub-cache.h" - > - </File> - <File - RelativePath="..\..\src\token.cc" - > - </File> - <File - RelativePath="..\..\src\token.h" - > - </File> - <File - RelativePath="..\..\src\top.cc" - > - </File> - <File - RelativePath="..\..\src\top.h" - > - </File> - <File - RelativePath="..\..\src\type-info.cc" - > - </File> - <File - RelativePath="..\..\src\type-info.h" - > - </File> - <File - RelativePath="..\..\src\unbound-queue-inl.h" - > - </File> - <File - RelativePath="..\..\src\unbound-queue.h" - > - </File> - <File - RelativePath="..\..\src\unicode-inl.h" - > - </File> - <File - RelativePath="..\..\src\unicode.h" - > - </File> - <File - RelativePath="..\..\src\utils.cc" - > - </File> - <File - RelativePath="..\..\src\utils.h" - > - </File> - <File - RelativePath="..\..\src\v8-counters.cc" - > - </File> - <File - RelativePath="..\..\src\v8-counters.h" - > - </File> - <File - RelativePath="..\..\src\v8.cc" - > - </File> - <File - RelativePath="..\..\src\v8.h" - > - </File> - <File - RelativePath="..\..\src\v8checks.h" - > - </File> - <File - RelativePath="..\..\src\v8globals.h" - > - </File> - <File - RelativePath="..\..\src\v8threads.cc" - > - </File> - <File - RelativePath="..\..\src\v8threads.h" - > - </File> - <File - RelativePath="..\..\src\v8utils.h" - > - </File> - <File - RelativePath="..\..\src\variables.cc" - > - </File> - <File - RelativePath="..\..\src\variables.h" - > - </File> - <File - RelativePath="..\..\src\version.cc" - > - </File> - <File - RelativePath="..\..\src\version.h" - > - </File> - <File - RelativePath="..\..\src\virtual-frame-inl.h" - > - </File> - <File - RelativePath="..\..\src\virtual-frame-heavy-inl.h" - > - </File> - <File - RelativePath="..\..\src\virtual-frame.h" - > - </File> - <File - RelativePath="..\..\src\ia32\virtual-frame-ia32.h" - > - </File> - <File - RelativePath="..\..\src\virtual-frame.cc" - > - </File> - <File - RelativePath="..\..\src\ia32\virtual-frame-ia32.cc" - > - </File> - <File - RelativePath="..\..\src\virtual-frame-heavy.cc" - > - </File> - <File - RelativePath="..\..\src\vm-state-inl.h" - > - </File> - <File - RelativePath="..\..\src\vm-state.h" - > - </File> - <File - RelativePath="..\..\src\zone-inl.h" - > - </File> - <File - RelativePath="..\..\src\zone.cc" - > - </File> - <File - RelativePath="..\..\src\zone.h" - > - </File> - <File - RelativePath="..\..\src\extensions\externalize-string-extension.cc" - > - </File> - <File - RelativePath="..\..\src\extensions\externalize-string-extension.h" - > - </File> - <File - RelativePath="..\..\src\extensions\gc-extension.cc" - > - </File> - <File - RelativePath="..\..\src\extensions\gc-extension.h" - > - </File> - <Filter - Name="third party" - > - <File - RelativePath="..\..\src\ia32\disasm-ia32.cc" - > - </File> - <File - RelativePath="..\..\src\disasm.h" - > - </File> - </Filter> - <Filter - Name="generated files" - > - <File - RelativePath="..\..\src\unicode.cc" - > - </File> - </Filter> - </Filter> - <Filter - Name="include" - > - <File - RelativePath="..\..\include\v8-debug.h" - > - </File> - <File - RelativePath="..\..\include\v8-profiler.h" - > - </File> - <File - RelativePath="..\..\include\v8-testing.h" - > - </File> - <File - RelativePath="..\..\include\v8.h" - > - </File> - <File - RelativePath="..\..\include\v8stdint.h" - > - </File> - </Filter> - </Files> - <Globals> - </Globals> + <File + RelativePath="..\..\src\objects.cc" + > + </File> + <File + RelativePath="..\..\src\objects.h" + > + </File> + <File + RelativePath="..\..\src\oprofile-agent.cc" + > + </File> + <File + RelativePath="..\..\src\oprofile-agent.h" + > + </File> + <File + RelativePath="..\..\src\parser.cc" + > + </File> + <File + RelativePath="..\..\src\parser.h" + > + </File> + <File + RelativePath="..\..\src\preparser.cc" + > + </File> + <File + RelativePath="..\..\src\preparser.h" + > + </File> + <File + RelativePath="..\..\src\preparse-data.cc" + > + </File> + <File + RelativePath="..\..\src\preparse-data.h" + > + </File> + <File + RelativePath="..\..\src\profile-generator.cc" + > + </File> + <File + RelativePath="..\..\src\profile-generator.h" + > + </File> + <File + RelativePath="..\..\src\profile-generator-inl.h" + > + </File> + <File + RelativePath="..\..\src\platform-win32.cc" + > + </File> + <File + RelativePath="..\..\src\platform.h" + > + </File> + <File + RelativePath="..\..\src\prettyprinter.cc" + > + <FileConfiguration + Name="Release|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCLCompilerTool" + /> + </FileConfiguration> + </File> + <File + RelativePath="..\..\src\prettyprinter.h" + > + </File> + <File + RelativePath="..\..\src\property.cc" + > + </File> + <File + RelativePath="..\..\src\property.h" + > + </File> + <File + RelativePath="..\..\src\ia32\regexp-macro-assembler-ia32.cc" + > + </File> + <File + RelativePath="..\..\src\ia32\regexp-macro-assembler-ia32.h" + > + </File> + <File + RelativePath="..\..\src\regexp-macro-assembler-irregexp.cc" + > + </File> + <File + RelativePath="..\..\src\regexp-macro-assembler-irregexp.h" + > + </File> + <File + RelativePath="..\..\src\regexp-macro-assembler.cc" + > + </File> + <File + RelativePath="..\..\src\regexp-macro-assembler.h" + > + </File> + <File + RelativePath="..\..\src\regexp-macro-assembler-tracer.cc" + > + </File> + <File + RelativePath="..\..\src\regexp-macro-assembler-tracer.h" + > + </File> + <File + RelativePath="..\..\src\regexp-stack.cc" + > + </File> + <File + RelativePath="..\..\src\register-allocator.h" + > + </File> + <File + RelativePath="..\..\src\register-allocator.cc" + > + </File> + <File + RelativePath="..\..\src\ia32\register-allocator-ia32.cc" + > + </File> + <File + RelativePath="..\..\src\rewriter.cc" + > + </File> + <File + RelativePath="..\..\src\rewriter.h" + > + </File> + <File + RelativePath="..\..\src\runtime.cc" + > + </File> + <File + RelativePath="..\..\src\runtime.h" + > + </File> + <File + RelativePath="..\..\src\runtime-profiler.cc" + > + </File> + <File + RelativePath="..\..\src\runtime-profiler.h" + > + </File> + <File + RelativePath="..\..\src\safepoint-table.cc" + > + </File> + <File + RelativePath="..\..\src\safepoint-table.h" + > + </File> + <File + RelativePath="..\..\src\scanner-base.cc" + > + </File> + <File + RelativePath="..\..\src\scanner-base.h" + > + </File> + <File + RelativePath="..\..\src\scanner.cc" + > + </File> + <File + RelativePath="..\..\src\scanner.h" + > + </File> + <File + RelativePath="..\..\src\scopeinfo.cc" + > + </File> + <File + RelativePath="..\..\src\scopeinfo.h" + > + </File> + <File + RelativePath="..\..\src\scopes.cc" + > + </File> + <File + RelativePath="..\..\src\scopes.h" + > + </File> + <File + RelativePath="..\..\src\serialize.cc" + > + </File> + <File + RelativePath="..\..\src\serialize.h" + > + </File> + <File + RelativePath="..\..\src\shell.h" + > + </File> + <File + RelativePath="..\..\src\snapshot-common.cc" + > + </File> + <File + RelativePath="..\..\src\snapshot.h" + > + </File> + <File + RelativePath="..\..\src\spaces-inl.h" + > + </File> + <File + RelativePath="..\..\src\spaces.cc" + > + </File> + <File + RelativePath="..\..\src\spaces.h" + > + </File> + <File + RelativePath="..\..\src\string-search.cc" + > + </File> + <File + RelativePath="..\..\src\string-search.h" + > + </File> + <File + RelativePath="..\..\src\string-stream.cc" + > + </File> + <File + RelativePath="..\..\src\string-stream.h" + > + </File> + <File + RelativePath="..\..\src\strtod.cc" + > + </File> + <File + RelativePath="..\..\src\strtod.h" + > + </File> + <File + RelativePath="..\..\src\ia32\stub-cache-ia32.cc" + > + </File> + <File + RelativePath="..\..\src\stub-cache.cc" + > + </File> + <File + RelativePath="..\..\src\stub-cache.h" + > + </File> + <File + RelativePath="..\..\src\token.cc" + > + </File> + <File + RelativePath="..\..\src\token.h" + > + </File> + <File + RelativePath="..\..\src\top.cc" + > + </File> + <File + RelativePath="..\..\src\top.h" + > + </File> + <File + RelativePath="..\..\src\type-info.cc" + > + </File> + <File + RelativePath="..\..\src\type-info.h" + > + </File> + <File + RelativePath="..\..\src\unbound-queue-inl.h" + > + </File> + <File + RelativePath="..\..\src\unbound-queue.h" + > + </File> + <File + RelativePath="..\..\src\unicode-inl.h" + > + </File> + <File + RelativePath="..\..\src\unicode.h" + > + </File> + <File + RelativePath="..\..\src\utils.cc" + > + </File> + <File + RelativePath="..\..\src\utils.h" + > + </File> + <File + RelativePath="..\..\src\v8-counters.cc" + > + </File> + <File + RelativePath="..\..\src\v8-counters.h" + > + </File> + <File + RelativePath="..\..\src\v8.cc" + > + </File> + <File + RelativePath="..\..\src\v8.h" + > + </File> + <File + RelativePath="..\..\src\v8checks.h" + > + </File> + <File + RelativePath="..\..\src\v8globals.h" + > + </File> + <File + RelativePath="..\..\src\v8threads.cc" + > + </File> + <File + RelativePath="..\..\src\v8threads.h" + > + </File> + <File + RelativePath="..\..\src\v8utils.h" + > + </File> + <File + RelativePath="..\..\src\variables.cc" + > + </File> + <File + RelativePath="..\..\src\variables.h" + > + </File> + <File + RelativePath="..\..\src\version.cc" + > + </File> + <File + RelativePath="..\..\src\version.h" + > + </File> + <File + RelativePath="..\..\src\virtual-frame-inl.h" + > + </File> + <File + RelativePath="..\..\src\virtual-frame-heavy-inl.h" + > + </File> + <File + RelativePath="..\..\src\virtual-frame.h" + > + </File> + <File + RelativePath="..\..\src\ia32\virtual-frame-ia32.h" + > + </File> + <File + RelativePath="..\..\src\virtual-frame.cc" + > + </File> + <File + RelativePath="..\..\src\ia32\virtual-frame-ia32.cc" + > + </File> + <File + RelativePath="..\..\src\virtual-frame-heavy.cc" + > + </File> + <File + RelativePath="..\..\src\vm-state-inl.h" + > + </File> + <File + RelativePath="..\..\src\vm-state.h" + > + </File> + <File + RelativePath="..\..\src\zone-inl.h" + > + </File> + <File + RelativePath="..\..\src\zone.cc" + > + </File> + <File + RelativePath="..\..\src\zone.h" + > + </File> + <File + RelativePath="..\..\src\extensions\externalize-string-extension.cc" + > + </File> + <File + RelativePath="..\..\src\extensions\externalize-string-extension.h" + > + </File> + <File + RelativePath="..\..\src\extensions\gc-extension.cc" + > + </File> + <File + RelativePath="..\..\src\extensions\gc-extension.h" + > + </File> + <Filter + Name="third party" + > + <File + RelativePath="..\..\src\ia32\disasm-ia32.cc" + > + </File> + <File + RelativePath="..\..\src\disasm.h" + > + </File> + </Filter> + <Filter + Name="generated files" + > + <File + RelativePath="..\..\src\unicode.cc" + > + </File> + </Filter> + </Filter> + <Filter + Name="include" + > + <File + RelativePath="..\..\include\v8-debug.h" + > + </File> + <File + RelativePath="..\..\include\v8-profiler.h" + > + </File> + <File + RelativePath="..\..\include\v8-testing.h" + > + </File> + <File + RelativePath="..\..\include\v8.h" + > + </File> + <File + RelativePath="..\..\include\v8stdint.h" + > + </File> + </Filter> + </Files> + <Globals> + </Globals> </VisualStudioProject> diff --git a/deps/v8/tools/visual_studio/v8_base_arm.vcproj b/deps/v8/tools/visual_studio/v8_base_arm.vcproj index 949e6df1c26..1054958aafe 100644 --- a/deps/v8/tools/visual_studio/v8_base_arm.vcproj +++ b/deps/v8/tools/visual_studio/v8_base_arm.vcproj @@ -1,1170 +1,1234 @@ <?xml version="1.0" encoding="Windows-1252"?> <VisualStudioProject - ProjectType="Visual C++" - Version="8.00" - Name="v8_base" - ProjectGUID="{EC8B7909-62AF-470D-A75D-E1D89C837142}" - RootNamespace="v8_base" - Keyword="Win32Proj" - > - <Platforms> - <Platform - Name="Win32" - /> - </Platforms> - <ToolFiles> - </ToolFiles> - <Configurations> - <Configuration - Name="Debug|Win32" - ConfigurationType="4" - InheritedPropertySheets=".\common.vsprops;.\debug.vsprops;.\arm.vsprops" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - <Configuration - Name="Release|Win32" - ConfigurationType="4" - InheritedPropertySheets=".\common.vsprops;.\release.vsprops;.\arm.vsprops" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - </Configurations> - <References> - </References> - <Files> - <Filter - Name="src" - > - <File - RelativePath="..\..\src\accessors.cc" - > - </File> - <File - RelativePath="..\..\src\accessors.h" - > - </File> - <File - RelativePath="..\..\src\allocation.cc" - > - </File> - <File - RelativePath="..\..\src\allocation.h" - > - </File> - <File - RelativePath="..\..\src\api.cc" - > - </File> - <File - RelativePath="..\..\src\api.h" - > - </File> - <File - RelativePath="..\..\src\arguments.h" - > - </File> - <File - RelativePath="..\..\src\arm\assembler-arm-inl.h" - > - </File> - <File - RelativePath="..\..\src\arm\assembler-arm.cc" - > - </File> - <File - RelativePath="..\..\src\arm\assembler-arm.h" - > - </File> - <File - RelativePath="..\..\src\regexp-stack.h" - > - </File> - <File - RelativePath="..\..\src\regexp-macro-assembler-irregexp-inl.h" - > - </File> - <File - RelativePath="..\..\src\assembler.cc" - > - </File> - <File - RelativePath="..\..\src\assembler.h" - > - </File> - <File - RelativePath="..\..\src\ast-inl.h" - > - </File> - <File - RelativePath="..\..\src\ast.cc" - > - </File> - <File - RelativePath="..\..\src\ast.h" - > - </File> - <File - RelativePath="..\..\src\bootstrapper.cc" - > - </File> - <File - RelativePath="..\..\src\bootstrapper.h" - > - </File> - <File - RelativePath="..\..\src\arm\builtins-arm.cc" - > - </File> - <File - RelativePath="..\..\src\bignum.cc" - > - </File> - <File - RelativePath="..\..\src\bignum.h" - > - </File> - <File - RelativePath="..\..\src\bignum-dtoa.cc" - > - </File> - <File - RelativePath="..\..\src\bignum-dtoa.h" - > - </File> - <File - RelativePath="..\..\src\builtins.cc" - > - </File> - <File - RelativePath="..\..\src\builtins.h" - > - </File> - <File - RelativePath="..\..\src\bytecodes-irregexp.h" - > - </File> - <File - RelativePath="..\..\src\cached-powers.cc" - > - </File> - <File - RelativePath="..\..\src\cached-powers.h" - > - </File> - <File - RelativePath="..\..\src\char-predicates-inl.h" - > - </File> - <File - RelativePath="..\..\src\char-predicates.h" - > - </File> - <File - RelativePath="..\..\src\checks.cc" - > - </File> - <File - RelativePath="..\..\src\checks.h" - > - </File> - <File - RelativePath="..\..\src\circular-queue-inl.h" - > - </File> - <File - RelativePath="..\..\src\circular-queue.cc" - > - </File> - <File - RelativePath="..\..\src\circular-queue.h" - > - </File> - <File - RelativePath="..\..\src\code-stubs.cc" - > - </File> - <File - RelativePath="..\..\src\code-stubs.h" - > - </File> - <File - RelativePath="..\..\src\arm\code-stubs-arm.cc" - > - </File> - <File - RelativePath="..\..\src\arm\code-stubs-arm.h" - > - </File> - <File - RelativePath="..\..\src\code.h" - > - </File> - <File - RelativePath="..\..\src\arm\codegen-arm.cc" - > - </File> - <File - RelativePath="..\..\src\arm\codegen-arm.h" - > - </File> - <File - RelativePath="..\..\src\codegen-inl.h" - > - </File> - <File - RelativePath="..\..\src\codegen.cc" - > - </File> - <File - RelativePath="..\..\src\codegen.h" - > - </File> - <File - RelativePath="..\..\src\compilation-cache.cc" - > - </File> - <File - RelativePath="..\..\src\compilation-cache.h" - > - </File> - <File - RelativePath="..\..\src\compiler.cc" - > - </File> - <File - RelativePath="..\..\src\compiler.h" - > - </File> - <File - RelativePath="..\..\src\arm\constants-arm.cc" - > - </File> - <File - RelativePath="..\..\src\arm\constants-arm.h" - > - </File> - <File - RelativePath="..\..\src\contexts.cc" - > - </File> - <File - RelativePath="..\..\src\contexts.h" - > - </File> - <File - RelativePath="..\..\src\conversions-inl.h" - > - </File> - <File - RelativePath="..\..\src\conversions.cc" - > - </File> - <File - RelativePath="..\..\src\conversions.h" - > - </File> - <File - RelativePath="..\..\src\counters.cc" - > - </File> - <File - RelativePath="..\..\src\counters.h" - > - </File> - <File - RelativePath="..\..\src\arm\cpu-arm.cc" - > - </File> - <File - RelativePath="..\..\src\cpu.h" - > - </File> - <File - RelativePath="..\..\src\cpu-profiler.cc" - > - </File> - <File - RelativePath="..\..\src\cpu-profiler.h" - > - </File> - <File - RelativePath="..\..\src\cpu-profiler-inl.h" - > - </File> - <File - RelativePath="..\..\src\data-flow.cc" - > - </File> - <File - RelativePath="..\..\src\data-flow.h" - > - </File> - <File - RelativePath="..\..\src\dateparser.cc" - > - </File> - <File - RelativePath="..\..\src\dateparser.h" - > - </File> - <File - RelativePath="..\..\src\debug-agent.cc" - > - </File> - <File - RelativePath="..\..\src\debug-agent.h" - > - </File> - <File - RelativePath="..\..\src\arm\debug-arm.cc" - > - </File> - <File - RelativePath="..\..\src\debug.cc" - > - </File> - <File - RelativePath="..\..\src\debug.h" - > - </File> - <File - RelativePath="..\..\src\disassembler.cc" - > - </File> - <File - RelativePath="..\..\src\disassembler.h" - > - </File> - <File - RelativePath="..\..\src\diy-fp.cc" - > - </File> - <File - RelativePath="..\..\src\diy-fp.h" - > - </File> - <File - RelativePath="..\..\src\double.h" - > - </File> - <File - RelativePath="..\..\src\dtoa.cc" - > - </File> - <File - RelativePath="..\..\src\dtoa.h" - > - </File> - <File - RelativePath="..\..\src\execution.cc" - > - </File> - <File - RelativePath="..\..\src\execution.h" - > - </File> - <File - RelativePath="..\..\src\factory.cc" - > - </File> - <File - RelativePath="..\..\src\factory.h" - > - </File> - <File - RelativePath="..\..\src\fast-dtoa.cc" - > - </File> - <File - RelativePath="..\..\src\fast-dtoa.h" - > - </File> - <File - RelativePath="..\..\src\fixed-dtoa.cc" - > - </File> - <File - RelativePath="..\..\src\fixed-dtoa.h" - > - </File> - <File - RelativePath="..\..\src\flags.cc" - > - </File> - <File - RelativePath="..\..\src\flags.h" - > - </File> - <File - RelativePath="..\..\src\flow-graph.cc" - > - </File> - <File - RelativePath="..\..\src\flow-graph.h" - > - </File> - <File - RelativePath="..\..\src\frame-element.cc" - > - </File> - <File - RelativePath="..\..\src\frame-element.h" - > - </File> - <File - RelativePath="..\..\src\arm\frames-arm.cc" - > - </File> - <File - RelativePath="..\..\src\arm\frames-arm.h" - > - </File> - <File - RelativePath="..\..\src\frames-inl.h" - > - </File> - <File - RelativePath="..\..\src\frames.cc" - > - </File> - <File - RelativePath="..\..\src\frames.h" - > - </File> - <File - RelativePath="..\..\src\arm\full-codegen-arm.cc" - > - </File> - <File - RelativePath="..\..\src\full-codegen.cc" - > - </File> - <File - RelativePath="..\..\src\full-codegen.h" - > - </File> - <File - RelativePath="..\..\src\func-name-inferrer.cc" - > - </File> - <File - RelativePath="..\..\src\func-name-inferrer.h" - > - </File> - <File - RelativePath="..\..\src\global-handles.cc" - > - </File> - <File - RelativePath="..\..\src\global-handles.h" - > - </File> - <File - RelativePath="..\..\src\globals.h" - > - </File> - <File - RelativePath="..\..\src\handles-inl.h" - > - </File> - <File - RelativePath="..\..\src\handles.cc" - > - </File> - <File - RelativePath="..\..\src\handles.h" - > - </File> - <File - RelativePath="..\..\src\hashmap.cc" - > - </File> - <File - RelativePath="..\..\src\hashmap.h" - > - </File> - <File - RelativePath="..\..\src\heap-inl.h" - > - </File> - <File - RelativePath="..\..\src\heap.cc" - > - </File> - <File - RelativePath="..\..\src\heap.h" - > - </File> - <File - RelativePath="..\..\src\heap-profiler.cc" - > - </File> - <File - RelativePath="..\..\src\heap-profiler.h" - > - </File> - <File - RelativePath="..\..\src\arm\ic-arm.cc" - > - </File> - <File - RelativePath="..\..\src\ic-inl.h" - > - </File> - <File - RelativePath="..\..\src\ic.cc" - > - </File> - <File - RelativePath="..\..\src\ic.h" - > - </File> - <File - RelativePath="..\..\src\interceptors.h" - > - </File> - <File - RelativePath="..\..\src\interpreter-irregexp.cc" - > - </File> - <File - RelativePath="..\..\src\interpreter-irregexp.h" - > - </File> - <File - RelativePath="..\..\src\jump-target.h" - > - </File> - <File - RelativePath="..\..\src\jump-target-inl.h" - > - </File> - <File - RelativePath="..\..\src\jump-target-light-inl.h" - > - </File> - <File - RelativePath="..\..\src\jump-target-light.h" - > - </File> - <File - RelativePath="..\..\src\jump-target.cc" - > - </File> - <File - RelativePath="..\..\src\arm\jump-target-arm.cc" - > - </File> - <File - RelativePath="..\..\src\jump-target-light.cc" - > - </File> - <File - RelativePath="..\..\src\jsregexp.cc" - > - </File> - <File - RelativePath="..\..\src\jsregexp.h" - > - </File> - <File - RelativePath="..\..\src\list-inl.h" - > - </File> - <File - RelativePath="..\..\src\list.h" - > - </File> - <File - RelativePath="..\..\src\liveedit.cc" - > - </File> - <File - RelativePath="..\..\src\liveedit.h" - > - </File> - <File - RelativePath="..\..\src\log.cc" - > - </File> - <File - RelativePath="..\..\src\log-inl.h" - > - </File> - <File - RelativePath="..\..\src\log.h" - > - </File> - <File - RelativePath="..\..\src\log-utils.cc" - > - </File> - <File - RelativePath="..\..\src\log-utils.h" - > - </File> - <File - RelativePath="..\..\src\arm\macro-assembler-arm.cc" - > - </File> - <File - RelativePath="..\..\src\arm\macro-assembler-arm.h" - > - </File> - <File - RelativePath="..\..\src\macro-assembler.h" - > - </File> - <File - RelativePath="..\..\src\mark-compact.cc" - > - </File> - <File - RelativePath="..\..\src\mark-compact.h" - > - </File> - <File - RelativePath="..\..\src\memory.h" - > - </File> - <File - RelativePath="..\..\src\messages.cc" - > - </File> - <File - RelativePath="..\..\src\messages.h" - > - </File> - <File - RelativePath="..\..\src\natives.h" - > - </File> - <File - RelativePath="..\..\src\objects-debug.cc" - > - <FileConfiguration - Name="Release|Win32" - ExcludedFromBuild="true" - > - <Tool - Name="VCCLCompilerTool" - /> - </FileConfiguration> - </File> - <File - RelativePath="..\..\src\objects-inl.h" - > - </File> - <File - RelativePath="..\..\src\objects-visiting.cc" - > - </File> - <File - RelativePath="..\..\src\objects-visiting.h" - > - <File - RelativePath="..\..\src\objects.cc" - > - </File> - <File - RelativePath="..\..\src\objects.h" - > - </File> - <File - RelativePath="..\..\src\oprofile-agent.cc" - > - </File> - <File - RelativePath="..\..\src\oprofile-agent.h" - > - </File> - <File - RelativePath="..\..\src\parser.cc" - > - </File> - <File - RelativePath="..\..\src\parser.h" - > - </File> - <File - RelativePath="..\..\src\profile-generator.cc" - > - </File> - <File - RelativePath="..\..\src\profile-generator.h" - > - </File> - <File - RelativePath="..\..\src\profile-generator-inl.h" - > - </File> - <File - RelativePath="..\..\src\platform-win32.cc" - > - </File> - <File - RelativePath="..\..\src\platform.h" - > - </File> - <File - RelativePath="..\..\src\prettyprinter.cc" - > - <FileConfiguration - Name="Release|Win32" - ExcludedFromBuild="true" - > - <Tool - Name="VCCLCompilerTool" - /> - </FileConfiguration> - </File> - <File - RelativePath="..\..\src\prettyprinter.h" - > - </File> - <File - RelativePath="..\..\src\property.cc" - > - </File> - <File - RelativePath="..\..\src\property.h" - > - </File> - <File - RelativePath="..\..\src\arm\regexp-macro-assembler-arm.cc" - > - </File> - <File - RelativePath="..\..\src\arm\regexp-macro-assembler-arm.h" - > - </File> - <File - RelativePath="..\..\src\regexp-macro-assembler-irregexp.cc" - > - </File> - <File - RelativePath="..\..\src\regexp-macro-assembler-irregexp.h" - > - </File> - <File - RelativePath="..\..\src\regexp-macro-assembler.cc" - > - </File> - <File - RelativePath="..\..\src\regexp-macro-assembler.h" - > - </File> - <File - RelativePath="..\..\src\regexp-macro-assembler-tracer.cc" - > - </File> - <File - RelativePath="..\..\src\regexp-macro-assembler-tracer.h" - > - </File> - <File - RelativePath="..\..\src\regexp-stack.cc" - > - </File> - <File - RelativePath="..\..\src\register-allocator.h" - > - </File> - <File - RelativePath="..\..\src\register-allocator.cc" - > - </File> - <File - RelativePath="..\..\src\arm\register-allocator-arm.cc" - > - </File> - <File - RelativePath="..\..\src\rewriter.cc" - > - </File> - <File - RelativePath="..\..\src\rewriter.h" - > - </File> - <File - RelativePath="..\..\src\runtime.cc" - > - </File> - <File - RelativePath="..\..\src\runtime.h" - > - </File> - <File - RelativePath="..\..\src\scanner.cc" - > - </File> - <File - RelativePath="..\..\src\scanner.h" - > - </File> - <File - RelativePath="..\..\src\scopeinfo.cc" - > - </File> - <File - RelativePath="..\..\src\scopeinfo.h" - > - </File> - <File - RelativePath="..\..\src\scopes.cc" - > - </File> - <File - RelativePath="..\..\src\scopes.h" - > - </File> - <File - RelativePath="..\..\src\serialize.cc" - > - </File> - <File - RelativePath="..\..\src\serialize.h" - > - </File> - <File - RelativePath="..\..\src\shell.h" - > - </File> - <File - RelativePath="..\..\src\snapshot-common.cc" - > - </File> - <File - RelativePath="..\..\src\snapshot.h" - > - </File> - <File - RelativePath="..\..\src\arm\simulator-arm.cc" - > - </File> - <File - RelativePath="..\..\src\arm\simulator-arm.h" - > - </File> - <File - RelativePath="..\..\src\spaces-inl.h" - > - </File> - <File - RelativePath="..\..\src\spaces.cc" - > - </File> - <File - RelativePath="..\..\src\spaces.h" - > - </File> - <File - RelativePath="..\..\src\string-search.cc" - > - </File> - <File - RelativePath="..\..\src\string-search.h" - > - </File> - <File - RelativePath="..\..\src\string-stream.cc" - > - </File> - <File - RelativePath="..\..\src\string-stream.h" - > - </File> - <File - RelativePath="..\..\src\strtod.cc" - > - </File> - <File - RelativePath="..\..\src\strtod.h" - > - </File> - <File - RelativePath="..\..\src\arm\stub-cache-arm.cc" - > - </File> - <File - RelativePath="..\..\src\stub-cache.cc" - > - </File> - <File - RelativePath="..\..\src\stub-cache.h" - > - </File> - <File - RelativePath="..\..\src\token.cc" - > - </File> - <File - RelativePath="..\..\src\token.h" - > - </File> - <File - RelativePath="..\..\src\top.cc" - > - </File> - <File - RelativePath="..\..\src\top.h" - > - </File> - <File - RelativePath="..\..\src\type-info.cc" - > - </File> - <File - RelativePath="..\..\src\type-info.h" - > - </File> - <File - RelativePath="..\..\src\unbound-queue-inl.h" - > - </File> - <File - RelativePath="..\..\src\unbound-queue.h" - > - </File> - <File - RelativePath="..\..\src\unicode-inl.h" - > - </File> - <File - RelativePath="..\..\src\unicode.h" - > - </File> - <File - RelativePath="..\..\src\utils.cc" - > - </File> - <File - RelativePath="..\..\src\utils.h" - > - </File> - <File - RelativePath="..\..\src\v8-counters.cc" - > - </File> - <File - RelativePath="..\..\src\v8-counters.h" - > - </File> - <File - RelativePath="..\..\src\v8.cc" - > - </File> - <File - RelativePath="..\..\src\v8.h" - > - </File> - <File - RelativePath="..\..\src\v8threads.cc" - > - </File> - <File - RelativePath="..\..\src\v8threads.h" - > - </File> - <File - RelativePath="..\..\src\variables.cc" - > - </File> - <File - RelativePath="..\..\src\variables.h" - > - </File> - <File - RelativePath="..\..\src\version.cc" - > - </File> - <File - RelativePath="..\..\src\version.h" - > - </File> - <File - RelativePath="..\..\src\virtual-frame-inl.h" - > - </File> - <File - RelativePath="..\..\src\virtual-frame-light-inl.h" - > - </File> - <File - RelativePath="..\..\src\virtual-frame.h" - > - </File> - <File - RelativePath="..\..\src\arm\virtual-frame-arm-inl.h" - > - </File> - <File - RelativePath="..\..\src\arm\virtual-frame-arm.h" - > - </File> - <File - RelativePath="..\..\src\virtual-frame.cc" - > - </File> - <File - RelativePath="..\..\src\arm\virtual-frame-arm.cc" - > - </File> - <File - RelativePath="..\..\src\virtual-frame-light.cc" - > - </File> - <File - RelativePath="..\..\src\vm-state-inl.h" - > - </File> - <File - RelativePath="..\..\src\vm-state.h" - > - </File> - <File - RelativePath="..\..\src\zone-inl.h" - > - </File> - <File - RelativePath="..\..\src\zone.cc" - > - </File> - <File - RelativePath="..\..\src\zone.h" - > - </File> - <Filter - Name="third party" - > - <File - RelativePath="..\..\src\arm\disasm-arm.cc" - > - </File> - <File - RelativePath="..\..\src\disasm.h" - > - </File> - </Filter> - <Filter - Name="generated files" - > - <File - RelativePath="..\..\src\unicode.cc" - > - </File> - </Filter> - </Filter> - <Filter - Name="include" - > - <File - RelativePath="..\..\include\v8-debug.h" - > - </File> - <File - RelativePath="..\..\include\v8-profiler.h" - > - </File> - <File - RelativePath="..\..\include\v8-testing.h" - > - </File> - <File - RelativePath="..\..\include\v8.h" - > - </File> - </Filter> - </Files> - <Globals> - </Globals> + ProjectType="Visual C++" + Version="8.00" + Name="v8_base" + ProjectGUID="{EC8B7909-62AF-470D-A75D-E1D89C837142}" + RootNamespace="v8_base" + Keyword="Win32Proj" + > + <Platforms> + <Platform + Name="Win32" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|Win32" + ConfigurationType="4" + InheritedPropertySheets=".\common.vsprops;.\debug.vsprops;.\arm.vsprops" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLibrarianTool" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Release|Win32" + ConfigurationType="4" + InheritedPropertySheets=".\common.vsprops;.\release.vsprops;.\arm.vsprops" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLibrarianTool" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <Filter + Name="src" + > + <File + RelativePath="..\..\src\accessors.cc" + > + </File> + <File + RelativePath="..\..\src\accessors.h" + > + </File> + <File + RelativePath="..\..\src\allocation.cc" + > + </File> + <File + RelativePath="..\..\src\allocation.h" + > + </File> + <File + RelativePath="..\..\src\api.cc" + > + </File> + <File + RelativePath="..\..\src\api.h" + > + </File> + <File + RelativePath="..\..\src\atomicops_internals_x86_msvc.h" + > + </File> + <File + RelativePath="..\..\src\arguments.h" + > + </File> + <File + RelativePath="..\..\src\arm\assembler-arm-inl.h" + > + </File> + <File + RelativePath="..\..\src\arm\assembler-arm.cc" + > + </File> + <File + RelativePath="..\..\src\arm\assembler-arm.h" + > + </File> + <File + RelativePath="..\..\src\regexp-stack.h" + > + </File> + <File + RelativePath="..\..\src\regexp-macro-assembler-irregexp-inl.h" + > + </File> + <File + RelativePath="..\..\src\assembler.cc" + > + </File> + <File + RelativePath="..\..\src\assembler.h" + > + </File> + <File + RelativePath="..\..\src\ast-inl.h" + > + </File> + <File + RelativePath="..\..\src\ast.cc" + > + </File> + <File + RelativePath="..\..\src\ast.h" + > + </File> + <File + RelativePath="..\..\src\bootstrapper.cc" + > + </File> + <File + RelativePath="..\..\src\bootstrapper.h" + > + </File> + <File + RelativePath="..\..\src\arm\builtins-arm.cc" + > + </File> + <File + RelativePath="..\..\src\bignum.cc" + > + </File> + <File + RelativePath="..\..\src\bignum.h" + > + </File> + <File + RelativePath="..\..\src\bignum-dtoa.cc" + > + </File> + <File + RelativePath="..\..\src\bignum-dtoa.h" + > + </File> + <File + RelativePath="..\..\src\builtins.cc" + > + </File> + <File + RelativePath="..\..\src\builtins.h" + > + </File> + <File + RelativePath="..\..\src\bytecodes-irregexp.h" + > + </File> + <File + RelativePath="..\..\src\cached-powers.cc" + > + </File> + <File + RelativePath="..\..\src\cached-powers.h" + > + </File> + <File + RelativePath="..\..\src\char-predicates-inl.h" + > + </File> + <File + RelativePath="..\..\src\char-predicates.h" + > + </File> + <File + RelativePath="..\..\src\checks.cc" + > + </File> + <File + RelativePath="..\..\src\checks.h" + > + </File> + <File + RelativePath="..\..\src\circular-queue-inl.h" + > + </File> + <File + RelativePath="..\..\src\circular-queue.cc" + > + </File> + <File + RelativePath="..\..\src\circular-queue.h" + > + </File> + <File + RelativePath="..\..\src\code-stubs.cc" + > + </File> + <File + RelativePath="..\..\src\code-stubs.h" + > + </File> + <File + RelativePath="..\..\src\arm\code-stubs-arm.cc" + > + </File> + <File + RelativePath="..\..\src\arm\code-stubs-arm.h" + > + </File> + <File + RelativePath="..\..\src\code.h" + > + </File> + <File + RelativePath="..\..\src\arm\codegen-arm.cc" + > + </File> + <File + RelativePath="..\..\src\arm\codegen-arm.h" + > + </File> + <File + RelativePath="..\..\src\codegen-inl.h" + > + </File> + <File + RelativePath="..\..\src\codegen.cc" + > + </File> + <File + RelativePath="..\..\src\codegen.h" + > + </File> + <File + RelativePath="..\..\src\compilation-cache.cc" + > + </File> + <File + RelativePath="..\..\src\compilation-cache.h" + > + </File> + <File + RelativePath="..\..\src\compiler.cc" + > + </File> + <File + RelativePath="..\..\src\compiler.h" + > + </File> + <File + RelativePath="..\..\src\arm\constants-arm.cc" + > + </File> + <File + RelativePath="..\..\src\arm\constants-arm.h" + > + </File> + <File + RelativePath="..\..\src\contexts.cc" + > + </File> + <File + RelativePath="..\..\src\contexts.h" + > + </File> + <File + RelativePath="..\..\src\conversions-inl.h" + > + </File> + <File + RelativePath="..\..\src\conversions.cc" + > + </File> + <File + RelativePath="..\..\src\conversions.h" + > + </File> + <File + RelativePath="..\..\src\counters.cc" + > + </File> + <File + RelativePath="..\..\src\counters.h" + > + </File> + <File + RelativePath="..\..\src\arm\cpu-arm.cc" + > + </File> + <File + RelativePath="..\..\src\cpu.h" + > + </File> + <File + RelativePath="..\..\src\cpu-profiler.cc" + > + </File> + <File + RelativePath="..\..\src\cpu-profiler.h" + > + </File> + <File + RelativePath="..\..\src\cpu-profiler-inl.h" + > + </File> + <File + RelativePath="..\..\src\data-flow.cc" + > + </File> + <File + RelativePath="..\..\src\data-flow.h" + > + </File> + <File + RelativePath="..\..\src\dateparser.cc" + > + </File> + <File + RelativePath="..\..\src\dateparser.h" + > + </File> + <File + RelativePath="..\..\src\debug-agent.cc" + > + </File> + <File + RelativePath="..\..\src\debug-agent.h" + > + </File> + <File + RelativePath="..\..\src\arm\debug-arm.cc" + > + </File> + <File + RelativePath="..\..\src\debug.cc" + > + </File> + <File + RelativePath="..\..\src\debug.h" + > + </File> + <File + RelativePath="..\..\src\arm\deoptimizer-arm.cc" + > + </File> + <File + RelativePath="..\..\src\deoptimizer.cc" + > + </File> + <File + RelativePath="..\..\src\deoptimizer.h" + > + </File> + <File + RelativePath="..\..\src\disassembler.cc" + > + </File> + <File + RelativePath="..\..\src\disassembler.h" + > + </File> + <File + RelativePath="..\..\src\diy-fp.cc" + > + </File> + <File + RelativePath="..\..\src\diy-fp.h" + > + </File> + <File + RelativePath="..\..\src\double.h" + > + </File> + <File + RelativePath="..\..\src\dtoa.cc" + > + </File> + <File + RelativePath="..\..\src\dtoa.h" + > + </File> + <File + RelativePath="..\..\src\execution.cc" + > + </File> + <File + RelativePath="..\..\src\execution.h" + > + </File> + <File + RelativePath="..\..\src\factory.cc" + > + </File> + <File + RelativePath="..\..\src\factory.h" + > + </File> + <File + RelativePath="..\..\src\fast-dtoa.cc" + > + </File> + <File + RelativePath="..\..\src\fast-dtoa.h" + > + </File> + <File + RelativePath="..\..\src\fixed-dtoa.cc" + > + </File> + <File + RelativePath="..\..\src\fixed-dtoa.h" + > + </File> + <File + RelativePath="..\..\src\flags.cc" + > + </File> + <File + RelativePath="..\..\src\flags.h" + > + </File> + <File + RelativePath="..\..\src\flow-graph.cc" + > + </File> + <File + RelativePath="..\..\src\flow-graph.h" + > + </File> + <File + RelativePath="..\..\src\frame-element.cc" + > + </File> + <File + RelativePath="..\..\src\frame-element.h" + > + </File> + <File + RelativePath="..\..\src\arm\frames-arm.cc" + > + </File> + <File + RelativePath="..\..\src\arm\frames-arm.h" + > + </File> + <File + RelativePath="..\..\src\frames-inl.h" + > + </File> + <File + RelativePath="..\..\src\frames.cc" + > + </File> + <File + RelativePath="..\..\src\frames.h" + > + </File> + <File + RelativePath="..\..\src\arm\full-codegen-arm.cc" + > + </File> + <File + RelativePath="..\..\src\full-codegen.cc" + > + </File> + <File + RelativePath="..\..\src\full-codegen.h" + > + </File> + <File + RelativePath="..\..\src\func-name-inferrer.cc" + > + </File> + <File + RelativePath="..\..\src\func-name-inferrer.h" + > + </File> + <File + RelativePath="..\..\src\global-handles.cc" + > + </File> + <File + RelativePath="..\..\src\global-handles.h" + > + </File> + <File + RelativePath="..\..\src\globals.h" + > + </File> + <File + RelativePath="..\..\src\handles-inl.h" + > + </File> + <File + RelativePath="..\..\src\handles.cc" + > + </File> + <File + RelativePath="..\..\src\handles.h" + > + </File> + <File + RelativePath="..\..\src\hashmap.cc" + > + </File> + <File + RelativePath="..\..\src\hashmap.h" + > + </File> + <File + RelativePath="..\..\src\heap-inl.h" + > + </File> + <File + RelativePath="..\..\src\heap.cc" + > + </File> + <File + RelativePath="..\..\src\heap.h" + > + </File> + <File + RelativePath="..\..\src\hydrogen.cc" + > + </File> + <File + RelativePath="..\..\src\hydrogen.h" + > + </File> + <File + RelativePath="..\..\src\heap-profiler.cc" + > + </File> + <File + RelativePath="..\..\src\heap-profiler.h" + > + </File> + <File + RelativePath="..\..\src\arm\ic-arm.cc" + > + </File> + <File + RelativePath="..\..\src\ic-inl.h" + > + </File> + <File + RelativePath="..\..\src\ic.cc" + > + </File> + <File + RelativePath="..\..\src\ic.h" + > + </File> + <File + RelativePath="..\..\src\interceptors.h" + > + </File> + <File + RelativePath="..\..\src\interpreter-irregexp.cc" + > + </File> + <File + RelativePath="..\..\src\interpreter-irregexp.h" + > + </File> + <File + RelativePath="..\..\src\jump-target.h" + > + </File> + <File + RelativePath="..\..\src\jump-target-inl.h" + > + </File> + <File + RelativePath="..\..\src\jump-target-light-inl.h" + > + </File> + <File + RelativePath="..\..\src\jump-target-light.h" + > + </File> + <File + RelativePath="..\..\src\jump-target.cc" + > + </File> + <File + RelativePath="..\..\src\arm\jump-target-arm.cc" + > + </File> + <File + RelativePath="..\..\src\jump-target-light.cc" + > + </File> + <File + RelativePath="..\..\src\jsregexp.cc" + > + </File> + <File + RelativePath="..\..\src\jsregexp.h" + > + </File> + <File + RelativePath="..\..\src\list-inl.h" + > + </File> + <File + RelativePath="..\..\src\list.h" + > + </File> + <File + RelativePath="..\..\src\lithium-allocator.cc" + > + </File> + <File + RelativePath="..\..\src\lithium-allocator.h" + > + </File> + <File + RelativePath="..\..\src\arm\lithium-arm.cc" + > + </File> + <File + RelativePath="..\..\src\arm\lithium-arm.h" + > + </File> + <File + RelativePath="..\..\src\arm\lithium-codegen-arm.cc" + > + </File> + <File + RelativePath="..\..\src\arm\lithium-codegen-arm.h" + > + </File> + <File + RelativePath="..\..\src\liveedit.cc" + > + </File> + <File + RelativePath="..\..\src\liveedit.h" + > + </File> + <File + RelativePath="..\..\src\log.cc" + > + </File> + <File + RelativePath="..\..\src\log-inl.h" + > + </File> + <File + RelativePath="..\..\src\log.h" + > + </File> + <File + RelativePath="..\..\src\log-utils.cc" + > + </File> + <File + RelativePath="..\..\src\log-utils.h" + > + </File> + <File + RelativePath="..\..\src\arm\macro-assembler-arm.cc" + > + </File> + <File + RelativePath="..\..\src\arm\macro-assembler-arm.h" + > + </File> + <File + RelativePath="..\..\src\macro-assembler.h" + > + </File> + <File + RelativePath="..\..\src\mark-compact.cc" + > + </File> + <File + RelativePath="..\..\src\mark-compact.h" + > + </File> + <File + RelativePath="..\..\src\memory.h" + > + </File> + <File + RelativePath="..\..\src\messages.cc" + > + </File> + <File + RelativePath="..\..\src\messages.h" + > + </File> + <File + RelativePath="..\..\src\natives.h" + > + </File> + <File + RelativePath="..\..\src\objects-debug.cc" + > + <FileConfiguration + Name="Release|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCLCompilerTool" + /> + </FileConfiguration> + </File> + <File + RelativePath="..\..\src\objects-inl.h" + > + </File> + <File + RelativePath="..\..\src\objects-visiting.cc" + > + </File> + <File + RelativePath="..\..\src\objects-visiting.h" + > + <File + RelativePath="..\..\src\objects.cc" + > + </File> + <File + RelativePath="..\..\src\objects.h" + > + </File> + <File + RelativePath="..\..\src\oprofile-agent.cc" + > + </File> + <File + RelativePath="..\..\src\oprofile-agent.h" + > + </File> + <File + RelativePath="..\..\src\parser.cc" + > + </File> + <File + RelativePath="..\..\src\parser.h" + > + </File> + <File + RelativePath="..\..\src\profile-generator.cc" + > + </File> + <File + RelativePath="..\..\src\profile-generator.h" + > + </File> + <File + RelativePath="..\..\src\profile-generator-inl.h" + > + </File> + <File + RelativePath="..\..\src\platform-win32.cc" + > + </File> + <File + RelativePath="..\..\src\platform.h" + > + </File> + <File + RelativePath="..\..\src\prettyprinter.cc" + > + <FileConfiguration + Name="Release|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCLCompilerTool" + /> + </FileConfiguration> + </File> + <File + RelativePath="..\..\src\prettyprinter.h" + > + </File> + <File + RelativePath="..\..\src\property.cc" + > + </File> + <File + RelativePath="..\..\src\property.h" + > + </File> + <File + RelativePath="..\..\src\arm\regexp-macro-assembler-arm.cc" + > + </File> + <File + RelativePath="..\..\src\arm\regexp-macro-assembler-arm.h" + > + </File> + <File + RelativePath="..\..\src\regexp-macro-assembler-irregexp.cc" + > + </File> + <File + RelativePath="..\..\src\regexp-macro-assembler-irregexp.h" + > + </File> + <File + RelativePath="..\..\src\regexp-macro-assembler.cc" + > + </File> + <File + RelativePath="..\..\src\regexp-macro-assembler.h" + > + </File> + <File + RelativePath="..\..\src\regexp-macro-assembler-tracer.cc" + > + </File> + <File + RelativePath="..\..\src\regexp-macro-assembler-tracer.h" + > + </File> + <File + RelativePath="..\..\src\regexp-stack.cc" + > + </File> + <File + RelativePath="..\..\src\register-allocator.h" + > + </File> + <File + RelativePath="..\..\src\register-allocator.cc" + > + </File> + <File + RelativePath="..\..\src\arm\register-allocator-arm.cc" + > + </File> + <File + RelativePath="..\..\src\rewriter.cc" + > + </File> + <File + RelativePath="..\..\src\rewriter.h" + > + </File> + <File + RelativePath="..\..\src\runtime.cc" + > + </File> + <File + RelativePath="..\..\src\runtime.h" + > + </File> + <File + RelativePath="..\..\src\runtime-profiler.cc" + > + </File> + <File + RelativePath="..\..\src\runtime-profiler.h" + > + </File> + <File + RelativePath="..\..\src\safepoint-table.cc" + > + </File> + <File + RelativePath="..\..\src\safepoint-table.h" + > + </File> + <File + RelativePath="..\..\src\scanner.cc" + > + </File> + <File + RelativePath="..\..\src\scanner.h" + > + </File> + <File + RelativePath="..\..\src\scopeinfo.cc" + > + </File> + <File + RelativePath="..\..\src\scopeinfo.h" + > + </File> + <File + RelativePath="..\..\src\scopes.cc" + > + </File> + <File + RelativePath="..\..\src\scopes.h" + > + </File> + <File + RelativePath="..\..\src\serialize.cc" + > + </File> + <File + RelativePath="..\..\src\serialize.h" + > + </File> + <File + RelativePath="..\..\src\shell.h" + > + </File> + <File + RelativePath="..\..\src\snapshot-common.cc" + > + </File> + <File + RelativePath="..\..\src\snapshot.h" + > + </File> + <File + RelativePath="..\..\src\arm\simulator-arm.cc" + > + </File> + <File + RelativePath="..\..\src\arm\simulator-arm.h" + > + </File> + <File + RelativePath="..\..\src\spaces-inl.h" + > + </File> + <File + RelativePath="..\..\src\spaces.cc" + > + </File> + <File + RelativePath="..\..\src\spaces.h" + > + </File> + <File + RelativePath="..\..\src\string-search.cc" + > + </File> + <File + RelativePath="..\..\src\string-search.h" + > + </File> + <File + RelativePath="..\..\src\string-stream.cc" + > + </File> + <File + RelativePath="..\..\src\string-stream.h" + > + </File> + <File + RelativePath="..\..\src\strtod.cc" + > + </File> + <File + RelativePath="..\..\src\strtod.h" + > + </File> + <File + RelativePath="..\..\src\arm\stub-cache-arm.cc" + > + </File> + <File + RelativePath="..\..\src\stub-cache.cc" + > + </File> + <File + RelativePath="..\..\src\stub-cache.h" + > + </File> + <File + RelativePath="..\..\src\token.cc" + > + </File> + <File + RelativePath="..\..\src\token.h" + > + </File> + <File + RelativePath="..\..\src\top.cc" + > + </File> + <File + RelativePath="..\..\src\top.h" + > + </File> + <File + RelativePath="..\..\src\type-info.cc" + > + </File> + <File + RelativePath="..\..\src\type-info.h" + > + </File> + <File + RelativePath="..\..\src\unbound-queue-inl.h" + > + </File> + <File + RelativePath="..\..\src\unbound-queue.h" + > + </File> + <File + RelativePath="..\..\src\unicode-inl.h" + > + </File> + <File + RelativePath="..\..\src\unicode.h" + > + </File> + <File + RelativePath="..\..\src\utils.cc" + > + </File> + <File + RelativePath="..\..\src\utils.h" + > + </File> + <File + RelativePath="..\..\src\v8-counters.cc" + > + </File> + <File + RelativePath="..\..\src\v8-counters.h" + > + </File> + <File + RelativePath="..\..\src\v8.cc" + > + </File> + <File + RelativePath="..\..\src\v8.h" + > + </File> + <File + RelativePath="..\..\src\v8threads.cc" + > + </File> + <File + RelativePath="..\..\src\v8threads.h" + > + </File> + <File + RelativePath="..\..\src\variables.cc" + > + </File> + <File + RelativePath="..\..\src\variables.h" + > + </File> + <File + RelativePath="..\..\src\version.cc" + > + </File> + <File + RelativePath="..\..\src\version.h" + > + </File> + <File + RelativePath="..\..\src\virtual-frame-inl.h" + > + </File> + <File + RelativePath="..\..\src\virtual-frame-light-inl.h" + > + </File> + <File + RelativePath="..\..\src\virtual-frame.h" + > + </File> + <File + RelativePath="..\..\src\arm\virtual-frame-arm-inl.h" + > + </File> + <File + RelativePath="..\..\src\arm\virtual-frame-arm.h" + > + </File> + <File + RelativePath="..\..\src\virtual-frame.cc" + > + </File> + <File + RelativePath="..\..\src\arm\virtual-frame-arm.cc" + > + </File> + <File + RelativePath="..\..\src\virtual-frame-light.cc" + > + </File> + <File + RelativePath="..\..\src\vm-state-inl.h" + > + </File> + <File + RelativePath="..\..\src\vm-state.h" + > + </File> + <File + RelativePath="..\..\src\zone-inl.h" + > + </File> + <File + RelativePath="..\..\src\zone.cc" + > + </File> + <File + RelativePath="..\..\src\zone.h" + > + </File> + <Filter + Name="third party" + > + <File + RelativePath="..\..\src\arm\disasm-arm.cc" + > + </File> + <File + RelativePath="..\..\src\disasm.h" + > + </File> + </Filter> + <Filter + Name="generated files" + > + <File + RelativePath="..\..\src\unicode.cc" + > + </File> + </Filter> + </Filter> + <Filter + Name="include" + > + <File + RelativePath="..\..\include\v8-debug.h" + > + </File> + <File + RelativePath="..\..\include\v8-profiler.h" + > + </File> + <File + RelativePath="..\..\include\v8-testing.h" + > + </File> + <File + RelativePath="..\..\include\v8.h" + > + </File> + </Filter> + </Files> + <Globals> + </Globals> </VisualStudioProject> diff --git a/deps/v8/tools/visual_studio/v8_base_x64.vcproj b/deps/v8/tools/visual_studio/v8_base_x64.vcproj index 5abe923b552..28f299edb5e 100644 --- a/deps/v8/tools/visual_studio/v8_base_x64.vcproj +++ b/deps/v8/tools/visual_studio/v8_base_x64.vcproj @@ -1,1152 +1,1200 @@ <?xml version="1.0" encoding="Windows-1252"?> <VisualStudioProject - ProjectType="Visual C++" - Version="8.00" - Name="v8_base" - ProjectGUID="{EC8B7909-62AF-470D-A75D-E1D89C837142}" - RootNamespace="v8_base" - Keyword="Win32Proj" - > - <Platforms> - <Platform - Name="x64" - /> - </Platforms> - <ToolFiles> - </ToolFiles> - <Configurations> - <Configuration - Name="Debug|x64" - ConfigurationType="4" - InheritedPropertySheets=".\common.vsprops;.\x64.vsprops;.\debug.vsprops" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - <Configuration - Name="Release|x64" - ConfigurationType="4" - InheritedPropertySheets=".\common.vsprops;.\x64.vsprops;.\release.vsprops" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - </Configurations> - <References> - </References> - <Files> - <Filter - Name="src" - > - <File - RelativePath="..\..\src\accessors.cc" - > - </File> - <File - RelativePath="..\..\src\accessors.h" - > - </File> - <File - RelativePath="..\..\src\allocation.cc" - > - </File> - <File - RelativePath="..\..\src\allocation.h" - > - </File> - <File - RelativePath="..\..\src\api.cc" - > - </File> - <File - RelativePath="..\..\src\api.h" - > - </File> - <File - RelativePath="..\..\src\arguments.h" - > - </File> - <File - RelativePath="..\..\src\x64\assembler-x64-inl.h" - > - </File> - <File - RelativePath="..\..\src\x64\assembler-x64.cc" - > - </File> - <File - RelativePath="..\..\src\x64\assembler-x64.h" - > - </File> - <File - RelativePath="..\..\src\regexp-macro-assembler-irregexp-inl.h" - > - </File> - <File - RelativePath="..\..\src\regexp-stack.h" - > - </File> - <File - RelativePath="..\..\src\assembler.cc" - > - </File> - <File - RelativePath="..\..\src\assembler.h" - > - </File> - <File - RelativePath="..\..\src\ast-inl.h" - > - </File> - <File - RelativePath="..\..\src\ast.cc" - > - </File> - <File - RelativePath="..\..\src\ast.h" - > - </File> - <File - RelativePath="..\..\src\bignum.cc" - > - </File> - <File - RelativePath="..\..\src\bignum.h" - > - </File> - <File - RelativePath="..\..\src\bignum-dtoa.cc" - > - </File> - <File - RelativePath="..\..\src\bignum-dtoa.h" - > - </File> - <File - RelativePath="..\..\src\bootstrapper.cc" - > - </File> - <File - RelativePath="..\..\src\bootstrapper.h" - > - </File> - <File - RelativePath="..\..\src\x64\builtins-x64.cc" - > - </File> - <File - RelativePath="..\..\src\builtins.cc" - > - </File> - <File - RelativePath="..\..\src\builtins.h" - > - </File> - <File - RelativePath="..\..\src\bytecodes-irregexp.h" - > - </File> - <File - RelativePath="..\..\src\cached-powers.cc" - > - </File> - <File - RelativePath="..\..\src\cached-powers.h" - > - </File> - <File - RelativePath="..\..\src\char-predicates-inl.h" - > - </File> - <File - RelativePath="..\..\src\char-predicates.h" - > - </File> - <File - RelativePath="..\..\src\checks.cc" - > - </File> - <File - RelativePath="..\..\src\checks.h" - > - </File> - <File - RelativePath="..\..\src\circular-queue-inl.h" - > - </File> - <File - RelativePath="..\..\src\circular-queue.cc" - > - </File> - <File - RelativePath="..\..\src\circular-queue.h" - > - </File> - <File - RelativePath="..\..\src\code-stubs.cc" - > - </File> - <File - RelativePath="..\..\src\code-stubs.h" - > - </File> - <File - RelativePath="..\..\src\x64\code-stubs-x64.cc" - > - </File> - <File - RelativePath="..\..\src\x64\code-stubs-x64.h" - > - </File> - <File - RelativePath="..\..\src\code.h" - > - </File> - <File - RelativePath="..\..\src\x64\codegen-x64.cc" - > - </File> - <File - RelativePath="..\..\src\x64\codegen-x64.h" - > - </File> - <File - RelativePath="..\..\src\codegen-inl.h" - > - </File> - <File - RelativePath="..\..\src\codegen.cc" - > - </File> - <File - RelativePath="..\..\src\codegen.h" - > - </File> - <File - RelativePath="..\..\src\compilation-cache.cc" - > - </File> - <File - RelativePath="..\..\src\compilation-cache.h" - > - </File> - <File - RelativePath="..\..\src\compiler.cc" - > - </File> - <File - RelativePath="..\..\src\compiler.h" - > - </File> - <File - RelativePath="..\..\src\contexts.cc" - > - </File> - <File - RelativePath="..\..\src\contexts.h" - > - </File> - <File - RelativePath="..\..\src\conversions-inl.h" - > - </File> - <File - RelativePath="..\..\src\conversions.cc" - > - </File> - <File - RelativePath="..\..\src\conversions.h" - > - </File> - <File - RelativePath="..\..\src\counters.cc" - > - </File> - <File - RelativePath="..\..\src\counters.h" - > - </File> - <File - RelativePath="..\..\src\x64\cpu-x64.cc" - > - </File> - <File - RelativePath="..\..\src\cpu.h" - > - </File> - <File - RelativePath="..\..\src\cpu-profiler.cc" - > - </File> - <File - RelativePath="..\..\src\cpu-profiler.h" - > - </File> - <File - RelativePath="..\..\src\cpu-profiler-inl.h" - > - </File> - <File - RelativePath="..\..\src\data-flow.cc" - > - </File> - <File - RelativePath="..\..\src\data-flow.h" - > - </File> - <File - RelativePath="..\..\src\dateparser.cc" - > - </File> - <File - RelativePath="..\..\src\dateparser.h" - > - </File> - <File - RelativePath="..\..\src\debug-agent.cc" - > - </File> - <File - RelativePath="..\..\src\debug-agent.h" - > - </File> - <File - RelativePath="..\..\src\x64\debug-x64.cc" - > - </File> - <File - RelativePath="..\..\src\debug.cc" - > - </File> - <File - RelativePath="..\..\src\debug.h" - > - </File> - <File - RelativePath="..\..\src\disassembler.cc" - > - </File> - <File - RelativePath="..\..\src\disassembler.h" - > - </File> - <File - RelativePath="..\..\src\diy-fp.cc" - > - </File> - <File - RelativePath="..\..\src\diy-fp.h" - > - </File> - <File - RelativePath="..\..\src\double.h" - > - </File> - <File - RelativePath="..\..\src\dtoa.cc" - > - </File> - <File - RelativePath="..\..\src\dtoa.h" - > - </File> - <File - RelativePath="..\..\src\execution.cc" - > - </File> - <File - RelativePath="..\..\src\execution.h" - > - </File> - <File - RelativePath="..\..\src\factory.cc" - > - </File> - <File - RelativePath="..\..\src\factory.h" - > - </File> - <File - RelativePath="..\..\src\fast-dtoa.cc" - > - </File> - <File - RelativePath="..\..\src\fast-dtoa.h" - > - </File> - <File - RelativePath="..\..\src\fixed-dtoa.cc" - > - </File> - <File - RelativePath="..\..\src\fixed-dtoa.h" - > - </File> - <File - RelativePath="..\..\src\flags.cc" - > - </File> - <File - RelativePath="..\..\src\flags.h" - > - </File> - <File - RelativePath="..\..\src\flow-graph.cc" - > - </File> - <File - RelativePath="..\..\src\flow-graph.h" - > - </File> - <File - RelativePath="..\..\src\frame-element.cc" - > - </File> - <File - RelativePath="..\..\src\frame-element.h" - > - </File> - <File - RelativePath="..\..\src\x64\frames-x64.cc" - > - </File> - <File - RelativePath="..\..\src\x64\frames-x64.h" - > - </File> - <File - RelativePath="..\..\src\frames-inl.h" - > - </File> - <File - RelativePath="..\..\src\frames.cc" - > - </File> - <File - RelativePath="..\..\src\frames.h" - > - </File> - <File - RelativePath="..\..\src\x64\full-codegen-x64.cc" - > - </File> - <File - RelativePath="..\..\src\full-codegen.cc" - > - </File> - <File - RelativePath="..\..\src\full-codegen.h" - > - </File> - <File + ProjectType="Visual C++" + Version="8.00" + Name="v8_base" + ProjectGUID="{EC8B7909-62AF-470D-A75D-E1D89C837142}" + RootNamespace="v8_base" + Keyword="Win32Proj" + > + <Platforms> + <Platform + Name="x64" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|x64" + ConfigurationType="4" + InheritedPropertySheets=".\common.vsprops;.\x64.vsprops;.\debug.vsprops" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLibrarianTool" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Release|x64" + ConfigurationType="4" + InheritedPropertySheets=".\common.vsprops;.\x64.vsprops;.\release.vsprops" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLibrarianTool" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <Filter + Name="src" + > + <File + RelativePath="..\..\src\accessors.cc" + > + </File> + <File + RelativePath="..\..\src\accessors.h" + > + </File> + <File + RelativePath="..\..\src\allocation.cc" + > + </File> + <File + RelativePath="..\..\src\allocation.h" + > + </File> + <File + RelativePath="..\..\src\api.cc" + > + </File> + <File + RelativePath="..\..\src\api.h" + > + </File> + <File + RelativePath="..\..\src\arguments.h" + > + </File> + <File + RelativePath="..\..\src\x64\assembler-x64-inl.h" + > + </File> + <File + RelativePath="..\..\src\x64\assembler-x64.cc" + > + </File> + <File + RelativePath="..\..\src\x64\assembler-x64.h" + > + </File> + <File + RelativePath="..\..\src\regexp-macro-assembler-irregexp-inl.h" + > + </File> + <File + RelativePath="..\..\src\regexp-stack.h" + > + </File> + <File + RelativePath="..\..\src\assembler.cc" + > + </File> + <File + RelativePath="..\..\src\assembler.h" + > + </File> + <File + RelativePath="..\..\src\ast-inl.h" + > + </File> + <File + RelativePath="..\..\src\ast.cc" + > + </File> + <File + RelativePath="..\..\src\ast.h" + > + </File> + <File + RelativePath="..\..\src\atomicops_internals_x86_msvc.h" + > + </File> + <File + RelativePath="..\..\src\bignum.cc" + > + </File> + <File + RelativePath="..\..\src\bignum.h" + > + </File> + <File + RelativePath="..\..\src\bignum-dtoa.cc" + > + </File> + <File + RelativePath="..\..\src\bignum-dtoa.h" + > + </File> + <File + RelativePath="..\..\src\bootstrapper.cc" + > + </File> + <File + RelativePath="..\..\src\bootstrapper.h" + > + </File> + <File + RelativePath="..\..\src\x64\builtins-x64.cc" + > + </File> + <File + RelativePath="..\..\src\builtins.cc" + > + </File> + <File + RelativePath="..\..\src\builtins.h" + > + </File> + <File + RelativePath="..\..\src\bytecodes-irregexp.h" + > + </File> + <File + RelativePath="..\..\src\cached-powers.cc" + > + </File> + <File + RelativePath="..\..\src\cached-powers.h" + > + </File> + <File + RelativePath="..\..\src\char-predicates-inl.h" + > + </File> + <File + RelativePath="..\..\src\char-predicates.h" + > + </File> + <File + RelativePath="..\..\src\checks.cc" + > + </File> + <File + RelativePath="..\..\src\checks.h" + > + </File> + <File + RelativePath="..\..\src\circular-queue-inl.h" + > + </File> + <File + RelativePath="..\..\src\circular-queue.cc" + > + </File> + <File + RelativePath="..\..\src\circular-queue.h" + > + </File> + <File + RelativePath="..\..\src\code-stubs.cc" + > + </File> + <File + RelativePath="..\..\src\code-stubs.h" + > + </File> + <File + RelativePath="..\..\src\x64\code-stubs-x64.cc" + > + </File> + <File + RelativePath="..\..\src\x64\code-stubs-x64.h" + > + </File> + <File + RelativePath="..\..\src\code.h" + > + </File> + <File + RelativePath="..\..\src\x64\codegen-x64.cc" + > + </File> + <File + RelativePath="..\..\src\x64\codegen-x64.h" + > + </File> + <File + RelativePath="..\..\src\codegen-inl.h" + > + </File> + <File + RelativePath="..\..\src\codegen.cc" + > + </File> + <File + RelativePath="..\..\src\codegen.h" + > + </File> + <File + RelativePath="..\..\src\compilation-cache.cc" + > + </File> + <File + RelativePath="..\..\src\compilation-cache.h" + > + </File> + <File + RelativePath="..\..\src\compiler.cc" + > + </File> + <File + RelativePath="..\..\src\compiler.h" + > + </File> + <File + RelativePath="..\..\src\contexts.cc" + > + </File> + <File + RelativePath="..\..\src\contexts.h" + > + </File> + <File + RelativePath="..\..\src\conversions-inl.h" + > + </File> + <File + RelativePath="..\..\src\conversions.cc" + > + </File> + <File + RelativePath="..\..\src\conversions.h" + > + </File> + <File + RelativePath="..\..\src\counters.cc" + > + </File> + <File + RelativePath="..\..\src\counters.h" + > + </File> + <File + RelativePath="..\..\src\x64\cpu-x64.cc" + > + </File> + <File + RelativePath="..\..\src\cpu.h" + > + </File> + <File + RelativePath="..\..\src\cpu-profiler.cc" + > + </File> + <File + RelativePath="..\..\src\cpu-profiler.h" + > + </File> + <File + RelativePath="..\..\src\cpu-profiler-inl.h" + > + </File> + <File + RelativePath="..\..\src\data-flow.cc" + > + </File> + <File + RelativePath="..\..\src\data-flow.h" + > + </File> + <File + RelativePath="..\..\src\dateparser.cc" + > + </File> + <File + RelativePath="..\..\src\dateparser.h" + > + </File> + <File + RelativePath="..\..\src\debug-agent.cc" + > + </File> + <File + RelativePath="..\..\src\debug-agent.h" + > + </File> + <File + RelativePath="..\..\src\x64\debug-x64.cc" + > + </File> + <File + RelativePath="..\..\src\debug.cc" + > + </File> + <File + RelativePath="..\..\src\debug.h" + > + </File> + <File + RelativePath="..\..\src\x64\deoptimizer-x64.cc" + > + </File> + <File + RelativePath="..\..\src\deoptimizer.cc" + > + </File> + <File + RelativePath="..\..\src\deoptimizer.h" + > + </File> + <File + RelativePath="..\..\src\disassembler.cc" + > + </File> + <File + RelativePath="..\..\src\disassembler.h" + > + </File> + <File + RelativePath="..\..\src\diy-fp.cc" + > + </File> + <File + RelativePath="..\..\src\diy-fp.h" + > + </File> + <File + RelativePath="..\..\src\double.h" + > + </File> + <File + RelativePath="..\..\src\dtoa.cc" + > + </File> + <File + RelativePath="..\..\src\dtoa.h" + > + </File> + <File + RelativePath="..\..\src\execution.cc" + > + </File> + <File + RelativePath="..\..\src\execution.h" + > + </File> + <File + RelativePath="..\..\src\factory.cc" + > + </File> + <File + RelativePath="..\..\src\factory.h" + > + </File> + <File + RelativePath="..\..\src\fast-dtoa.cc" + > + </File> + <File + RelativePath="..\..\src\fast-dtoa.h" + > + </File> + <File + RelativePath="..\..\src\fixed-dtoa.cc" + > + </File> + <File + RelativePath="..\..\src\fixed-dtoa.h" + > + </File> + <File + RelativePath="..\..\src\flags.cc" + > + </File> + <File + RelativePath="..\..\src\flags.h" + > + </File> + <File + RelativePath="..\..\src\flow-graph.cc" + > + </File> + <File + RelativePath="..\..\src\flow-graph.h" + > + </File> + <File + RelativePath="..\..\src\frame-element.cc" + > + </File> + <File + RelativePath="..\..\src\frame-element.h" + > + </File> + <File + RelativePath="..\..\src\x64\frames-x64.cc" + > + </File> + <File + RelativePath="..\..\src\x64\frames-x64.h" + > + </File> + <File + RelativePath="..\..\src\frames-inl.h" + > + </File> + <File + RelativePath="..\..\src\frames.cc" + > + </File> + <File + RelativePath="..\..\src\frames.h" + > + </File> + <File + RelativePath="..\..\src\x64\full-codegen-x64.cc" + > + </File> + <File + RelativePath="..\..\src\full-codegen.cc" + > + </File> + <File + RelativePath="..\..\src\full-codegen.h" + > + </File> + <File - RelativePath="..\..\src\func-name-inferrer.cc" - > - </File> - <File - RelativePath="..\..\src\func-name-inferrer.h" - > - </File> - <File - RelativePath="..\..\src\global-handles.cc" - > - </File> - <File - RelativePath="..\..\src\global-handles.h" - > - </File> - <File - RelativePath="..\..\src\globals.h" - > - </File> - <File - RelativePath="..\..\src\handles-inl.h" - > - </File> - <File - RelativePath="..\..\src\handles.cc" - > - </File> - <File - RelativePath="..\..\src\handles.h" - > - </File> - <File - RelativePath="..\..\src\hashmap.cc" - > - </File> - <File - RelativePath="..\..\src\hashmap.h" - > - </File> - <File - RelativePath="..\..\src\heap-inl.h" - > - </File> - <File - RelativePath="..\..\src\heap.cc" - > - </File> - <File - RelativePath="..\..\src\heap.h" - > - </File> - <File - RelativePath="..\..\src\heap-profiler.cc" - > - </File> - <File - RelativePath="..\..\src\heap-profiler.h" - > - </File> - <File - RelativePath="..\..\src\x64\ic-x64.cc" - > - </File> - <File - RelativePath="..\..\src\ic-inl.h" - > - </File> - <File - RelativePath="..\..\src\ic.cc" - > - </File> - <File - RelativePath="..\..\src\ic.h" - > - </File> - <File - RelativePath="..\..\src\interceptors.h" - > - </File> - <File - RelativePath="..\..\src\interpreter-irregexp.cc" - > - </File> - <File - RelativePath="..\..\src\interpreter-irregexp.h" - > - </File> - <File - RelativePath="..\..\src\jump-target.h" - > - </File> - <File - RelativePath="..\..\src\jump-target-inl.h" - > - </File> - <File - RelativePath="..\..\src\jump-target-heavy-inl.h" - > - </File> - <File - RelativePath="..\..\src\jump-target-heavy.h" - > - </File> - <File - RelativePath="..\..\src\jump-target.cc" - > - </File> - <File - RelativePath="..\..\src\x64\jump-target-x64.cc" - > - </File> - <File - RelativePath="..\..\src\jump-target-heavy.cc" - > - </File> - <File - RelativePath="..\..\src\jsregexp.cc" - > - </File> - <File - RelativePath="..\..\src\jsregexp.h" - > - </File> - <File - RelativePath="..\..\src\list-inl.h" - > - </File> - <File - RelativePath="..\..\src\list.h" - > - </File> - <File - RelativePath="..\..\src\liveedit.cc" - > - </File> - <File - RelativePath="..\..\src\liveedit.h" - > - </File> - <File - RelativePath="..\..\src\log.cc" - > - </File> - <File - RelativePath="..\..\src\log-inl.h" - > - </File> - <File - RelativePath="..\..\src\log.h" - > - </File> - <File - RelativePath="..\..\src\log-utils.cc" - > - </File> - <File - RelativePath="..\..\src\log-utils.h" - > - </File> - <File - RelativePath="..\..\src\x64\macro-assembler-x64.cc" - > - </File> - <File - RelativePath="..\..\src\x64\macro-assembler-x64.h" - > - </File> - <File - RelativePath="..\..\src\macro-assembler.h" - > - </File> - <File - RelativePath="..\..\src\mark-compact.cc" - > - </File> - <File - RelativePath="..\..\src\mark-compact.h" - > - </File> - <File - RelativePath="..\..\src\memory.h" - > - </File> - <File - RelativePath="..\..\src\messages.cc" - > - </File> - <File - RelativePath="..\..\src\messages.h" - > - </File> - <File - RelativePath="..\..\src\natives.h" - > - </File> - <File - RelativePath="..\..\src\objects-debug.cc" - > - <FileConfiguration - Name="Release|x64" - ExcludedFromBuild="true" - > - <Tool - Name="VCCLCompilerTool" - /> - </FileConfiguration> - </File> - <File - RelativePath="..\..\src\objects-inl.h" - > - </File> - <File - RelativePath="..\..\src\objects-visiting.cc" - > - </File> - <File - RelativePath="..\..\src\objects-visiting.h" - > - </File> - <File - RelativePath="..\..\src\objects.cc" - > - </File> - <File - RelativePath="..\..\src\objects.h" - > - </File> - <File - RelativePath="..\..\src\oprofile-agent.cc" - > - </File> - <File - RelativePath="..\..\src\oprofile-agent.h" - > - </File> - <File - RelativePath="..\..\src\parser.cc" - > - </File> - <File - RelativePath="..\..\src\parser.h" - > - </File> - <File - RelativePath="..\..\src\profile-generator.cc" - > - </File> - <File - RelativePath="..\..\src\profile-generator.h" - > - </File> - <File - RelativePath="..\..\src\profile-generator-inl.h" - > - </File> - <File - RelativePath="..\..\src\platform-win32.cc" - > - </File> - <File - RelativePath="..\..\src\platform.h" - > - </File> - <File - RelativePath="..\..\src\prettyprinter.cc" - > - <FileConfiguration - Name="Release|x64" - ExcludedFromBuild="true" - > - <Tool - Name="VCCLCompilerTool" - /> - </FileConfiguration> - </File> - <File - RelativePath="..\..\src\prettyprinter.h" - > - </File> - <File - RelativePath="..\..\src\property.cc" - > - </File> - <File - RelativePath="..\..\src\property.h" - > - </File> - <File - RelativePath="..\..\src\x64\regexp-macro-assembler-x64.cc" - > - </File> - <File - RelativePath="..\..\src\x64\regexp-macro-assembler-x64.h" - > - </File> - <File - RelativePath="..\..\src\regexp-macro-assembler-irregexp.cc" - > - </File> - <File - RelativePath="..\..\src\regexp-macro-assembler-irregexp.h" - > - </File> - <File - RelativePath="..\..\src\regexp-macro-assembler.cc" - > - </File> - <File - RelativePath="..\..\src\regexp-macro-assembler.h" - > - </File> - <File - RelativePath="..\..\src\regexp-macro-assembler-tracer.cc" - > - </File> - <File - RelativePath="..\..\src\regexp-macro-assembler-tracer.h" - > - </File> - <File - RelativePath="..\..\src\regexp-stack.cc" - > - </File> - <File - RelativePath="..\..\src\register-allocator.h" - > - </File> - <File - RelativePath="..\..\src\register-allocator.cc" - > - </File> - <File - RelativePath="..\..\src\x64\register-allocator-x64.cc" - > - </File> - <File - RelativePath="..\..\src\rewriter.cc" - > - </File> - <File - RelativePath="..\..\src\rewriter.h" - > - </File> - <File - RelativePath="..\..\src\runtime.cc" - > - </File> - <File - RelativePath="..\..\src\runtime.h" - > - </File> - <File - RelativePath="..\..\src\scanner.cc" - > - </File> - <File - RelativePath="..\..\src\scanner.h" - > - </File> - <File - RelativePath="..\..\src\scopeinfo.cc" - > - </File> - <File - RelativePath="..\..\src\scopeinfo.h" - > - </File> - <File - RelativePath="..\..\src\scopes.cc" - > - </File> - <File - RelativePath="..\..\src\scopes.h" - > - </File> - <File - RelativePath="..\..\src\serialize.cc" - > - </File> - <File - RelativePath="..\..\src\serialize.h" - > - </File> - <File - RelativePath="..\..\src\shell.h" - > - </File> - <File - RelativePath="..\..\src\snapshot-common.cc" - > - </File> - <File - RelativePath="..\..\src\snapshot.h" - > - </File> - <File - RelativePath="..\..\src\spaces-inl.h" - > - </File> - <File - RelativePath="..\..\src\spaces.cc" - > - </File> - <File - RelativePath="..\..\src\spaces.h" - > - </File> - <File - RelativePath="..\..\src\string-search.cc" - > - </File> - <File - RelativePath="..\..\src\string-search.h" - > - </File> - <File - RelativePath="..\..\src\string-stream.cc" - > - </File> - <File - RelativePath="..\..\src\string-stream.h" - > - </File> - <File - RelativePath="..\..\src\strtod.cc" - > - </File> - <File - RelativePath="..\..\src\strtod.h" - > - </File> - <File - RelativePath="..\..\src\x64\stub-cache-x64.cc" - > - </File> - <File - RelativePath="..\..\src\stub-cache.cc" - > - </File> - <File - RelativePath="..\..\src\stub-cache.h" - > - </File> - <File - RelativePath="..\..\src\token.cc" - > - </File> - <File - RelativePath="..\..\src\token.h" - > - </File> - <File - RelativePath="..\..\src\top.cc" - > - </File> - <File - RelativePath="..\..\src\top.h" - > - </File> - <File - RelativePath="..\..\src\type-info.cc" - > - </File> - <File - RelativePath="..\..\src\type-info.h" - > - </File> - <File - RelativePath="..\..\src\unbound-queue-inl.h" - > - </File> - <File - RelativePath="..\..\src\unbound-queue.h" - > - </File> - <File - RelativePath="..\..\src\unicode-inl.h" - > - </File> - <File - RelativePath="..\..\src\unicode.h" - > - </File> - <File - RelativePath="..\..\src\utils.cc" - > - </File> - <File - RelativePath="..\..\src\utils.h" - > - </File> - <File - RelativePath="..\..\src\v8-counters.cc" - > - </File> - <File - RelativePath="..\..\src\v8-counters.h" - > - </File> - <File - RelativePath="..\..\src\v8.cc" - > - </File> - <File - RelativePath="..\..\src\v8.h" - > - </File> - <File - RelativePath="..\..\src\v8threads.cc" - > - </File> - <File - RelativePath="..\..\src\v8threads.h" - > - </File> - <File - RelativePath="..\..\src\variables.cc" - > - </File> - <File - RelativePath="..\..\src\variables.h" - > - </File> - <File - RelativePath="..\..\src\version.cc" - > - </File> - <File - RelativePath="..\..\src\version.h" - > - </File> - <File - RelativePath="..\..\src\virtual-frame-inl.h" - > - </File> - <File - RelativePath="..\..\src\virtual-frame-heavy-inl.h" - > - </File> - <File - RelativePath="..\..\src\virtual-frame.h" - > - </File> - <File - RelativePath="..\..\src\x64\virtual-frame-x64.h" - > - </File> - <File - RelativePath="..\..\src\virtual-frame.cc" - > - </File> - <File - RelativePath="..\..\src\x64\virtual-frame-x64.cc" - > - </File> - <File - RelativePath="..\..\src\virtual-frame-heavy.cc" - > - </File> - <File - RelativePath="..\..\src\vm-state-inl.h" - > - </File> - <File - RelativePath="..\..\src\vm-state.h" - > - </File> - <File - RelativePath="..\..\src\zone-inl.h" - > - </File> - <File - RelativePath="..\..\src\zone.cc" - > - </File> - <File - RelativePath="..\..\src\zone.h" - > - </File> - <Filter - Name="third party" - > - <File - RelativePath="..\..\src\x64\disasm-x64.cc" - > - </File> - <File - RelativePath="..\..\src\disasm.h" - > - </File> - </Filter> - <Filter - Name="generated files" - > - <File - RelativePath="..\..\src\unicode.cc" - > - </File> - </Filter> - </Filter> - <Filter - Name="include" - > - <File - RelativePath="..\..\include\v8-debug.h" - > - </File> - <File - RelativePath="..\..\include\v8-profiler.h" - > - </File> - <File - RelativePath="..\..\include\v8-testing.h" - > - </File> - <File - RelativePath="..\..\include\v8.h" - > - </File> - </Filter> - </Files> - <Globals> - </Globals> + RelativePath="..\..\src\func-name-inferrer.cc" + > + </File> + <File + RelativePath="..\..\src\func-name-inferrer.h" + > + </File> + <File + RelativePath="..\..\src\global-handles.cc" + > + </File> + <File + RelativePath="..\..\src\global-handles.h" + > + </File> + <File + RelativePath="..\..\src\globals.h" + > + </File> + <File + RelativePath="..\..\src\handles-inl.h" + > + </File> + <File + RelativePath="..\..\src\handles.cc" + > + </File> + <File + RelativePath="..\..\src\handles.h" + > + </File> + <File + RelativePath="..\..\src\hashmap.cc" + > + </File> + <File + RelativePath="..\..\src\hashmap.h" + > + </File> + <File + RelativePath="..\..\src\heap-inl.h" + > + </File> + <File + RelativePath="..\..\src\heap.cc" + > + </File> + <File + RelativePath="..\..\src\heap.h" + > + </File> + <File + RelativePath="..\..\src\hydrogen.cc" + > + </File> + <File + RelativePath="..\..\src\hydrogen.h" + > + </File> + <File + RelativePath="..\..\src\heap-profiler.cc" + > + </File> + <File + RelativePath="..\..\src\heap-profiler.h" + > + </File> + <File + RelativePath="..\..\src\x64\ic-x64.cc" + > + </File> + <File + RelativePath="..\..\src\ic-inl.h" + > + </File> + <File + RelativePath="..\..\src\ic.cc" + > + </File> + <File + RelativePath="..\..\src\ic.h" + > + </File> + <File + RelativePath="..\..\src\interceptors.h" + > + </File> + <File + RelativePath="..\..\src\interpreter-irregexp.cc" + > + </File> + <File + RelativePath="..\..\src\interpreter-irregexp.h" + > + </File> + <File + RelativePath="..\..\src\jump-target.h" + > + </File> + <File + RelativePath="..\..\src\jump-target-inl.h" + > + </File> + <File + RelativePath="..\..\src\jump-target-heavy-inl.h" + > + </File> + <File + RelativePath="..\..\src\jump-target-heavy.h" + > + </File> + <File + RelativePath="..\..\src\jump-target.cc" + > + </File> + <File + RelativePath="..\..\src\x64\jump-target-x64.cc" + > + </File> + <File + RelativePath="..\..\src\jump-target-heavy.cc" + > + </File> + <File + RelativePath="..\..\src\jsregexp.cc" + > + </File> + <File + RelativePath="..\..\src\jsregexp.h" + > + </File> + <File + RelativePath="..\..\src\list-inl.h" + > + </File> + <File + RelativePath="..\..\src\list.h" + > + </File> + <File + RelativePath="..\..\src\lithium-allocator.cc" + > + </File> + <File + RelativePath="..\..\src\lithium-allocator.h" + > + </File> + <File + RelativePath="..\..\src\liveedit.cc" + > + </File> + <File + RelativePath="..\..\src\liveedit.h" + > + </File> + <File + RelativePath="..\..\src\log.cc" + > + </File> + <File + RelativePath="..\..\src\log-inl.h" + > + </File> + <File + RelativePath="..\..\src\log.h" + > + </File> + <File + RelativePath="..\..\src\log-utils.cc" + > + </File> + <File + RelativePath="..\..\src\log-utils.h" + > + </File> + <File + RelativePath="..\..\src\x64\macro-assembler-x64.cc" + > + </File> + <File + RelativePath="..\..\src\x64\macro-assembler-x64.h" + > + </File> + <File + RelativePath="..\..\src\macro-assembler.h" + > + </File> + <File + RelativePath="..\..\src\mark-compact.cc" + > + </File> + <File + RelativePath="..\..\src\mark-compact.h" + > + </File> + <File + RelativePath="..\..\src\memory.h" + > + </File> + <File + RelativePath="..\..\src\messages.cc" + > + </File> + <File + RelativePath="..\..\src\messages.h" + > + </File> + <File + RelativePath="..\..\src\natives.h" + > + </File> + <File + RelativePath="..\..\src\objects-debug.cc" + > + <FileConfiguration + Name="Release|x64" + ExcludedFromBuild="true" + > + <Tool + Name="VCCLCompilerTool" + /> + </FileConfiguration> + </File> + <File + RelativePath="..\..\src\objects-inl.h" + > + </File> + <File + RelativePath="..\..\src\objects-visiting.cc" + > + </File> + <File + RelativePath="..\..\src\objects-visiting.h" + > + </File> + <File + RelativePath="..\..\src\objects.cc" + > + </File> + <File + RelativePath="..\..\src\objects.h" + > + </File> + <File + RelativePath="..\..\src\oprofile-agent.cc" + > + </File> + <File + RelativePath="..\..\src\oprofile-agent.h" + > + </File> + <File + RelativePath="..\..\src\parser.cc" + > + </File> + <File + RelativePath="..\..\src\parser.h" + > + </File> + <File + RelativePath="..\..\src\profile-generator.cc" + > + </File> + <File + RelativePath="..\..\src\profile-generator.h" + > + </File> + <File + RelativePath="..\..\src\profile-generator-inl.h" + > + </File> + <File + RelativePath="..\..\src\platform-win32.cc" + > + </File> + <File + RelativePath="..\..\src\platform.h" + > + </File> + <File + RelativePath="..\..\src\prettyprinter.cc" + > + <FileConfiguration + Name="Release|x64" + ExcludedFromBuild="true" + > + <Tool + Name="VCCLCompilerTool" + /> + </FileConfiguration> + </File> + <File + RelativePath="..\..\src\prettyprinter.h" + > + </File> + <File + RelativePath="..\..\src\property.cc" + > + </File> + <File + RelativePath="..\..\src\property.h" + > + </File> + <File + RelativePath="..\..\src\x64\regexp-macro-assembler-x64.cc" + > + </File> + <File + RelativePath="..\..\src\x64\regexp-macro-assembler-x64.h" + > + </File> + <File + RelativePath="..\..\src\regexp-macro-assembler-irregexp.cc" + > + </File> + <File + RelativePath="..\..\src\regexp-macro-assembler-irregexp.h" + > + </File> + <File + RelativePath="..\..\src\regexp-macro-assembler.cc" + > + </File> + <File + RelativePath="..\..\src\regexp-macro-assembler.h" + > + </File> + <File + RelativePath="..\..\src\regexp-macro-assembler-tracer.cc" + > + </File> + <File + RelativePath="..\..\src\regexp-macro-assembler-tracer.h" + > + </File> + <File + RelativePath="..\..\src\regexp-stack.cc" + > + </File> + <File + RelativePath="..\..\src\register-allocator.h" + > + </File> + <File + RelativePath="..\..\src\register-allocator.cc" + > + </File> + <File + RelativePath="..\..\src\x64\register-allocator-x64.cc" + > + </File> + <File + RelativePath="..\..\src\rewriter.cc" + > + </File> + <File + RelativePath="..\..\src\rewriter.h" + > + </File> + <File + RelativePath="..\..\src\runtime.cc" + > + </File> + <File + RelativePath="..\..\src\runtime.h" + > + </File> + <File + RelativePath="..\..\src\runtime-profiler.cc" + > + </File> + <File + RelativePath="..\..\src\runtime-profiler.h" + > + </File> + <File + RelativePath="..\..\src\safepoint-table.cc" + > + </File> + <File + RelativePath="..\..\src\safepoint-table.h" + > + </File> + <File + RelativePath="..\..\src\scanner.cc" + > + </File> + <File + RelativePath="..\..\src\scanner.h" + > + </File> + <File + RelativePath="..\..\src\scopeinfo.cc" + > + </File> + <File + RelativePath="..\..\src\scopeinfo.h" + > + </File> + <File + RelativePath="..\..\src\scopes.cc" + > + </File> + <File + RelativePath="..\..\src\scopes.h" + > + </File> + <File + RelativePath="..\..\src\serialize.cc" + > + </File> + <File + RelativePath="..\..\src\serialize.h" + > + </File> + <File + RelativePath="..\..\src\shell.h" + > + </File> + <File + RelativePath="..\..\src\snapshot-common.cc" + > + </File> + <File + RelativePath="..\..\src\snapshot.h" + > + </File> + <File + RelativePath="..\..\src\spaces-inl.h" + > + </File> + <File + RelativePath="..\..\src\spaces.cc" + > + </File> + <File + RelativePath="..\..\src\spaces.h" + > + </File> + <File + RelativePath="..\..\src\string-search.cc" + > + </File> + <File + RelativePath="..\..\src\string-search.h" + > + </File> + <File + RelativePath="..\..\src\string-stream.cc" + > + </File> + <File + RelativePath="..\..\src\string-stream.h" + > + </File> + <File + RelativePath="..\..\src\strtod.cc" + > + </File> + <File + RelativePath="..\..\src\strtod.h" + > + </File> + <File + RelativePath="..\..\src\x64\stub-cache-x64.cc" + > + </File> + <File + RelativePath="..\..\src\stub-cache.cc" + > + </File> + <File + RelativePath="..\..\src\stub-cache.h" + > + </File> + <File + RelativePath="..\..\src\token.cc" + > + </File> + <File + RelativePath="..\..\src\token.h" + > + </File> + <File + RelativePath="..\..\src\top.cc" + > + </File> + <File + RelativePath="..\..\src\top.h" + > + </File> + <File + RelativePath="..\..\src\type-info.cc" + > + </File> + <File + RelativePath="..\..\src\type-info.h" + > + </File> + <File + RelativePath="..\..\src\unbound-queue-inl.h" + > + </File> + <File + RelativePath="..\..\src\unbound-queue.h" + > + </File> + <File + RelativePath="..\..\src\unicode-inl.h" + > + </File> + <File + RelativePath="..\..\src\unicode.h" + > + </File> + <File + RelativePath="..\..\src\utils.cc" + > + </File> + <File + RelativePath="..\..\src\utils.h" + > + </File> + <File + RelativePath="..\..\src\v8-counters.cc" + > + </File> + <File + RelativePath="..\..\src\v8-counters.h" + > + </File> + <File + RelativePath="..\..\src\v8.cc" + > + </File> + <File + RelativePath="..\..\src\v8.h" + > + </File> + <File + RelativePath="..\..\src\v8threads.cc" + > + </File> + <File + RelativePath="..\..\src\v8threads.h" + > + </File> + <File + RelativePath="..\..\src\variables.cc" + > + </File> + <File + RelativePath="..\..\src\variables.h" + > + </File> + <File + RelativePath="..\..\src\version.cc" + > + </File> + <File + RelativePath="..\..\src\version.h" + > + </File> + <File + RelativePath="..\..\src\virtual-frame-inl.h" + > + </File> + <File + RelativePath="..\..\src\virtual-frame-heavy-inl.h" + > + </File> + <File + RelativePath="..\..\src\virtual-frame.h" + > + </File> + <File + RelativePath="..\..\src\x64\virtual-frame-x64.h" + > + </File> + <File + RelativePath="..\..\src\virtual-frame.cc" + > + </File> + <File + RelativePath="..\..\src\x64\virtual-frame-x64.cc" + > + </File> + <File + RelativePath="..\..\src\virtual-frame-heavy.cc" + > + </File> + <File + RelativePath="..\..\src\vm-state-inl.h" + > + </File> + <File + RelativePath="..\..\src\vm-state.h" + > + </File> + <File + RelativePath="..\..\src\zone-inl.h" + > + </File> + <File + RelativePath="..\..\src\zone.cc" + > + </File> + <File + RelativePath="..\..\src\zone.h" + > + </File> + <Filter + Name="third party" + > + <File + RelativePath="..\..\src\x64\disasm-x64.cc" + > + </File> + <File + RelativePath="..\..\src\disasm.h" + > + </File> + </Filter> + <Filter + Name="generated files" + > + <File + RelativePath="..\..\src\unicode.cc" + > + </File> + </Filter> + </Filter> + <Filter + Name="include" + > + <File + RelativePath="..\..\include\v8-debug.h" + > + </File> + <File + RelativePath="..\..\include\v8-profiler.h" + > + </File> + <File + RelativePath="..\..\include\v8-testing.h" + > + </File> + <File + RelativePath="..\..\include\v8.h" + > + </File> + </Filter> + </Files> + <Globals> + </Globals> </VisualStudioProject> diff --git a/deps/v8/tools/visual_studio/v8_shell_sample.vcproj b/deps/v8/tools/visual_studio/v8_shell_sample.vcproj index b1e5f017859..4eb38bf842a 100644 --- a/deps/v8/tools/visual_studio/v8_shell_sample.vcproj +++ b/deps/v8/tools/visual_studio/v8_shell_sample.vcproj @@ -37,6 +37,7 @@ /> <Tool Name="VCCLCompilerTool" + AdditionalIncludeDirectories="$(ProjectDir)\..\..\include" /> <Tool Name="VCManagedResourceCompilerTool" @@ -95,6 +96,7 @@ /> <Tool Name="VCCLCompilerTool" + AdditionalIncludeDirectories="$(ProjectDir)\..\..\include" /> <Tool Name="VCManagedResourceCompilerTool" diff --git a/deps/v8/tools/visual_studio/v8_shell_sample_arm.vcproj b/deps/v8/tools/visual_studio/v8_shell_sample_arm.vcproj index a14c91a4583..b4260e02b5e 100644 --- a/deps/v8/tools/visual_studio/v8_shell_sample_arm.vcproj +++ b/deps/v8/tools/visual_studio/v8_shell_sample_arm.vcproj @@ -37,6 +37,7 @@ />
<Tool
Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="$(ProjectDir)\..\..\include"
/>
<Tool
Name="VCManagedResourceCompilerTool"
@@ -95,6 +96,7 @@ />
<Tool
Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="$(ProjectDir)\..\..\include"
/>
<Tool
Name="VCManagedResourceCompilerTool"
diff --git a/deps/v8/tools/visual_studio/v8_shell_sample_x64.vcproj b/deps/v8/tools/visual_studio/v8_shell_sample_x64.vcproj index 44d7b12c796..9ba6703b7c0 100644 --- a/deps/v8/tools/visual_studio/v8_shell_sample_x64.vcproj +++ b/deps/v8/tools/visual_studio/v8_shell_sample_x64.vcproj @@ -37,7 +37,8 @@ /> <Tool Name="VCCLCompilerTool" - /> + AdditionalIncludeDirectories="$(ProjectDir)\..\..\include" + /> <Tool Name="VCManagedResourceCompilerTool" /> @@ -95,6 +96,7 @@ /> <Tool Name="VCCLCompilerTool" + AdditionalIncludeDirectories="$(ProjectDir)\..\..\include" /> <Tool Name="VCManagedResourceCompilerTool" |