From 03fa258df7d9e642c3ccac82d27c9c8167681cce Mon Sep 17 00:00:00 2001 From: Ryan Dahl Date: Tue, 16 Nov 2010 19:13:52 -0800 Subject: [PATCH] Revert "Upgrade V8 to 2.5.6" This reverts commit 564a48643bd3edc6da845e458277a54c8068d0e2. Breaks cygwin --- deps/v8/AUTHORS | 1 - deps/v8/ChangeLog | 23 - deps/v8/include/v8-debug.h | 4 +- deps/v8/include/v8.h | 64 +- deps/v8/include/v8stdint.h | 53 - deps/v8/src/SConscript | 2 - deps/v8/src/api.cc | 15 +- deps/v8/src/arm/assembler-arm.cc | 114 +- deps/v8/src/arm/assembler-arm.h | 41 +- deps/v8/src/arm/codegen-arm.cc | 67 + deps/v8/src/arm/codegen-arm.h | 2 + deps/v8/src/arm/constants-arm.h | 7 - deps/v8/src/arm/full-codegen-arm.cc | 119 +- deps/v8/src/arm/ic-arm.cc | 4 +- deps/v8/src/arm/macro-assembler-arm.cc | 26 +- deps/v8/src/arm/simulator-arm.cc | 108 +- deps/v8/src/arm/simulator-arm.h | 3 - deps/v8/src/assembler.cc | 49 - deps/v8/src/assembler.h | 61 - deps/v8/src/bignum.cc | 767 --------- deps/v8/src/bignum.h | 140 -- deps/v8/src/checks.cc | 9 - deps/v8/src/checks.h | 19 +- deps/v8/src/code-stubs.h | 28 +- deps/v8/src/codegen.cc | 32 +- deps/v8/src/compiler.cc | 1 + deps/v8/src/conversions.cc | 6 +- deps/v8/src/debug-debugger.js | 32 + deps/v8/src/debug.cc | 1 - deps/v8/src/double.h | 32 +- deps/v8/src/flag-definitions.h | 1 - deps/v8/src/full-codegen.cc | 12 +- deps/v8/src/full-codegen.h | 4 +- deps/v8/src/global-handles.cc | 6 +- deps/v8/src/global-handles.h | 3 +- deps/v8/src/globals.h | 3 +- deps/v8/src/heap-inl.h | 7 +- deps/v8/src/heap.cc | 72 +- deps/v8/src/heap.h | 26 +- deps/v8/src/ia32/assembler-ia32.cc | 54 +- deps/v8/src/ia32/assembler-ia32.h | 17 +- deps/v8/src/ia32/code-stubs-ia32.cc | 20 - deps/v8/src/ia32/codegen-ia32.cc | 90 +- deps/v8/src/ia32/codegen-ia32.h | 5 + deps/v8/src/ia32/full-codegen-ia32.cc | 106 +- deps/v8/src/ia32/ic-ia32.cc | 1 + deps/v8/src/ia32/macro-assembler-ia32.h | 2 +- deps/v8/src/ia32/stub-cache-ia32.cc | 178 +- deps/v8/src/jump-target-heavy.cc | 5 +- deps/v8/src/jump-target-light.cc | 5 +- deps/v8/src/objects-debug.cc | 5 - deps/v8/src/objects-inl.h | 42 +- deps/v8/src/objects.h | 4 +- deps/v8/src/parser.cc | 1102 ++++++++---- deps/v8/src/parser.h | 238 +-- deps/v8/src/platform-linux.cc | 71 +- deps/v8/src/preparser.h | 1414 ---------------- deps/v8/src/profile-generator.cc | 30 +- deps/v8/src/profile-generator.h | 2 + deps/v8/src/regexp.js | 115 +- deps/v8/src/runtime.cc | 66 + deps/v8/src/runtime.h | 5 +- deps/v8/src/scanner-base.cc | 167 -- deps/v8/src/scanner-base.h | 165 -- deps/v8/src/scanner.cc | 136 ++ deps/v8/src/scanner.h | 122 +- deps/v8/src/spaces.cc | 34 +- deps/v8/src/spaces.h | 12 +- deps/v8/src/string.js | 82 +- deps/v8/src/strtod.cc | 129 +- deps/v8/src/token.h | 2 - deps/v8/src/utils.cc | 36 + deps/v8/src/utils.h | 315 +++- deps/v8/src/v8.h | 2 +- deps/v8/src/v8utils.h | 301 ---- deps/v8/src/version.cc | 2 +- deps/v8/src/x64/assembler-x64.cc | 54 +- deps/v8/src/x64/assembler-x64.h | 15 +- deps/v8/src/x64/codegen-x64.cc | 82 +- deps/v8/src/x64/codegen-x64.h | 2 + deps/v8/src/x64/full-codegen-x64.cc | 157 +- deps/v8/src/x64/ic-x64.cc | 1 + deps/v8/test/cctest/SConscript | 1 - deps/v8/test/cctest/test-assembler-arm.cc | 68 - deps/v8/test/cctest/test-bignum.cc | 1502 ----------------- deps/v8/test/cctest/test-debug.cc | 45 +- deps/v8/test/cctest/test-double.cc | 16 - deps/v8/test/cctest/test-heap-profiler.cc | 35 +- deps/v8/test/cctest/test-mark-compact.cc | 4 +- deps/v8/test/cctest/test-parsing.cc | 33 +- deps/v8/test/cctest/test-spaces.cc | 6 +- deps/v8/test/cctest/test-strtod.cc | 164 +- deps/v8/test/mjsunit/regress/regress-927.js | 33 - .../regress/regress-conditional-position.js | 95 -- deps/v8/test/mjsunit/string-split.js | 91 +- deps/v8/tools/gyp/v8.gyp | 4 - deps/v8/tools/presubmit.py | 2 +- deps/v8/tools/v8.xcodeproj/project.pbxproj | 8 - deps/v8/tools/visual_studio/v8_base.vcproj | 40 - 99 files changed, 2691 insertions(+), 6813 deletions(-) delete mode 100644 deps/v8/include/v8stdint.h delete mode 100644 deps/v8/src/bignum.cc delete mode 100644 deps/v8/src/bignum.h delete mode 100644 deps/v8/src/preparser.h delete mode 100644 deps/v8/src/scanner-base.cc delete mode 100644 deps/v8/src/scanner-base.h delete mode 100644 deps/v8/src/v8utils.h delete mode 100644 deps/v8/test/cctest/test-bignum.cc delete mode 100644 deps/v8/test/mjsunit/regress/regress-927.js delete mode 100644 deps/v8/test/mjsunit/regress/regress-conditional-position.js diff --git a/deps/v8/AUTHORS b/deps/v8/AUTHORS index 68f9b63bab..3749cebcd1 100644 --- a/deps/v8/AUTHORS +++ b/deps/v8/AUTHORS @@ -9,7 +9,6 @@ ARM Ltd. Hewlett-Packard Development Company, LP Alexander Botero-Lowry -Alexandre Rames Alexandre Vassalotti Andreas Anyuru Burcu Dogan diff --git a/deps/v8/ChangeLog b/deps/v8/ChangeLog index 573ebb3497..69aff33d18 100644 --- a/deps/v8/ChangeLog +++ b/deps/v8/ChangeLog @@ -1,26 +1,3 @@ -2010-11-10: Version 2.5.6 - - Added support for VFP rounding modes to the ARM simulator. - - Fixed multiplication overflow bug (issue 927). - - Added a limit for the amount of executable memory (issue 925). - - -2010-11-08: Version 2.5.5 - - Added more aggressive GC of external objects in near out-of-memory - situations. - - Fixed a bug that gave the incorrect result for String.split called - on the empty string (issue 924). - - -2010-11-03: Version 2.5.4 - - Improved V8 VFPv3 runtime detection to address issue 914. - - 2010-11-01: Version 2.5.3 Fixed a bug that prevents constants from overwriting function values diff --git a/deps/v8/include/v8-debug.h b/deps/v8/include/v8-debug.h index f17b848550..4314727adc 100755 --- a/deps/v8/include/v8-debug.h +++ b/deps/v8/include/v8-debug.h @@ -142,7 +142,7 @@ class EXPORT Debug { virtual ~Message() {} }; - + /** * An event details object passed to the debug event listener. @@ -300,7 +300,7 @@ class EXPORT Debug { * get access to information otherwise not available during normal JavaScript * execution e.g. details on stack frames. Receiver of the function call will * be the debugger context global object, however this is a subject to change. - * The following example show a JavaScript function which when passed to + * The following example show a JavaScript function which when passed to * v8::Debug::Call will return the current line of JavaScript execution. * * \code diff --git a/deps/v8/include/v8.h b/deps/v8/include/v8.h index f6c3c8b301..c7e4552b4d 100644 --- a/deps/v8/include/v8.h +++ b/deps/v8/include/v8.h @@ -38,9 +38,23 @@ #ifndef V8_H_ #define V8_H_ -#include "v8stdint.h" +#include #ifdef _WIN32 +// When compiling on MinGW stdint.h is available. +#ifdef __MINGW32__ +#include +#else // __MINGW32__ +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef short int16_t; // NOLINT +typedef unsigned short uint16_t; // NOLINT +typedef int int32_t; +typedef unsigned int uint32_t; +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +// intptr_t and friends are defined in crtdefs.h through stdio.h. +#endif // __MINGW32__ // Setup for Windows DLL export/import. When building the V8 DLL the // BUILDING_V8_SHARED needs to be defined. When building a program which uses @@ -62,6 +76,8 @@ #else // _WIN32 +#include + // Setup for Linux shared library export. There is no need to distinguish // between building or using the V8 shared library, but we should not // export symbols when we are building a static library. @@ -111,6 +127,7 @@ class Arguments; class Object; class Heap; class Top; + } @@ -459,10 +476,10 @@ class V8EXPORT HandleScope { level = 0; } }; - + void Leave(); - + internal::Object** prev_next_; internal::Object** prev_limit_; @@ -1038,7 +1055,7 @@ class String : public Primitive { */ V8EXPORT bool IsExternalAscii() const; - class V8EXPORT ExternalStringResourceBase { // NOLINT + class V8EXPORT ExternalStringResourceBase { public: virtual ~ExternalStringResourceBase() {} @@ -2348,15 +2365,12 @@ class V8EXPORT ResourceConstraints { void set_max_young_space_size(int value) { max_young_space_size_ = value; } int max_old_space_size() const { return max_old_space_size_; } void set_max_old_space_size(int value) { max_old_space_size_ = value; } - int max_executable_size() { return max_executable_size_; } - void set_max_executable_size(int value) { max_executable_size_ = value; } uint32_t* stack_limit() const { return stack_limit_; } // Sets an address beyond which the VM's stack may not grow. void set_stack_limit(uint32_t* value) { stack_limit_ = value; } private: int max_young_space_size_; int max_old_space_size_; - int max_executable_size_; uint32_t* stack_limit_; }; @@ -2488,18 +2502,13 @@ class V8EXPORT HeapStatistics { public: HeapStatistics(); size_t total_heap_size() { return total_heap_size_; } - size_t total_heap_size_executable() { return total_heap_size_executable_; } size_t used_heap_size() { return used_heap_size_; } private: void set_total_heap_size(size_t size) { total_heap_size_ = size; } - void set_total_heap_size_executable(size_t size) { - total_heap_size_executable_ = size; - } void set_used_heap_size(size_t size) { used_heap_size_ = size; } size_t total_heap_size_; - size_t total_heap_size_executable_; size_t used_heap_size_; friend class V8; @@ -3251,8 +3260,8 @@ class V8EXPORT Locker { /** * An interface for exporting data from V8, using "push" model. */ -class V8EXPORT OutputStream { // NOLINT - public: +class V8EXPORT OutputStream { +public: enum OutputEncoding { kAscii = 0 // 7-bit ASCII. }; @@ -3282,8 +3291,6 @@ class V8EXPORT OutputStream { // NOLINT namespace internal { -const int kPointerSize = sizeof(void*); // NOLINT -const int kIntSize = sizeof(int); // NOLINT // Tag information for HeapObject. const int kHeapObjectTag = 1; @@ -3319,19 +3326,19 @@ template <> struct SmiConstants<8> { } }; -const int kSmiShiftSize = SmiConstants::kSmiShiftSize; -const int kSmiValueSize = SmiConstants::kSmiValueSize; +const int kSmiShiftSize = SmiConstants::kSmiShiftSize; +const int kSmiValueSize = SmiConstants::kSmiValueSize; template struct InternalConstants; // Internal constants for 32-bit systems. template <> struct InternalConstants<4> { - static const int kStringResourceOffset = 3 * kPointerSize; + static const int kStringResourceOffset = 3 * sizeof(void*); }; // Internal constants for 64-bit systems. template <> struct InternalConstants<8> { - static const int kStringResourceOffset = 3 * kPointerSize; + static const int kStringResourceOffset = 3 * sizeof(void*); }; /** @@ -3345,12 +3352,12 @@ class Internals { // These values match non-compiler-dependent values defined within // the implementation of v8. static const int kHeapObjectMapOffset = 0; - static const int kMapInstanceTypeOffset = kPointerSize + kIntSize; + static const int kMapInstanceTypeOffset = sizeof(void*) + sizeof(int); static const int kStringResourceOffset = - InternalConstants::kStringResourceOffset; + InternalConstants::kStringResourceOffset; - static const int kProxyProxyOffset = kPointerSize; - static const int kJSObjectHeaderSize = 3 * kPointerSize; + static const int kProxyProxyOffset = sizeof(void*); + static const int kJSObjectHeaderSize = 3 * sizeof(void*); static const int kFullStringRepresentationMask = 0x07; static const int kExternalTwoByteRepresentationTag = 0x02; @@ -3368,7 +3375,7 @@ class Internals { } static inline int SmiValue(internal::Object* value) { - return SmiConstants::SmiToInt(value); + return SmiConstants::SmiToInt(value); } static inline int GetInstanceType(internal::Object* obj) { @@ -3397,9 +3404,10 @@ class Internals { uint8_t* addr = reinterpret_cast(ptr) + offset - kHeapObjectTag; return *reinterpret_cast(addr); } + }; -} // namespace internal +} template @@ -3559,7 +3567,7 @@ Local Object::UncheckedGetInternalField(int index) { // If the object is a plain JSObject, which is the common case, // we know where to find the internal fields and can return the // value directly. - int offset = I::kJSObjectHeaderSize + (internal::kPointerSize * index); + int offset = I::kJSObjectHeaderSize + (sizeof(void*) * index); O* value = I::ReadField(obj, offset); O** result = HandleScope::CreateHandle(value); return Local(reinterpret_cast(result)); @@ -3595,7 +3603,7 @@ void* Object::GetPointerFromInternalField(int index) { // If the object is a plain JSObject, which is the common case, // we know where to find the internal fields and can return the // value directly. - int offset = I::kJSObjectHeaderSize + (internal::kPointerSize * index); + int offset = I::kJSObjectHeaderSize + (sizeof(void*) * index); O* value = I::ReadField(obj, offset); return I::GetExternalPointer(value); } diff --git a/deps/v8/include/v8stdint.h b/deps/v8/include/v8stdint.h deleted file mode 100644 index 50b4f29a64..0000000000 --- a/deps/v8/include/v8stdint.h +++ /dev/null @@ -1,53 +0,0 @@ -// 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. - -// Load definitions of standard types. - -#ifndef V8STDINT_H_ -#define V8STDINT_H_ - -#include - -#if defined(_WIN32) && !defined(__MINGW32__) - -typedef signed char int8_t; -typedef unsigned char uint8_t; -typedef short int16_t; // NOLINT -typedef unsigned short uint16_t; // NOLINT -typedef int int32_t; -typedef unsigned int uint32_t; -typedef __int64 int64_t; -typedef unsigned __int64 uint64_t; -// intptr_t and friends are defined in crtdefs.h through stdio.h. - -#else - -#include - -#endif - -#endif // V8STDINT_H_ diff --git a/deps/v8/src/SConscript b/deps/v8/src/SConscript index ad647dfa00..ef5485d854 100755 --- a/deps/v8/src/SConscript +++ b/deps/v8/src/SConscript @@ -40,7 +40,6 @@ SOURCES = { api.cc assembler.cc ast.cc - bignum.cc bootstrapper.cc builtins.cc cached-powers.cc @@ -96,7 +95,6 @@ SOURCES = { register-allocator.cc rewriter.cc runtime.cc - scanner-base.cc scanner.cc scopeinfo.cc scopes.cc diff --git a/deps/v8/src/api.cc b/deps/v8/src/api.cc index 9da3346d79..617922dd5a 100644 --- a/deps/v8/src/api.cc +++ b/deps/v8/src/api.cc @@ -43,6 +43,7 @@ #include "serialize.h" #include "snapshot.h" #include "top.h" +#include "utils.h" #include "v8threads.h" #include "version.h" @@ -393,18 +394,14 @@ v8::Handle False() { ResourceConstraints::ResourceConstraints() : max_young_space_size_(0), max_old_space_size_(0), - max_executable_size_(0), stack_limit_(NULL) { } bool SetResourceConstraints(ResourceConstraints* constraints) { int young_space_size = constraints->max_young_space_size(); int old_gen_size = constraints->max_old_space_size(); - int max_executable_size = constraints->max_executable_size(); - if (young_space_size != 0 || old_gen_size != 0 || max_executable_size != 0) { - bool result = i::Heap::ConfigureHeap(young_space_size / 2, - old_gen_size, - max_executable_size); + if (young_space_size != 0 || old_gen_size != 0) { + bool result = i::Heap::ConfigureHeap(young_space_size / 2, old_gen_size); if (!result) return false; } if (constraints->stack_limit() != NULL) { @@ -3263,15 +3260,11 @@ bool v8::V8::Dispose() { } -HeapStatistics::HeapStatistics(): total_heap_size_(0), - total_heap_size_executable_(0), - used_heap_size_(0) { } +HeapStatistics::HeapStatistics(): total_heap_size_(0), used_heap_size_(0) { } void v8::V8::GetHeapStatistics(HeapStatistics* heap_statistics) { heap_statistics->set_total_heap_size(i::Heap::CommittedMemory()); - heap_statistics->set_total_heap_size_executable( - i::Heap::CommittedMemoryExecutable()); heap_statistics->set_used_heap_size(i::Heap::SizeOfObjects()); } diff --git a/deps/v8/src/arm/assembler-arm.cc b/deps/v8/src/arm/assembler-arm.cc index 4cb421c577..ebbd9b1138 100644 --- a/deps/v8/src/arm/assembler-arm.cc +++ b/deps/v8/src/arm/assembler-arm.cc @@ -317,8 +317,7 @@ static const Instr kLdrStrOffsetMask = 0x00000fff; static const int kMinimalBufferSize = 4*KB; static byte* spare_buffer_ = NULL; -Assembler::Assembler(void* buffer, int buffer_size) - : positions_recorder_(this) { +Assembler::Assembler(void* buffer, int buffer_size) { if (buffer == NULL) { // Do our own buffer management. if (buffer_size <= kMinimalBufferSize) { @@ -355,6 +354,10 @@ Assembler::Assembler(void* buffer, int buffer_size) no_const_pool_before_ = 0; last_const_pool_end_ = 0; last_bound_pos_ = 0; + current_statement_position_ = RelocInfo::kNoPosition; + current_position_ = RelocInfo::kNoPosition; + written_statement_position_ = current_statement_position_; + written_position_ = current_position_; } @@ -749,15 +752,15 @@ static bool fits_shifter(uint32_t imm32, // if they can be encoded in the ARM's 12 bits of immediate-offset instruction // space. There is no guarantee that the relocated location can be similarly // encoded. -bool Operand::must_use_constant_pool() const { - if (rmode_ == RelocInfo::EXTERNAL_REFERENCE) { +static bool MustUseConstantPool(RelocInfo::Mode rmode) { + if (rmode == RelocInfo::EXTERNAL_REFERENCE) { #ifdef DEBUG if (!Serializer::enabled()) { Serializer::TooLateToEnableNow(); } #endif // def DEBUG return Serializer::enabled(); - } else if (rmode_ == RelocInfo::NONE) { + } else if (rmode == RelocInfo::NONE) { return false; } return true; @@ -766,7 +769,7 @@ bool Operand::must_use_constant_pool() const { bool Operand::is_single_instruction() const { if (rm_.is_valid()) return true; - if (must_use_constant_pool()) return false; + if (MustUseConstantPool(rmode_)) return false; uint32_t dummy1, dummy2; return fits_shifter(imm32_, &dummy1, &dummy2, NULL); } @@ -782,7 +785,7 @@ void Assembler::addrmod1(Instr instr, // Immediate. uint32_t rotate_imm; uint32_t immed_8; - if (x.must_use_constant_pool() || + if (MustUseConstantPool(x.rmode_) || !fits_shifter(x.imm32_, &rotate_imm, &immed_8, &instr)) { // The immediate operand cannot be encoded as a shifter operand, so load // it first to register ip and change the original instruction to use ip. @@ -791,7 +794,8 @@ void Assembler::addrmod1(Instr instr, CHECK(!rn.is(ip)); // rn should never be ip, or will be trashed Condition cond = static_cast(instr & CondMask); if ((instr & ~CondMask) == 13*B21) { // mov, S not set - if (x.must_use_constant_pool() || !CpuFeatures::IsSupported(ARMv7)) { + if (MustUseConstantPool(x.rmode_) || + !CpuFeatures::IsSupported(ARMv7)) { RecordRelocInfo(x.rmode_, x.imm32_); ldr(rd, MemOperand(pc, 0), cond); } else { @@ -802,7 +806,7 @@ void Assembler::addrmod1(Instr instr, } else { // If this is not a mov or mvn instruction we may still be able to avoid // a constant pool entry by using mvn or movw. - if (!x.must_use_constant_pool() && + if (!MustUseConstantPool(x.rmode_) && (instr & kMovMvnMask) != kMovMvnPattern) { mov(ip, x, LeaveCC, cond); } else { @@ -995,7 +999,7 @@ void Assembler::bl(int branch_offset, Condition cond) { void Assembler::blx(int branch_offset) { // v5 and above - positions_recorder()->WriteRecordedPositions(); + WriteRecordedPositions(); ASSERT((branch_offset & 1) == 0); int h = ((branch_offset & 2) >> 1)*B24; int imm24 = branch_offset >> 2; @@ -1005,14 +1009,14 @@ void Assembler::blx(int branch_offset) { // v5 and above void Assembler::blx(Register target, Condition cond) { // v5 and above - positions_recorder()->WriteRecordedPositions(); + WriteRecordedPositions(); ASSERT(!target.is(pc)); emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | 3*B4 | target.code()); } void Assembler::bx(Register target, Condition cond) { // v5 and above, plus v4t - positions_recorder()->WriteRecordedPositions(); + WriteRecordedPositions(); ASSERT(!target.is(pc)); // use of pc is actually allowed, but discouraged emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | B4 | target.code()); } @@ -1110,7 +1114,7 @@ void Assembler::orr(Register dst, Register src1, const Operand& src2, void Assembler::mov(Register dst, const Operand& src, SBit s, Condition cond) { if (dst.is(pc)) { - positions_recorder()->WriteRecordedPositions(); + WriteRecordedPositions(); } // Don't allow nop instructions in the form mov rn, rn to be generated using // the mov instruction. They must be generated using nop(int) @@ -1335,7 +1339,7 @@ void Assembler::msr(SRegisterFieldMask fields, const Operand& src, // Immediate. uint32_t rotate_imm; uint32_t immed_8; - if (src.must_use_constant_pool() || + if (MustUseConstantPool(src.rmode_) || !fits_shifter(src.imm32_, &rotate_imm, &immed_8, NULL)) { // Immediate operand cannot be encoded, load it first to register ip. RecordRelocInfo(src.rmode_, src.imm32_); @@ -1355,7 +1359,7 @@ void Assembler::msr(SRegisterFieldMask fields, const Operand& src, // Load/Store instructions. void Assembler::ldr(Register dst, const MemOperand& src, Condition cond) { if (dst.is(pc)) { - positions_recorder()->WriteRecordedPositions(); + WriteRecordedPositions(); } addrmod2(cond | B26 | L, dst, src); @@ -2144,7 +2148,6 @@ static Instr EncodeVCVT(const VFPType dst_type, const int dst_code, const VFPType src_type, const int src_code, - Assembler::ConversionMode mode, const Condition cond) { ASSERT(src_type != dst_type); int D, Vd, M, Vm; @@ -2163,7 +2166,7 @@ static Instr EncodeVCVT(const VFPType dst_type, if (IsIntegerVFPType(dst_type)) { opc2 = IsSignedVFPType(dst_type) ? 0x5 : 0x4; sz = IsDoubleVFPType(src_type) ? 0x1 : 0x0; - op = mode; + op = 1; // round towards zero } else { ASSERT(IsIntegerVFPType(src_type)); opc2 = 0x0; @@ -2187,64 +2190,57 @@ static Instr EncodeVCVT(const VFPType dst_type, void Assembler::vcvt_f64_s32(const DwVfpRegister dst, const SwVfpRegister src, - ConversionMode mode, const Condition cond) { ASSERT(CpuFeatures::IsEnabled(VFP3)); - emit(EncodeVCVT(F64, dst.code(), S32, src.code(), mode, cond)); + emit(EncodeVCVT(F64, dst.code(), S32, src.code(), cond)); } void Assembler::vcvt_f32_s32(const SwVfpRegister dst, const SwVfpRegister src, - ConversionMode mode, const Condition cond) { ASSERT(CpuFeatures::IsEnabled(VFP3)); - emit(EncodeVCVT(F32, dst.code(), S32, src.code(), mode, cond)); + emit(EncodeVCVT(F32, dst.code(), S32, src.code(), cond)); } void Assembler::vcvt_f64_u32(const DwVfpRegister dst, const SwVfpRegister src, - ConversionMode mode, const Condition cond) { ASSERT(CpuFeatures::IsEnabled(VFP3)); - emit(EncodeVCVT(F64, dst.code(), U32, src.code(), mode, cond)); + emit(EncodeVCVT(F64, dst.code(), U32, src.code(), cond)); } void Assembler::vcvt_s32_f64(const SwVfpRegister dst, const DwVfpRegister src, - ConversionMode mode, const Condition cond) { ASSERT(CpuFeatures::IsEnabled(VFP3)); - emit(EncodeVCVT(S32, dst.code(), F64, src.code(), mode, cond)); + emit(EncodeVCVT(S32, dst.code(), F64, src.code(), cond)); } void Assembler::vcvt_u32_f64(const SwVfpRegister dst, const DwVfpRegister src, - ConversionMode mode, const Condition cond) { ASSERT(CpuFeatures::IsEnabled(VFP3)); - emit(EncodeVCVT(U32, dst.code(), F64, src.code(), mode, cond)); + emit(EncodeVCVT(U32, dst.code(), F64, src.code(), cond)); } void Assembler::vcvt_f64_f32(const DwVfpRegister dst, const SwVfpRegister src, - ConversionMode mode, const Condition cond) { ASSERT(CpuFeatures::IsEnabled(VFP3)); - emit(EncodeVCVT(F64, dst.code(), F32, src.code(), mode, cond)); + emit(EncodeVCVT(F64, dst.code(), F32, src.code(), cond)); } void Assembler::vcvt_f32_f64(const SwVfpRegister dst, const DwVfpRegister src, - ConversionMode mode, const Condition cond) { ASSERT(CpuFeatures::IsEnabled(VFP3)); - emit(EncodeVCVT(F32, dst.code(), F64, src.code(), mode, cond)); + emit(EncodeVCVT(F32, dst.code(), F64, src.code(), cond)); } @@ -2337,16 +2333,6 @@ void Assembler::vcmp(const DwVfpRegister src1, } -void Assembler::vmsr(Register dst, Condition cond) { - // Instruction details available in ARM DDI 0406A, A8-652. - // cond(31-28) | 1110 (27-24) | 1110(23-20)| 0001 (19-16) | - // Rt(15-12) | 1010 (11-8) | 0(7) | 00 (6-5) | 1(4) | 0000(3-0) - ASSERT(CpuFeatures::IsEnabled(VFP3)); - emit(cond | 0xE*B24 | 0xE*B20 | B16 | - dst.code()*B12 | 0xA*B8 | B4); -} - - void Assembler::vmrs(Register dst, Condition cond) { // Instruction details available in ARM DDI 0406A, A8-652. // cond(31-28) | 1110 (27-24) | 1111(23-20)| 0001 (19-16) | @@ -2357,6 +2343,7 @@ void Assembler::vmrs(Register dst, Condition cond) { } + void Assembler::vsqrt(const DwVfpRegister dst, const DwVfpRegister src, const Condition cond) { @@ -2390,14 +2377,14 @@ void Assembler::BlockConstPoolFor(int instructions) { // Debugging. void Assembler::RecordJSReturn() { - positions_recorder()->WriteRecordedPositions(); + WriteRecordedPositions(); CheckBuffer(); RecordRelocInfo(RelocInfo::JS_RETURN); } void Assembler::RecordDebugBreakSlot() { - positions_recorder()->WriteRecordedPositions(); + WriteRecordedPositions(); CheckBuffer(); RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT); } @@ -2411,6 +2398,47 @@ void Assembler::RecordComment(const char* msg) { } +void Assembler::RecordPosition(int pos) { + if (pos == RelocInfo::kNoPosition) return; + ASSERT(pos >= 0); + current_position_ = pos; +} + + +void Assembler::RecordStatementPosition(int pos) { + if (pos == RelocInfo::kNoPosition) return; + ASSERT(pos >= 0); + current_statement_position_ = pos; +} + + +bool Assembler::WriteRecordedPositions() { + bool written = false; + + // Write the statement position if it is different from what was written last + // time. + if (current_statement_position_ != written_statement_position_) { + CheckBuffer(); + RecordRelocInfo(RelocInfo::STATEMENT_POSITION, current_statement_position_); + written_statement_position_ = current_statement_position_; + written = true; + } + + // Write the position if it is different from what was written last time and + // also different from the written statement position. + if (current_position_ != written_position_ && + current_position_ != written_statement_position_) { + CheckBuffer(); + RecordRelocInfo(RelocInfo::POSITION, current_position_); + written_position_ = current_position_; + written = true; + } + + // Return whether something was written. + return written; +} + + void Assembler::GrowBuffer() { if (!own_buffer_) FATAL("external code buffer is too small"); diff --git a/deps/v8/src/arm/assembler-arm.h b/deps/v8/src/arm/assembler-arm.h index de3931c2cf..5b647a7537 100644 --- a/deps/v8/src/arm/assembler-arm.h +++ b/deps/v8/src/arm/assembler-arm.h @@ -448,7 +448,6 @@ class Operand BASE_EMBEDDED { // Return true of this operand fits in one instruction so that no // 2-instruction solution with a load into the ip register is necessary. bool is_single_instruction() const; - bool must_use_constant_pool() const; inline int32_t immediate() const { ASSERT(!rm_.is_valid()); @@ -1008,37 +1007,26 @@ class Assembler : public Malloced { void vmov(const Register dst, const SwVfpRegister src, const Condition cond = al); - enum ConversionMode { - FPSCRRounding = 0, - RoundToZero = 1 - }; void vcvt_f64_s32(const DwVfpRegister dst, const SwVfpRegister src, - ConversionMode mode = RoundToZero, const Condition cond = al); void vcvt_f32_s32(const SwVfpRegister dst, const SwVfpRegister src, - ConversionMode mode = RoundToZero, const Condition cond = al); void vcvt_f64_u32(const DwVfpRegister dst, const SwVfpRegister src, - ConversionMode mode = RoundToZero, const Condition cond = al); void vcvt_s32_f64(const SwVfpRegister dst, const DwVfpRegister src, - ConversionMode mode = RoundToZero, const Condition cond = al); void vcvt_u32_f64(const SwVfpRegister dst, const DwVfpRegister src, - ConversionMode mode = RoundToZero, const Condition cond = al); void vcvt_f64_f32(const DwVfpRegister dst, const SwVfpRegister src, - ConversionMode mode = RoundToZero, const Condition cond = al); void vcvt_f32_f64(const SwVfpRegister dst, const DwVfpRegister src, - ConversionMode mode = RoundToZero, const Condition cond = al); void vadd(const DwVfpRegister dst, @@ -1067,8 +1055,6 @@ class Assembler : public Malloced { const Condition cond = al); void vmrs(const Register dst, const Condition cond = al); - void vmsr(const Register dst, - const Condition cond = al); void vsqrt(const DwVfpRegister dst, const DwVfpRegister src, const Condition cond = al); @@ -1131,9 +1117,13 @@ class Assembler : public Malloced { // Use --debug_code to enable. void RecordComment(const char* msg); - int pc_offset() const { return pc_ - buffer_; } + void RecordPosition(int pos); + void RecordStatementPosition(int pos); + bool WriteRecordedPositions(); - PositionsRecorder* positions_recorder() { return &positions_recorder_; } + int pc_offset() const { return pc_ - buffer_; } + int current_position() const { return current_position_; } + int current_statement_position() const { return current_statement_position_; } bool can_peephole_optimize(int instructions) { if (!FLAG_peephole_optimization) return false; @@ -1269,6 +1259,12 @@ class Assembler : public Malloced { // The bound position, before this we cannot do instruction elimination. int last_bound_pos_; + // source position information + int current_position_; + int current_statement_position_; + int written_position_; + int written_statement_position_; + // Code emission inline void CheckBuffer(); void GrowBuffer(); @@ -1294,21 +1290,8 @@ class Assembler : public Malloced { friend class RelocInfo; friend class CodePatcher; friend class BlockConstPoolScope; - - PositionsRecorder positions_recorder_; - friend class PositionsRecorder; - friend class EnsureSpace; }; - -class EnsureSpace BASE_EMBEDDED { - public: - explicit EnsureSpace(Assembler* assembler) { - assembler->CheckBuffer(); - } -}; - - } } // namespace v8::internal #endif // V8_ARM_ASSEMBLER_ARM_H_ diff --git a/deps/v8/src/arm/codegen-arm.cc b/deps/v8/src/arm/codegen-arm.cc index d7fd9a4902..70ff244649 100644 --- a/deps/v8/src/arm/codegen-arm.cc +++ b/deps/v8/src/arm/codegen-arm.cc @@ -5496,6 +5496,73 @@ void CodeGenerator::GenerateRegExpConstructResult(ZoneList* args) { } +void CodeGenerator::GenerateRegExpCloneResult(ZoneList* args) { + ASSERT_EQ(1, args->length()); + + Load(args->at(0)); + frame_->PopToR0(); + { + VirtualFrame::SpilledScope spilled_scope(frame_); + + Label done; + Label call_runtime; + __ BranchOnSmi(r0, &done); + + // Load JSRegExp map into r1. Check that argument object has this map. + // Arguments to this function should be results of calling RegExp exec, + // which is either an unmodified JSRegExpResult or null. Anything not having + // the unmodified JSRegExpResult map is returned unmodified. + // This also ensures that elements are fast. + + __ ldr(r1, ContextOperand(cp, Context::GLOBAL_INDEX)); + __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalContextOffset)); + __ ldr(r1, ContextOperand(r1, Context::REGEXP_RESULT_MAP_INDEX)); + __ ldr(ip, FieldMemOperand(r0, HeapObject::kMapOffset)); + __ cmp(r1, Operand(ip)); + __ b(ne, &done); + + if (FLAG_debug_code) { + __ LoadRoot(r2, Heap::kEmptyFixedArrayRootIndex); + __ ldr(ip, FieldMemOperand(r0, JSObject::kPropertiesOffset)); + __ cmp(ip, r2); + __ Check(eq, "JSRegExpResult: default map but non-empty properties."); + } + + // All set, copy the contents to a new object. + __ AllocateInNewSpace(JSRegExpResult::kSize, + r2, + r3, + r4, + &call_runtime, + NO_ALLOCATION_FLAGS); + // Store RegExpResult map as map of allocated object. + ASSERT(JSRegExpResult::kSize == 6 * kPointerSize); + // Copy all fields (map is already in r1) from (untagged) r0 to r2. + // Change map of elements array (ends up in r4) to be a FixedCOWArray. + __ bic(r0, r0, Operand(kHeapObjectTagMask)); + __ ldm(ib, r0, r3.bit() | r4.bit() | r5.bit() | r6.bit() | r7.bit()); + __ stm(ia, r2, + r1.bit() | r3.bit() | r4.bit() | r5.bit() | r6.bit() | r7.bit()); + ASSERT(JSRegExp::kElementsOffset == 2 * kPointerSize); + // Check whether elements array is empty fixed array, and otherwise make + // it copy-on-write (it never should be empty unless someone is messing + // with the arguments to the runtime function). + __ LoadRoot(ip, Heap::kEmptyFixedArrayRootIndex); + __ add(r0, r2, Operand(kHeapObjectTag)); // Tag result and move it to r0. + __ cmp(r4, ip); + __ b(eq, &done); + __ LoadRoot(ip, Heap::kFixedCOWArrayMapRootIndex); + __ str(ip, FieldMemOperand(r4, HeapObject::kMapOffset)); + __ b(&done); + __ bind(&call_runtime); + __ push(r0); + __ CallRuntime(Runtime::kRegExpCloneResult, 1); + __ bind(&done); + } + frame_->EmitPush(r0); +} + + class DeferredSearchCache: public DeferredCode { public: DeferredSearchCache(Register dst, Register cache, Register key) diff --git a/deps/v8/src/arm/codegen-arm.h b/deps/v8/src/arm/codegen-arm.h index 97e50b426b..e6fd6071e1 100644 --- a/deps/v8/src/arm/codegen-arm.h +++ b/deps/v8/src/arm/codegen-arm.h @@ -518,6 +518,8 @@ class CodeGenerator: public AstVisitor { void GenerateRegExpConstructResult(ZoneList* args); + void GenerateRegExpCloneResult(ZoneList* args); + // Support for fast native caches. void GenerateGetFromCache(ZoneList* args); diff --git a/deps/v8/src/arm/constants-arm.h b/deps/v8/src/arm/constants-arm.h index 36f6283c96..123c5e7972 100644 --- a/deps/v8/src/arm/constants-arm.h +++ b/deps/v8/src/arm/constants-arm.h @@ -206,13 +206,6 @@ enum VFPRegPrecision { kDoublePrecision = 1 }; -// VFP rounding modes. See ARM DDI 0406B Page A2-29. -enum FPSCRRoundingModes { - RN, // Round to Nearest. - RP, // Round towards Plus Infinity. - RM, // Round towards Minus Infinity. - RZ // Round towards zero. -}; typedef int32_t instr_t; diff --git a/deps/v8/src/arm/full-codegen-arm.cc b/deps/v8/src/arm/full-codegen-arm.cc index bf27d0c7fe..9935e038f5 100644 --- a/deps/v8/src/arm/full-codegen-arm.cc +++ b/deps/v8/src/arm/full-codegen-arm.cc @@ -1688,14 +1688,12 @@ void FullCodeGenerator::EmitCallWithIC(Call* expr, // Code common for calls using the IC. ZoneList* args = expr->arguments(); int arg_count = args->length(); - { PreserveStatementPositionScope scope(masm()->positions_recorder()); - for (int i = 0; i < arg_count; i++) { - VisitForStackValue(args->at(i)); - } - __ mov(r2, Operand(name)); + for (int i = 0; i < arg_count; i++) { + VisitForStackValue(args->at(i)); } + __ mov(r2, Operand(name)); // Record source position for debugger. - SetSourcePosition(expr->position(), FORCED_POSITION); + SetSourcePosition(expr->position()); // Call the IC initialization code. InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; Handle ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop); @@ -1712,15 +1710,13 @@ void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, // Code common for calls using the IC. ZoneList* args = expr->arguments(); int arg_count = args->length(); - { PreserveStatementPositionScope scope(masm()->positions_recorder()); - for (int i = 0; i < arg_count; i++) { - VisitForStackValue(args->at(i)); - } - VisitForAccumulatorValue(key); - __ mov(r2, r0); + for (int i = 0; i < arg_count; i++) { + VisitForStackValue(args->at(i)); } + VisitForAccumulatorValue(key); + __ mov(r2, r0); // Record source position for debugger. - SetSourcePosition(expr->position(), FORCED_POSITION); + SetSourcePosition(expr->position()); // Call the IC initialization code. InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; Handle ic = CodeGenerator::ComputeKeyedCallInitialize(arg_count, @@ -1736,13 +1732,11 @@ void FullCodeGenerator::EmitCallWithStub(Call* expr) { // Code common for calls using the call stub. ZoneList* args = expr->arguments(); int arg_count = args->length(); - { PreserveStatementPositionScope scope(masm()->positions_recorder()); - for (int i = 0; i < arg_count; i++) { - VisitForStackValue(args->at(i)); - } + for (int i = 0; i < arg_count; i++) { + VisitForStackValue(args->at(i)); } // Record source position for debugger. - SetSourcePosition(expr->position(), FORCED_POSITION); + SetSourcePosition(expr->position()); InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); __ CallStub(&stub); @@ -1762,45 +1756,41 @@ void FullCodeGenerator::VisitCall(Call* expr) { // resolve the function we need to call and the receiver of the // call. Then we call the resolved function using the given // arguments. + VisitForStackValue(fun); + __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); + __ push(r2); // Reserved receiver slot. + + // Push the arguments. ZoneList* args = expr->arguments(); int arg_count = args->length(); + for (int i = 0; i < arg_count; i++) { + VisitForStackValue(args->at(i)); + } - { PreserveStatementPositionScope pos_scope(masm()->positions_recorder()); - VisitForStackValue(fun); - __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); - __ push(r2); // Reserved receiver slot. - - // Push the arguments. - for (int i = 0; i < arg_count; i++) { - VisitForStackValue(args->at(i)); - } + // Push copy of the function - found below the arguments. + __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); + __ push(r1); - // Push copy of the function - found below the arguments. - __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); + // Push copy of the first argument or undefined if it doesn't exist. + if (arg_count > 0) { + __ ldr(r1, MemOperand(sp, arg_count * kPointerSize)); __ push(r1); + } else { + __ push(r2); + } - // Push copy of the first argument or undefined if it doesn't exist. - if (arg_count > 0) { - __ ldr(r1, MemOperand(sp, arg_count * kPointerSize)); - __ push(r1); - } else { - __ push(r2); - } - - // Push the receiver of the enclosing function and do runtime call. - __ ldr(r1, - MemOperand(fp, (2 + scope()->num_parameters()) * kPointerSize)); - __ push(r1); - __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 3); + // Push the receiver of the enclosing function and do runtime call. + __ ldr(r1, MemOperand(fp, (2 + scope()->num_parameters()) * kPointerSize)); + __ push(r1); + __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 3); - // The runtime call returns a pair of values in r0 (function) and - // r1 (receiver). Touch up the stack with the right values. - __ str(r0, MemOperand(sp, (arg_count + 1) * kPointerSize)); - __ str(r1, MemOperand(sp, arg_count * kPointerSize)); - } + // The runtime call returns a pair of values in r0 (function) and + // r1 (receiver). Touch up the stack with the right values. + __ str(r0, MemOperand(sp, (arg_count + 1) * kPointerSize)); + __ str(r1, MemOperand(sp, arg_count * kPointerSize)); // Record source position for debugger. - SetSourcePosition(expr->position(), FORCED_POSITION); + SetSourcePosition(expr->position()); InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); __ CallStub(&stub); @@ -1817,14 +1807,12 @@ void FullCodeGenerator::VisitCall(Call* expr) { // Call to a lookup slot (dynamically introduced variable). Label slow, done; - { PreserveStatementPositionScope scope(masm()->positions_recorder()); - // Generate code for loading from variables potentially shadowed - // by eval-introduced variables. - EmitDynamicLoadFromSlotFastCase(var->AsSlot(), - NOT_INSIDE_TYPEOF, - &slow, - &done); - } + // Generate code for loading from variables potentially shadowed + // by eval-introduced variables. + EmitDynamicLoadFromSlotFastCase(var->AsSlot(), + NOT_INSIDE_TYPEOF, + &slow, + &done); __ bind(&slow); // Call the runtime to find the function to call (returned in r0) @@ -1858,23 +1846,17 @@ void FullCodeGenerator::VisitCall(Call* expr) { Literal* key = prop->key()->AsLiteral(); if (key != NULL && key->handle()->IsSymbol()) { // Call to a named property, use call IC. - { PreserveStatementPositionScope scope(masm()->positions_recorder()); - VisitForStackValue(prop->obj()); - } + VisitForStackValue(prop->obj()); EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); } else { // Call to a keyed property. // For a synthetic property use keyed load IC followed by function call, // for a regular property use keyed CallIC. - { PreserveStatementPositionScope scope(masm()->positions_recorder()); - VisitForStackValue(prop->obj()); - } + VisitForStackValue(prop->obj()); if (prop->is_synthetic()) { - { PreserveStatementPositionScope scope(masm()->positions_recorder()); - VisitForAccumulatorValue(prop->key()); - } + VisitForAccumulatorValue(prop->key()); // Record source code position for IC call. - SetSourcePosition(prop->position(), FORCED_POSITION); + SetSourcePosition(prop->position()); __ pop(r1); // We do not need to keep the receiver. Handle ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); @@ -1897,10 +1879,7 @@ void FullCodeGenerator::VisitCall(Call* expr) { loop_depth() == 0) { lit->set_try_full_codegen(true); } - - { PreserveStatementPositionScope scope(masm()->positions_recorder()); - VisitForStackValue(fun); - } + VisitForStackValue(fun); // Load global receiver object. __ ldr(r1, CodeGenerator::GlobalObject()); __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); diff --git a/deps/v8/src/arm/ic-arm.cc b/deps/v8/src/arm/ic-arm.cc index 4c1f9835f4..a09afdf754 100644 --- a/deps/v8/src/arm/ic-arm.cc +++ b/deps/v8/src/arm/ic-arm.cc @@ -1988,9 +1988,9 @@ void KeyedStoreIC::GenerateExternalArray(MacroAssembler* masm, // Not infinity or NaN simply convert to int. if (IsElementTypeSigned(array_type)) { - __ vcvt_s32_f64(s0, d0, Assembler::RoundToZero, ne); + __ vcvt_s32_f64(s0, d0, ne); } else { - __ vcvt_u32_f64(s0, d0, Assembler::RoundToZero, ne); + __ vcvt_u32_f64(s0, d0, ne); } __ vmov(r5, s0, ne); diff --git a/deps/v8/src/arm/macro-assembler-arm.cc b/deps/v8/src/arm/macro-assembler-arm.cc index d2c22af53d..7f6090bc50 100644 --- a/deps/v8/src/arm/macro-assembler-arm.cc +++ b/deps/v8/src/arm/macro-assembler-arm.cc @@ -129,7 +129,7 @@ void MacroAssembler::Call(intptr_t target, RelocInfo::Mode rmode, // address is loaded. The mov method will automatically record // positions when pc is the target, since this is not the case here // we have to do it explicitly. - positions_recorder()->WriteRecordedPositions(); + WriteRecordedPositions(); mov(ip, Operand(target, rmode), LeaveCC, cond); blx(ip, cond); @@ -220,20 +220,20 @@ void MacroAssembler::Move(Register dst, Register src) { void MacroAssembler::And(Register dst, Register src1, const Operand& src2, Condition cond) { - if (!src2.is_reg() && - !src2.must_use_constant_pool() && - src2.immediate() == 0) { - mov(dst, Operand(0, RelocInfo::NONE), LeaveCC, cond); - - } else if (!src2.is_single_instruction() && - !src2.must_use_constant_pool() && - CpuFeatures::IsSupported(ARMv7) && - IsPowerOf2(src2.immediate() + 1)) { - ubfx(dst, src1, 0, WhichPowerOf2(src2.immediate() + 1), cond); - - } else { + if (!CpuFeatures::IsSupported(ARMv7) || src2.is_single_instruction()) { and_(dst, src1, src2, LeaveCC, cond); + return; + } + int32_t immediate = src2.immediate(); + if (immediate == 0) { + mov(dst, Operand(0, RelocInfo::NONE), LeaveCC, cond); + return; + } + if (IsPowerOf2(immediate + 1) && ((immediate & 1) != 0)) { + ubfx(dst, src1, 0, WhichPowerOf2(immediate + 1), cond); + return; } + and_(dst, src1, src2, LeaveCC, cond); } diff --git a/deps/v8/src/arm/simulator-arm.cc b/deps/v8/src/arm/simulator-arm.cc index 3ec5f449d8..cb91520f3a 100644 --- a/deps/v8/src/arm/simulator-arm.cc +++ b/deps/v8/src/arm/simulator-arm.cc @@ -705,7 +705,6 @@ Simulator::Simulator() { z_flag_FPSCR_ = false; c_flag_FPSCR_ = false; v_flag_FPSCR_ = false; - FPSCR_rounding_mode_ = RZ; inv_op_vfp_flag_ = false; div_zero_vfp_flag_ = false; @@ -2502,45 +2501,10 @@ void Simulator::DecodeTypeVFP(Instr* instr) { (instr->VAField() == 0x7) && (instr->Bits(19, 16) == 0x1)) { // vmrs - uint32_t rt = instr->RtField(); - if (rt == 0xF) { + if (instr->RtField() == 0xF) Copy_FPSCR_to_APSR(); - } else { - // Emulate FPSCR from the Simulator flags. - uint32_t fpscr = (n_flag_FPSCR_ << 31) | - (z_flag_FPSCR_ << 30) | - (c_flag_FPSCR_ << 29) | - (v_flag_FPSCR_ << 28) | - (inexact_vfp_flag_ << 4) | - (underflow_vfp_flag_ << 3) | - (overflow_vfp_flag_ << 2) | - (div_zero_vfp_flag_ << 1) | - (inv_op_vfp_flag_ << 0) | - (FPSCR_rounding_mode_ << 22); - set_register(rt, fpscr); - } - } else if ((instr->VLField() == 0x0) && - (instr->VCField() == 0x0) && - (instr->VAField() == 0x7) && - (instr->Bits(19, 16) == 0x1)) { - // vmsr - uint32_t rt = instr->RtField(); - if (rt == pc) { - UNREACHABLE(); - } else { - uint32_t rt_value = get_register(rt); - n_flag_FPSCR_ = (rt_value >> 31) & 1; - z_flag_FPSCR_ = (rt_value >> 30) & 1; - c_flag_FPSCR_ = (rt_value >> 29) & 1; - v_flag_FPSCR_ = (rt_value >> 28) & 1; - inexact_vfp_flag_ = (rt_value >> 4) & 1; - underflow_vfp_flag_ = (rt_value >> 3) & 1; - overflow_vfp_flag_ = (rt_value >> 2) & 1; - div_zero_vfp_flag_ = (rt_value >> 1) & 1; - inv_op_vfp_flag_ = (rt_value >> 0) & 1; - FPSCR_rounding_mode_ = - static_cast((rt_value >> 22) & 3); - } + else + UNIMPLEMENTED(); // Not used by V8. } else { UNIMPLEMENTED(); // Not used by V8. } @@ -2641,71 +2605,29 @@ void Simulator::DecodeVCVTBetweenFloatingPointAndInteger(Instr* instr) { if (to_integer) { bool unsigned_integer = (instr->Bit(16) == 0); - FPSCRRoundingModes mode; if (instr->Bit(7) != 1) { - // Use FPSCR defined rounding mode. - mode = FPSCR_rounding_mode_; - // Only RZ and RM modes are supported. - ASSERT((mode == RM) || (mode == RZ)); - } else { - // VFP uses round towards zero by default. - mode = RZ; + // Only rounding towards zero supported. + UNIMPLEMENTED(); // Not used by V8. } int dst = instr->VFPDRegCode(kSinglePrecision); int src = instr->VFPMRegCode(src_precision); - int32_t kMaxInt = v8::internal::kMaxInt; - int32_t kMinInt = v8::internal::kMinInt; - switch (mode) { - case RM: - if (src_precision == kDoublePrecision) { - double val = get_double_from_d_register(src); - - inv_op_vfp_flag_ = (val > kMaxInt) || (val < kMinInt) || (val != val); - - int sint = unsigned_integer ? static_cast(val) : - static_cast(val); - sint = sint > val ? sint - 1 : sint; - - set_s_register_from_sinteger(dst, sint); - } else { - float val = get_float_from_s_register(src); - inv_op_vfp_flag_ = (val > kMaxInt) || (val < kMinInt) || (val != val); - - int sint = unsigned_integer ? static_cast(val) : - static_cast(val); - sint = sint > val ? sint - 1 : sint; - - set_s_register_from_sinteger(dst, sint); - } - break; - case RZ: - if (src_precision == kDoublePrecision) { - double val = get_double_from_d_register(src); - - inv_op_vfp_flag_ = (val > kMaxInt) || (val < kMinInt) || (val != val); - - int sint = unsigned_integer ? static_cast(val) : - static_cast(val); - - set_s_register_from_sinteger(dst, sint); - } else { - float val = get_float_from_s_register(src); + if (src_precision == kDoublePrecision) { + double val = get_double_from_d_register(src); - inv_op_vfp_flag_ = (val > kMaxInt) || (val < kMinInt) || (val != val); + int sint = unsigned_integer ? static_cast(val) : + static_cast(val); - int sint = unsigned_integer ? static_cast(val) : - static_cast(val); + set_s_register_from_sinteger(dst, sint); + } else { + float val = get_float_from_s_register(src); - set_s_register_from_sinteger(dst, sint); - } - break; + int sint = unsigned_integer ? static_cast(val) : + static_cast(val); - default: - UNREACHABLE(); + set_s_register_from_sinteger(dst, sint); } - } else { bool unsigned_integer = (instr->Bit(7) == 0); diff --git a/deps/v8/src/arm/simulator-arm.h b/deps/v8/src/arm/simulator-arm.h index c37b3f7156..3e023489ee 100644 --- a/deps/v8/src/arm/simulator-arm.h +++ b/deps/v8/src/arm/simulator-arm.h @@ -306,9 +306,6 @@ class Simulator { bool c_flag_FPSCR_; bool v_flag_FPSCR_; - // VFP rounding mode. See ARM DDI 0406B Page A2-29. - FPSCRRoundingModes FPSCR_rounding_mode_; - // VFP FP exception flags architecture state. bool inv_op_vfp_flag_; bool div_zero_vfp_flag_; diff --git a/deps/v8/src/assembler.cc b/deps/v8/src/assembler.cc index 7493673e81..ce90dceacb 100644 --- a/deps/v8/src/assembler.cc +++ b/deps/v8/src/assembler.cc @@ -804,53 +804,4 @@ ExternalReference ExternalReference::debug_step_in_fp_address() { } #endif - -void PositionsRecorder::RecordPosition(int pos, - PositionRecordingType recording_type) { - ASSERT(pos != RelocInfo::kNoPosition); - ASSERT(pos >= 0); - current_position_ = pos; - current_position_recording_type_ = recording_type; -} - - -void PositionsRecorder::RecordStatementPosition(int pos) { - ASSERT(pos != RelocInfo::kNoPosition); - ASSERT(pos >= 0); - current_statement_position_ = pos; -} - - -bool PositionsRecorder::WriteRecordedPositions() { - bool written = false; - - // Write the statement position if it is different from what was written last - // time. - if (current_statement_position_ != written_statement_position_) { - EnsureSpace ensure_space(assembler_); - assembler_->RecordRelocInfo(RelocInfo::STATEMENT_POSITION, - current_statement_position_); - written_statement_position_ = current_statement_position_; - written = true; - } - - // Write the position if it is different from what was written last time and - // also different from the written statement position or was forced. - if (current_position_ != written_position_ && - (current_position_ != current_statement_position_ || !written) && - (current_position_ != written_statement_position_ - || current_position_recording_type_ == FORCED_POSITION)) { - EnsureSpace ensure_space(assembler_); - assembler_->RecordRelocInfo(RelocInfo::POSITION, current_position_); - written_position_ = current_position_; - written = true; - } - - current_position_recording_type_ = NORMAL_POSITION; - - // Return whether something was written. - return written; -} - - } } // namespace v8::internal diff --git a/deps/v8/src/assembler.h b/deps/v8/src/assembler.h index 09159fed08..66811777fa 100644 --- a/deps/v8/src/assembler.h +++ b/deps/v8/src/assembler.h @@ -584,67 +584,6 @@ class ExternalReference BASE_EMBEDDED { }; -// ----------------------------------------------------------------------------- -// Position recording support - -enum PositionRecordingType { FORCED_POSITION, NORMAL_POSITION }; - -class PositionsRecorder BASE_EMBEDDED { - public: - explicit PositionsRecorder(Assembler* assembler) - : assembler_(assembler), - current_position_(RelocInfo::kNoPosition), - current_position_recording_type_(NORMAL_POSITION), - written_position_(RelocInfo::kNoPosition), - current_statement_position_(RelocInfo::kNoPosition), - written_statement_position_(RelocInfo::kNoPosition) { } - - // Set current position to pos. If recording_type is FORCED_POSITION then - // WriteRecordedPositions will write this position even if it is equal to - // statement position previously written for another pc. - void RecordPosition(int pos, - PositionRecordingType recording_type = NORMAL_POSITION); - - // Set current statement position to pos. - void RecordStatementPosition(int pos); - - // Write recorded positions to relocation information. - bool WriteRecordedPositions(); - - int current_position() const { return current_position_; } - - int current_statement_position() const { return current_statement_position_; } - - private: - Assembler* assembler_; - - int current_position_; - PositionRecordingType current_position_recording_type_; - int written_position_; - - int current_statement_position_; - int written_statement_position_; -}; - - -class PreserveStatementPositionScope BASE_EMBEDDED { - public: - explicit PreserveStatementPositionScope(PositionsRecorder* positions_recorder) - : positions_recorder_(positions_recorder), - statement_position_(positions_recorder->current_statement_position()) {} - - ~PreserveStatementPositionScope() { - if (statement_position_ != RelocInfo::kNoPosition) { - positions_recorder_->RecordStatementPosition(statement_position_); - } - } - - private: - PositionsRecorder* positions_recorder_; - int statement_position_; -}; - - // ----------------------------------------------------------------------------- // Utility functions diff --git a/deps/v8/src/bignum.cc b/deps/v8/src/bignum.cc deleted file mode 100644 index dd1537a25a..0000000000 --- a/deps/v8/src/bignum.cc +++ /dev/null @@ -1,767 +0,0 @@ -// 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 "v8.h" - -#include "bignum.h" -#include "utils.h" - -namespace v8 { -namespace internal { - -Bignum::Bignum() - : bigits_(bigits_buffer_, kBigitCapacity), used_digits_(0), exponent_(0) { - for (int i = 0; i < kBigitCapacity; ++i) { - bigits_[i] = 0; - } -} - - -template -static int BitSize(S value) { - return 8 * sizeof(value); -} - -// Guaranteed to lie in one Bigit. -void Bignum::AssignUInt16(uint16_t value) { - ASSERT(kBigitSize >= BitSize(value)); - Zero(); - if (value == 0) return; - - EnsureCapacity(1); - bigits_[0] = value; - used_digits_ = 1; -} - - -void Bignum::AssignUInt64(uint64_t value) { - const int kUInt64Size = 64; - - Zero(); - if (value == 0) return; - - int needed_bigits = kUInt64Size / kBigitSize + 1; - EnsureCapacity(needed_bigits); - for (int i = 0; i < needed_bigits; ++i) { - bigits_[i] = value & kBigitMask; - value = value >> kBigitSize; - } - used_digits_ = needed_bigits; - Clamp(); -} - - -void Bignum::AssignBignum(const Bignum& other) { - exponent_ = other.exponent_; - for (int i = 0; i < other.used_digits_; ++i) { - bigits_[i] = other.bigits_[i]; - } - // Clear the excess digits (if there were any). - for (int i = other.used_digits_; i < used_digits_; ++i) { - bigits_[i] = 0; - } - used_digits_ = other.used_digits_; -} - - -static uint64_t ReadUInt64(Vector buffer, - int from, - int digits_to_read) { - uint64_t result = 0; - for (int i = from; i < from + digits_to_read; ++i) { - int digit = buffer[i] - '0'; - ASSERT(0 <= digit && digit <= 9); - result = result * 10 + digit; - } - return result; -} - - -void Bignum::AssignDecimalString(Vector value) { - // 2^64 = 18446744073709551616 > 10^19 - const int kMaxUint64DecimalDigits = 19; - Zero(); - int length = value.length(); - int pos = 0; - // Let's just say that each digit needs 4 bits. - while (length >= kMaxUint64DecimalDigits) { - uint64_t digits = ReadUInt64(value, pos, kMaxUint64DecimalDigits); - pos += kMaxUint64DecimalDigits; - length -= kMaxUint64DecimalDigits; - MultiplyByPowerOfTen(kMaxUint64DecimalDigits); - AddUInt64(digits); - } - uint64_t digits = ReadUInt64(value, pos, length); - MultiplyByPowerOfTen(length); - AddUInt64(digits); - Clamp(); -} - - -static int HexCharValue(char c) { - if ('0' <= c && c <= '9') return c - '0'; - if ('a' <= c && c <= 'f') return 10 + c - 'a'; - if ('A' <= c && c <= 'F') return 10 + c - 'A'; - UNREACHABLE(); - return 0; // To make compiler happy. -} - - -void Bignum::AssignHexString(Vector value) { - Zero(); - int length = value.length(); - - int needed_bigits = length * 4 / kBigitSize + 1; - EnsureCapacity(needed_bigits); - int string_index = length - 1; - for (int i = 0; i < needed_bigits - 1; ++i) { - // These bigits are guaranteed to be "full". - Chunk current_bigit = 0; - for (int j = 0; j < kBigitSize / 4; j++) { - current_bigit += HexCharValue(value[string_index--]) << (j * 4); - } - bigits_[i] = current_bigit; - } - used_digits_ = needed_bigits - 1; - - Chunk most_significant_bigit = 0; // Could be = 0; - for (int j = 0; j <= string_index; ++j) { - most_significant_bigit <<= 4; - most_significant_bigit += HexCharValue(value[j]); - } - if (most_significant_bigit != 0) { - bigits_[used_digits_] = most_significant_bigit; - used_digits_++; - } - Clamp(); -} - - -void Bignum::AddUInt64(uint64_t operand) { - if (operand == 0) return; - Bignum other; - other.AssignUInt64(operand); - AddBignum(other); -} - - -void Bignum::AddBignum(const Bignum& other) { - ASSERT(IsClamped()); - ASSERT(other.IsClamped()); - - // If this has a greater exponent than other append zero-bigits to this. - // After this call exponent_ <= other.exponent_. - Align(other); - - // There are two possibilities: - // aaaaaaaaaaa 0000 (where the 0s represent a's exponent) - // bbbbb 00000000 - // ---------------- - // ccccccccccc 0000 - // or - // aaaaaaaaaa 0000 - // bbbbbbbbb 0000000 - // ----------------- - // cccccccccccc 0000 - // In both cases we might need a carry bigit. - - EnsureCapacity(1 + Max(BigitLength(), other.BigitLength()) - exponent_); - Chunk carry = 0; - int bigit_pos = other.exponent_ - exponent_; - ASSERT(bigit_pos >= 0); - for (int i = 0; i < other.used_digits_; ++i) { - Chunk sum = bigits_[bigit_pos] + other.bigits_[i] + carry; - bigits_[bigit_pos] = sum & kBigitMask; - carry = sum >> kBigitSize; - bigit_pos++; - } - - while (carry != 0) { - Chunk sum = bigits_[bigit_pos] + carry; - bigits_[bigit_pos] = sum & kBigitMask; - carry = sum >> kBigitSize; - bigit_pos++; - } - used_digits_ = Max(bigit_pos, used_digits_); - ASSERT(IsClamped()); -} - - -void Bignum::SubtractBignum(const Bignum& other) { - ASSERT(IsClamped()); - ASSERT(other.IsClamped()); - // We require this to be bigger than other. - ASSERT(LessEqual(other, *this)); - - Align(other); - - int offset = other.exponent_ - exponent_; - Chunk borrow = 0; - int i; - for (i = 0; i < other.used_digits_; ++i) { - ASSERT((borrow == 0) || (borrow == 1)); - Chunk difference = bigits_[i + offset] - other.bigits_[i] - borrow; - bigits_[i + offset] = difference & kBigitMask; - borrow = difference >> (kChunkSize - 1); - } - while (borrow != 0) { - Chunk difference = bigits_[i + offset] - borrow; - bigits_[i + offset] = difference & kBigitMask; - borrow = difference >> (kChunkSize - 1); - ++i; - } - Clamp(); -} - - -void Bignum::ShiftLeft(int shift_amount) { - if (used_digits_ == 0) return; - exponent_ += shift_amount / kBigitSize; - int local_shift = shift_amount % kBigitSize; - EnsureCapacity(used_digits_ + 1); - BigitsShiftLeft(local_shift); -} - - -void Bignum::MultiplyByUInt32(uint32_t factor) { - if (factor == 1) return; - if (factor == 0) { - Zero(); - return; - } - if (used_digits_ == 0) return; - - // The product of a bigit with the factor is of size kBigitSize + 32. - // Assert that this number + 1 (for the carry) fits into double chunk. - ASSERT(kDoubleChunkSize >= kBigitSize + 32 + 1); - DoubleChunk carry = 0; - for (int i = 0; i < used_digits_; ++i) { - DoubleChunk product = static_cast(factor) * bigits_[i] + carry; - bigits_[i] = static_cast(product & kBigitMask); - carry = (product >> kBigitSize); - } - while (carry != 0) { - EnsureCapacity(used_digits_ + 1); - bigits_[used_digits_] = carry & kBigitMask; - used_digits_++; - carry >>= kBigitSize; - } -} - - -void Bignum::MultiplyByUInt64(uint64_t factor) { - if (factor == 1) return; - if (factor == 0) { - Zero(); - return; - } - ASSERT(kBigitSize < 32); - uint64_t carry = 0; - uint64_t low = factor & 0xFFFFFFFF; - uint64_t high = factor >> 32; - for (int i = 0; i < used_digits_; ++i) { - uint64_t product_low = low * bigits_[i]; - uint64_t product_high = high * bigits_[i]; - uint64_t tmp = (carry & kBigitMask) + product_low; - bigits_[i] = tmp & kBigitMask; - carry = (carry >> kBigitSize) + (tmp >> kBigitSize) + - (product_high << (32 - kBigitSize)); - } - while (carry != 0) { - EnsureCapacity(used_digits_ + 1); - bigits_[used_digits_] = carry & kBigitMask; - used_digits_++; - carry >>= kBigitSize; - } -} - - -void Bignum::MultiplyByPowerOfTen(int exponent) { - const uint64_t kFive27 = V8_2PART_UINT64_C(0x6765c793, fa10079d); - const uint16_t kFive1 = 5; - const uint16_t kFive2 = kFive1 * 5; - const uint16_t kFive3 = kFive2 * 5; - const uint16_t kFive4 = kFive3 * 5; - const uint16_t kFive5 = kFive4 * 5; - const uint16_t kFive6 = kFive5 * 5; - const uint32_t kFive7 = kFive6 * 5; - const uint32_t kFive8 = kFive7 * 5; - const uint32_t kFive9 = kFive8 * 5; - const uint32_t kFive10 = kFive9 * 5; - const uint32_t kFive11 = kFive10 * 5; - const uint32_t kFive12 = kFive11 * 5; - const uint32_t kFive13 = kFive12 * 5; - const uint32_t kFive1_to_12[] = - { kFive1, kFive2, kFive3, kFive4, kFive5, kFive6, - kFive7, kFive8, kFive9, kFive10, kFive11, kFive12 }; - - ASSERT(exponent >= 0); - if (exponent == 0) return; - if (used_digits_ == 0) return; - - // We shift by exponent at the end just before returning. - int remaining_exponent = exponent; - while (remaining_exponent >= 27) { - MultiplyByUInt64(kFive27); - remaining_exponent -= 27; - } - while (remaining_exponent >= 13) { - MultiplyByUInt32(kFive13); - remaining_exponent -= 13; - } - if (remaining_exponent > 0) { - MultiplyByUInt32(kFive1_to_12[remaining_exponent - 1]); - } - ShiftLeft(exponent); -} - - -void Bignum::Square() { - ASSERT(IsClamped()); - int product_length = 2 * used_digits_; - EnsureCapacity(product_length); - - // Comba multiplication: compute each column separately. - // Example: r = a2a1a0 * b2b1b0. - // r = 1 * a0b0 + - // 10 * (a1b0 + a0b1) + - // 100 * (a2b0 + a1b1 + a0b2) + - // 1000 * (a2b1 + a1b2) + - // 10000 * a2b2 - // - // In the worst case we have to accumulate nb-digits products of digit*digit. - // - // Assert that the additional number of bits in a DoubleChunk are enough to - // sum up used_digits of Bigit*Bigit. - if ((1 << (2 * (kChunkSize - kBigitSize))) <= used_digits_) { - UNIMPLEMENTED(); - } - DoubleChunk accumulator = 0; - // First shift the digits so we don't overwrite them. - int copy_offset = used_digits_; - for (int i = 0; i < used_digits_; ++i) { - bigits_[copy_offset + i] = bigits_[i]; - } - // We have two loops to avoid some 'if's in the loop. - for (int i = 0; i < used_digits_; ++i) { - // Process temporary digit i with power i. - // The sum of the two indices must be equal to i. - int bigit_index1 = i; - int bigit_index2 = 0; - // Sum all of the sub-products. - while (bigit_index1 >= 0) { - Chunk chunk1 = bigits_[copy_offset + bigit_index1]; - Chunk chunk2 = bigits_[copy_offset + bigit_index2]; - accumulator += static_cast(chunk1) * chunk2; - bigit_index1--; - bigit_index2++; - } - bigits_[i] = static_cast(accumulator) & kBigitMask; - accumulator >>= kBigitSize; - } - for (int i = used_digits_; i < product_length; ++i) { - int bigit_index1 = used_digits_ - 1; - int bigit_index2 = i - bigit_index1; - // Invariant: sum of both indices is again equal to i. - // Inner loop runs 0 times on last iteration, emptying accumulator. - while (bigit_index2 < used_digits_) { - Chunk chunk1 = bigits_[copy_offset + bigit_index1]; - Chunk chunk2 = bigits_[copy_offset + bigit_index2]; - accumulator += static_cast(chunk1) * chunk2; - bigit_index1--; - bigit_index2++; - } - // The overwritten bigits_[i] will never be read in further loop iterations, - // because bigit_index1 and bigit_index2 are always greater - // than i - used_digits_. - bigits_[i] = static_cast(accumulator) & kBigitMask; - accumulator >>= kBigitSize; - } - // Since the result was guaranteed to lie inside the number the - // accumulator must be 0 now. - ASSERT(accumulator == 0); - - // Don't forget to update the used_digits and the exponent. - used_digits_ = product_length; - exponent_ *= 2; - Clamp(); -} - - -void Bignum::AssignPowerUInt16(uint16_t base, int power_exponent) { - ASSERT(base != 0); - ASSERT(power_exponent >= 0); - if (power_exponent == 0) { - AssignUInt16(1); - return; - } - Zero(); - int shifts = 0; - // We expect base to be in range 2-32, and most often to be 10. - // It does not make much sense to implement different algorithms for counting - // the bits. - while ((base & 1) == 0) { - base >>= 1; - shifts++; - } - int bit_size = 0; - int tmp_base = base; - while (tmp_base != 0) { - tmp_base >>= 1; - bit_size++; - } - int final_size = bit_size * power_exponent; - // 1 extra bigit for the shifting, and one for rounded final_size. - EnsureCapacity(final_size / kBigitSize + 2); - - // Left to Right exponentiation. - int mask = 1; - while (power_exponent >= mask) mask <<= 1; - - // The mask is now pointing to the bit above the most significant 1-bit of - // power_exponent. - // Get rid of first 1-bit; - mask >>= 2; - uint64_t this_value = base; - - bool delayed_multipliciation = false; - const uint64_t max_32bits = 0xFFFFFFFF; - while (mask != 0 && this_value <= max_32bits) { - this_value = this_value * this_value; - // Verify that there is enough space in this_value to perform the - // multiplication. The first bit_size bits must be 0. - if ((power_exponent & mask) != 0) { - uint64_t base_bits_mask = - ~((static_cast(1) << (64 - bit_size)) - 1); - bool high_bits_zero = (this_value & base_bits_mask) == 0; - if (high_bits_zero) { - this_value *= base; - } else { - delayed_multipliciation = true; - } - } - mask >>= 1; - } - AssignUInt64(this_value); - if (delayed_multipliciation) { - MultiplyByUInt32(base); - } - - // Now do the same thing as a bignum. - while (mask != 0) { - Square(); - if ((power_exponent & mask) != 0) { - MultiplyByUInt32(base); - } - mask >>= 1; - } - - // And finally add the saved shifts. - ShiftLeft(shifts * power_exponent); -} - - -// Precondition: this/other < 16bit. -uint16_t Bignum::DivideModuloIntBignum(const Bignum& other) { - ASSERT(IsClamped()); - ASSERT(other.IsClamped()); - ASSERT(other.used_digits_ > 0); - - // Easy case: if we have less digits than the divisor than the result is 0. - // Note: this handles the case where this == 0, too. - if (BigitLength() < other.BigitLength()) { - return 0; - } - - Align(other); - - uint16_t result = 0; - - // Start by removing multiples of 'other' until both numbers have the same - // number of digits. - while (BigitLength() > other.BigitLength()) { - // This naive approach is extremely inefficient if the this divided other - // might be big. This function is implemented for doubleToString where - // the result should be small (less than 10). - ASSERT(other.bigits_[other.used_digits_ - 1] >= ((1 << kBigitSize) / 16)); - // Remove the multiples of the first digit. - // Example this = 23 and other equals 9. -> Remove 2 multiples. - result += bigits_[used_digits_ - 1]; - SubtractTimes(other, bigits_[used_digits_ - 1]); - } - - ASSERT(BigitLength() == other.BigitLength()); - - // Both bignums are at the same length now. - // Since other has more than 0 digits we know that the access to - // bigits_[used_digits_ - 1] is safe. - Chunk this_bigit = bigits_[used_digits_ - 1]; - Chunk other_bigit = other.bigits_[other.used_digits_ - 1]; - - if (other.used_digits_ == 1) { - // Shortcut for easy (and common) case. - int quotient = this_bigit / other_bigit; - bigits_[used_digits_ - 1] = this_bigit - other_bigit * quotient; - result += quotient; - Clamp(); - return result; - } - - int division_estimate = this_bigit / (other_bigit + 1); - result += division_estimate; - SubtractTimes(other, division_estimate); - - if (other_bigit * (division_estimate + 1) > this_bigit) { - // No need to even try to subtract. Even if other's remaining digits were 0 - // another subtraction would be too much. - return result; - } - - while (LessEqual(other, *this)) { - SubtractBignum(other); - result++; - } - return result; -} - - -template -static int SizeInHexChars(S number) { - ASSERT(number > 0); - int result = 0; - while (number != 0) { - number >>= 4; - result++; - } - return result; -} - - -static char HexCharOfValue(int value) { - ASSERT(0 <= value && value <= 16); - if (value < 10) return value + '0'; - return value - 10 + 'A'; -} - - -bool Bignum::ToHexString(char* buffer, int buffer_size) const { - ASSERT(IsClamped()); - // Each bigit must be printable as separate hex-character. - ASSERT(kBigitSize % 4 == 0); - const int kHexCharsPerBigit = kBigitSize / 4; - - if (used_digits_ == 0) { - if (buffer_size < 2) return false; - buffer[0] = '0'; - buffer[1] = '\0'; - return true; - } - // We add 1 for the terminating '\0' character. - int needed_chars = (BigitLength() - 1) * kHexCharsPerBigit + - SizeInHexChars(bigits_[used_digits_ - 1]) + 1; - if (needed_chars > buffer_size) return false; - int string_index = needed_chars - 1; - buffer[string_index--] = '\0'; - for (int i = 0; i < exponent_; ++i) { - for (int j = 0; j < kHexCharsPerBigit; ++j) { - buffer[string_index--] = '0'; - } - } - for (int i = 0; i < used_digits_ - 1; ++i) { - Chunk current_bigit = bigits_[i]; - for (int j = 0; j < kHexCharsPerBigit; ++j) { - buffer[string_index--] = HexCharOfValue(current_bigit & 0xF); - current_bigit >>= 4; - } - } - // And finally the last bigit. - Chunk most_significant_bigit = bigits_[used_digits_ - 1]; - while (most_significant_bigit != 0) { - buffer[string_index--] = HexCharOfValue(most_significant_bigit & 0xF); - most_significant_bigit >>= 4; - } - return true; -} - - -Bignum::Chunk Bignum::BigitAt(int index) const { - if (index >= BigitLength()) return 0; - if (index < exponent_) return 0; - return bigits_[index - exponent_]; -} - - -int Bignum::Compare(const Bignum& a, const Bignum& b) { - ASSERT(a.IsClamped()); - ASSERT(b.IsClamped()); - int bigit_length_a = a.BigitLength(); - int bigit_length_b = b.BigitLength(); - if (bigit_length_a < bigit_length_b) return -1; - if (bigit_length_a > bigit_length_b) return +1; - for (int i = bigit_length_a - 1; i >= Min(a.exponent_, b.exponent_); --i) { - Chunk bigit_a = a.BigitAt(i); - Chunk bigit_b = b.BigitAt(i); - if (bigit_a < bigit_b) return -1; - if (bigit_a > bigit_b) return +1; - // Otherwise they are equal up to this digit. Try the next digit. - } - return 0; -} - - -int Bignum::PlusCompare(const Bignum& a, const Bignum& b, const Bignum& c) { - ASSERT(a.IsClamped()); - ASSERT(b.IsClamped()); - ASSERT(c.IsClamped()); - if (a.BigitLength() < b.BigitLength()) { - return PlusCompare(b, a, c); - } - if (a.BigitLength() + 1 < c.BigitLength()) return -1; - if (a.BigitLength() > c.BigitLength()) return +1; - // The exponent encodes 0-bigits. So if there are more 0-digits in 'a' than - // 'b' has digits, then the bigit-length of 'a'+'b' must be equal to the one - // of 'a'. - if (a.exponent_ >= b.BigitLength() && a.BigitLength() < c.BigitLength()) { - return -1; - } - - Chunk borrow = 0; - // Starting at min_exponent all digits are == 0. So no need to compare them. - int min_exponent = Min(Min(a.exponent_, b.exponent_), c.exponent_); - for (int i = c.BigitLength() - 1; i >= min_exponent; --i) { - Chunk chunk_a = a.BigitAt(i); - Chunk chunk_b = b.BigitAt(i); - Chunk chunk_c = c.BigitAt(i); - Chunk sum = chunk_a + chunk_b; - if (sum > chunk_c + borrow) { - return +1; - } else { - borrow = chunk_c + borrow - sum; - if (borrow > 1) return -1; - borrow <<= kBigitSize; - } - } - if (borrow == 0) return 0; - return -1; -} - - -void Bignum::Clamp() { - while (used_digits_ > 0 && bigits_[used_digits_ - 1] == 0) { - used_digits_--; - } - if (used_digits_ == 0) { - // Zero. - exponent_ = 0; - } -} - - -bool Bignum::IsClamped() const { - return used_digits_ == 0 || bigits_[used_digits_ - 1] != 0; -} - - -void Bignum::Zero() { - for (int i = 0; i < used_digits_; ++i) { - bigits_[i] = 0; - } - used_digits_ = 0; - exponent_ = 0; -} - - -void Bignum::Align(const Bignum& other) { - if (exponent_ > other.exponent_) { - // If "X" represents a "hidden" digit (by the exponent) then we are in the - // following case (a == this, b == other): - // a: aaaaaaXXXX or a: aaaaaXXX - // b: bbbbbbX b: bbbbbbbbXX - // We replace some of the hidden digits (X) of a with 0 digits. - // a: aaaaaa000X or a: aaaaa0XX - int zero_digits = exponent_ - other.exponent_; - EnsureCapacity(used_digits_ + zero_digits); - for (int i = used_digits_ - 1; i >= 0; --i) { - bigits_[i + zero_digits] = bigits_[i]; - } - for (int i = 0; i < zero_digits; ++i) { - bigits_[i] = 0; - } - used_digits_ += zero_digits; - exponent_ -= zero_digits; - ASSERT(used_digits_ >= 0); - ASSERT(exponent_ >= 0); - } -} - - -void Bignum::BigitsShiftLeft(int shift_amount) { - ASSERT(shift_amount < kBigitSize); - ASSERT(shift_amount >= 0); - Chunk carry = 0; - for (int i = 0; i < used_digits_; ++i) { - Chunk new_carry = bigits_[i] >> (kBigitSize - shift_amount); - bigits_[i] = ((bigits_[i] << shift_amount) + carry) & kBigitMask; - carry = new_carry; - } - if (carry != 0) { - bigits_[used_digits_] = carry; - used_digits_++; - } -} - - -void Bignum::SubtractTimes(const Bignum& other, int factor) { - ASSERT(exponent_ <= other.exponent_); - if (factor < 3) { - for (int i = 0; i < factor; ++i) { - SubtractBignum(other); - } - return; - } - Chunk borrow = 0; - int exponent_diff = other.exponent_ - exponent_; - for (int i = 0; i < other.used_digits_; ++i) { - DoubleChunk product = static_cast(factor) * other.bigits_[i]; - DoubleChunk remove = borrow + product; - Chunk difference = bigits_[i + exponent_diff] - (remove & kBigitMask); - bigits_[i + exponent_diff] = difference & kBigitMask; - borrow = static_cast((difference >> (kChunkSize - 1)) + - (remove >> kBigitSize)); - } - for (int i = other.used_digits_ + exponent_diff; i < used_digits_; ++i) { - if (borrow == 0) return; - Chunk difference = bigits_[i] - borrow; - bigits_[i] = difference & kBigitMask; - borrow = difference >> (kChunkSize - 1); - ++i; - } - Clamp(); -} - - -} } // namespace v8::internal diff --git a/deps/v8/src/bignum.h b/deps/v8/src/bignum.h deleted file mode 100644 index 1d2bff61a5..0000000000 --- a/deps/v8/src/bignum.h +++ /dev/null @@ -1,140 +0,0 @@ -// 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_BIGNUM_H_ -#define V8_BIGNUM_H_ - -namespace v8 { -namespace internal { - -class Bignum { - public: - // 3584 = 128 * 28. We can represent 2^3584 > 10^1000 accurately. - // This bignum can encode much bigger numbers, since it contains an - // exponent. - static const int kMaxSignificantBits = 3584; - - Bignum(); - void AssignUInt16(uint16_t value); - void AssignUInt64(uint64_t value); - void AssignBignum(const Bignum& other); - - void AssignDecimalString(Vector value); - void AssignHexString(Vector value); - - void AssignPowerUInt16(uint16_t base, int exponent); - - void AddUInt16(uint16_t operand); - void AddUInt64(uint64_t operand); - void AddBignum(const Bignum& other); - // Precondition: this >= other. - void SubtractBignum(const Bignum& other); - - void Square(); - void ShiftLeft(int shift_amount); - void MultiplyByUInt32(uint32_t factor); - void MultiplyByUInt64(uint64_t factor); - void MultiplyByPowerOfTen(int exponent); - void Times10() { return MultiplyByUInt32(10); } - // Pseudocode: - // int result = this / other; - // this = this % other; - // In the worst case this function is in O(this/other). - uint16_t DivideModuloIntBignum(const Bignum& other); - - bool ToHexString(char* buffer, int buffer_size) const; - - static int Compare(const Bignum& a, const Bignum& b); - static bool Equal(const Bignum& a, const Bignum& b) { - return Compare(a, b) == 0; - } - static bool LessEqual(const Bignum& a, const Bignum& b) { - return Compare(a, b) <= 0; - } - static bool Less(const Bignum& a, const Bignum& b) { - return Compare(a, b) < 0; - } - // Returns Compare(a + b, c); - static int PlusCompare(const Bignum& a, const Bignum& b, const Bignum& c); - // Returns a + b == c - static bool PlusEqual(const Bignum& a, const Bignum& b, const Bignum& c) { - return PlusCompare(a, b, c) == 0; - } - // Returns a + b <= c - static bool PlusLessEqual(const Bignum& a, const Bignum& b, const Bignum& c) { - return PlusCompare(a, b, c) <= 0; - } - // Returns a + b < c - static bool PlusLess(const Bignum& a, const Bignum& b, const Bignum& c) { - return PlusCompare(a, b, c) < 0; - } - private: - typedef uint32_t Chunk; - typedef uint64_t DoubleChunk; - - static const int kChunkSize = sizeof(Chunk) * 8; - static const int kDoubleChunkSize = sizeof(DoubleChunk) * 8; - // With bigit size of 28 we loose some bits, but a double still fits easily - // into two chunks, and more importantly we can use the Comba multiplication. - static const int kBigitSize = 28; - static const Chunk kBigitMask = (1 << kBigitSize) - 1; - // Every instance allocates kBigitLength chunks on the stack. Bignums cannot - // grow. There are no checks if the stack-allocated space is sufficient. - static const int kBigitCapacity = kMaxSignificantBits / kBigitSize; - - void EnsureCapacity(int size) { - if (size > kBigitCapacity) { - UNREACHABLE(); - } - } - void Align(const Bignum& other); - void Clamp(); - bool IsClamped() const; - void Zero(); - // Requires this to have enough capacity (no tests done). - // Updates used_digits_ if necessary. - // by must be < kBigitSize. - void BigitsShiftLeft(int shift_amount); - // BigitLength includes the "hidden" digits encoded in the exponent. - int BigitLength() const { return used_digits_ + exponent_; } - Chunk BigitAt(int index) const; - void SubtractTimes(const Bignum& other, int factor); - - Chunk bigits_buffer_[kBigitCapacity]; - // A vector backed by bigits_buffer_. This way accesses to the array are - // checked for out-of-bounds errors. - Vector bigits_; - int used_digits_; - // The Bignum's value equals value(bigits_) * 2^(exponent_ * kBigitSize). - int exponent_; - - DISALLOW_COPY_AND_ASSIGN(Bignum); -}; - -} } // namespace v8::internal - -#endif // V8_BIGNUM_H_ diff --git a/deps/v8/src/checks.cc b/deps/v8/src/checks.cc index 1ab8802ec3..b5df316d0f 100644 --- a/deps/v8/src/checks.cc +++ b/deps/v8/src/checks.cc @@ -98,12 +98,3 @@ void API_Fatal(const char* location, const char* format, ...) { i::OS::PrintError("\n#\n\n"); i::OS::Abort(); } - - -namespace v8 { namespace internal { - - bool EnableSlowAsserts() { return FLAG_enable_slow_asserts; } - - intptr_t HeapObjectTagMask() { return kHeapObjectTagMask; } - -} } // namespace v8::internal diff --git a/deps/v8/src/checks.h b/deps/v8/src/checks.h index e0704774ba..5ea59920ac 100644 --- a/deps/v8/src/checks.h +++ b/deps/v8/src/checks.h @@ -30,7 +30,7 @@ #include -#include "../include/v8stdint.h" +#include "flags.h" extern "C" void V8_Fatal(const char* file, int line, const char* format, ...); void API_Fatal(const char* location, const char* format, ...); @@ -279,12 +279,6 @@ template class StaticAssertionHelper { }; SEMI_STATIC_JOIN(__StaticAssertTypedef__, __LINE__) -namespace v8 { namespace internal { - -bool EnableSlowAsserts(); - -} } // namespace v8::internal - // The ASSERT macro is equivalent to CHECK except that it only // generates code in debug builds. #ifdef DEBUG @@ -293,7 +287,7 @@ bool EnableSlowAsserts(); #define ASSERT_EQ(v1, v2) CHECK_EQ(v1, v2) #define ASSERT_NE(v1, v2) CHECK_NE(v1, v2) #define ASSERT_GE(v1, v2) CHECK_GE(v1, v2) -#define SLOW_ASSERT(condition) if (EnableSlowAsserts()) CHECK(condition) +#define SLOW_ASSERT(condition) if (FLAG_enable_slow_asserts) CHECK(condition) #else #define ASSERT_RESULT(expr) (expr) #define ASSERT(condition) ((void) 0) @@ -309,16 +303,11 @@ bool EnableSlowAsserts(); // and release compilation modes behaviour. #define STATIC_ASSERT(test) STATIC_CHECK(test) -namespace v8 { namespace internal { - -intptr_t HeapObjectTagMask(); - -} } // namespace v8::internal #define ASSERT_TAG_ALIGNED(address) \ - ASSERT((reinterpret_cast(address) & HeapObjectTagMask()) == 0) + ASSERT((reinterpret_cast(address) & kHeapObjectTagMask) == 0) -#define ASSERT_SIZE_TAG_ALIGNED(size) ASSERT((size & HeapObjectTagMask()) == 0) +#define ASSERT_SIZE_TAG_ALIGNED(size) ASSERT((size & kHeapObjectTagMask) == 0) #define ASSERT_NOT_NULL(p) ASSERT_NE(NULL, p) diff --git a/deps/v8/src/code-stubs.h b/deps/v8/src/code-stubs.h index ec64353415..c0a8d3063c 100644 --- a/deps/v8/src/code-stubs.h +++ b/deps/v8/src/code-stubs.h @@ -542,7 +542,7 @@ class ApiGetterEntryStub : public CodeStub { ApiFunction* fun() { return fun_; } Major MajorKey() { return NoCache; } int MinorKey() { return 0; } - const char* GetName() { return "ApiGetterEntryStub"; } + const char* GetName() { return "ApiEntryStub"; } // The accessor info associated with the function. Handle info_; // The function to be called. @@ -550,32 +550,6 @@ class ApiGetterEntryStub : public CodeStub { }; -class ApiCallEntryStub : public CodeStub { - public: - ApiCallEntryStub(Handle info, - ApiFunction* fun) - : info_(info), - fun_(fun) { } - void Generate(MacroAssembler* masm); - virtual bool has_custom_cache() { return true; } - virtual bool GetCustomCache(Code** code_out); - virtual void SetCustomCache(Code* value); - - static const int kStackSpace = 0; - static const int kArgc = 5; - private: - Handle info() { return info_; } - ApiFunction* fun() { return fun_; } - Major MajorKey() { return NoCache; } - int MinorKey() { return 0; } - const char* GetName() { return "ApiCallEntryStub"; } - // The call handler info associated with the function. - Handle info_; - // The function to be called. - ApiFunction* fun_; -}; - - class JSEntryStub : public CodeStub { public: JSEntryStub() { } diff --git a/deps/v8/src/codegen.cc b/deps/v8/src/codegen.cc index e954dd66c1..bda697abaf 100644 --- a/deps/v8/src/codegen.cc +++ b/deps/v8/src/codegen.cc @@ -70,10 +70,9 @@ void CodeGenerator::ProcessDeferred() { DeferredCode* code = deferred_.RemoveLast(); ASSERT(masm_ == code->masm()); // Record position of deferred code stub. - masm_->positions_recorder()->RecordStatementPosition( - code->statement_position()); + masm_->RecordStatementPosition(code->statement_position()); if (code->position() != RelocInfo::kNoPosition) { - masm_->positions_recorder()->RecordPosition(code->position()); + masm_->RecordPosition(code->position()); } // Generate the code. Comment cmnt(masm_, code->comment()); @@ -403,10 +402,10 @@ bool CodeGenerator::RecordPositions(MacroAssembler* masm, int pos, bool right_here) { if (pos != RelocInfo::kNoPosition) { - masm->positions_recorder()->RecordStatementPosition(pos); - masm->positions_recorder()->RecordPosition(pos); + masm->RecordStatementPosition(pos); + masm->RecordPosition(pos); if (right_here) { - return masm->positions_recorder()->WriteRecordedPositions(); + return masm->WriteRecordedPositions(); } } return false; @@ -436,7 +435,7 @@ void CodeGenerator::CodeForDoWhileConditionPosition(DoWhileStatement* stmt) { void CodeGenerator::CodeForSourcePosition(int pos) { if (FLAG_debug_info && pos != RelocInfo::kNoPosition) { - masm()->positions_recorder()->RecordPosition(pos); + masm()->RecordPosition(pos); } } @@ -482,8 +481,8 @@ int CEntryStub::MinorKey() { } -// Implementation of CodeStub::GetCustomCache. -static bool GetCustomCacheHelper(Object* cache, Code** code_out) { +bool ApiGetterEntryStub::GetCustomCache(Code** code_out) { + Object* cache = info()->load_stub_cache(); if (cache->IsUndefined()) { return false; } else { @@ -493,24 +492,9 @@ static bool GetCustomCacheHelper(Object* cache, Code** code_out) { } -bool ApiGetterEntryStub::GetCustomCache(Code** code_out) { - return GetCustomCacheHelper(info()->load_stub_cache(), code_out); -} - - void ApiGetterEntryStub::SetCustomCache(Code* value) { info()->set_load_stub_cache(value); } -bool ApiCallEntryStub::GetCustomCache(Code** code_out) { - return GetCustomCacheHelper(info()->call_stub_cache(), code_out); -} - - -void ApiCallEntryStub::SetCustomCache(Code* value) { - info()->set_call_stub_cache(value); -} - - } } // namespace v8::internal diff --git a/deps/v8/src/compiler.cc b/deps/v8/src/compiler.cc index 29bbbc7034..6f02960dda 100755 --- a/deps/v8/src/compiler.cc +++ b/deps/v8/src/compiler.cc @@ -279,6 +279,7 @@ Handle Compiler::Compile(Handle source, // in that case too. ScriptDataImpl* pre_data = input_pre_data; if (pre_data == NULL + && FLAG_lazy && source_length >= FLAG_min_preparse_length) { pre_data = ParserApi::PartialPreParse(source, NULL, extension); } diff --git a/deps/v8/src/conversions.cc b/deps/v8/src/conversions.cc index 4cc6744850..790e807aef 100644 --- a/deps/v8/src/conversions.cc +++ b/deps/v8/src/conversions.cc @@ -816,7 +816,7 @@ const char* IntToCString(int n, Vector buffer) { char* DoubleToFixedCString(double value, int f) { - const int kMaxDigitsBeforePoint = 21; + const int kMaxDigitsBeforePoint = 20; const double kFirstNonFixed = 1e21; const int kMaxDigitsAfterPoint = 20; ASSERT(f >= 0); @@ -840,9 +840,9 @@ char* DoubleToFixedCString(double value, int f) { // Find a sufficiently precise decimal representation of n. int decimal_point; int sign; - // Add space for the '\0' byte. + // Add space for the '.' and the '\0' byte. const int kDecimalRepCapacity = - kMaxDigitsBeforePoint + kMaxDigitsAfterPoint + 1; + kMaxDigitsBeforePoint + kMaxDigitsAfterPoint + 2; char decimal_rep[kDecimalRepCapacity]; int decimal_rep_length; bool status = DoubleToAscii(value, DTOA_FIXED, f, diff --git a/deps/v8/src/debug-debugger.js b/deps/v8/src/debug-debugger.js index d091991a11..0eab8d1b83 100644 --- a/deps/v8/src/debug-debugger.js +++ b/deps/v8/src/debug-debugger.js @@ -897,6 +897,10 @@ ExecutionState.prototype.frame = function(opt_index) { return new FrameMirror(this.break_id, opt_index); }; +ExecutionState.prototype.cframesValue = function(opt_from_index, opt_to_index) { + return %GetCFrames(this.break_id); +}; + ExecutionState.prototype.setSelectedFrame = function(index) { var i = %ToNumber(index); if (i < 0 || i >= this.frameCount()) throw new Error('Illegal frame index.'); @@ -1747,6 +1751,11 @@ DebugCommandProcessor.prototype.backtraceRequest_ = function(request, response) }; +DebugCommandProcessor.prototype.backtracec = function(cmd, args) { + return this.exec_state_.cframesValue(); +}; + + DebugCommandProcessor.prototype.frameRequest_ = function(request, response) { // No frames no source. if (this.exec_state_.frameCount() == 0) { @@ -2196,6 +2205,29 @@ function NumberToHex8Str(n) { return r; }; +DebugCommandProcessor.prototype.formatCFrames = function(cframes_value) { + var result = ""; + if (cframes_value == null || cframes_value.length == 0) { + result += "(stack empty)"; + } else { + for (var i = 0; i < cframes_value.length; ++i) { + if (i != 0) result += "\n"; + result += this.formatCFrame(cframes_value[i]); + } + } + return result; +}; + + +DebugCommandProcessor.prototype.formatCFrame = function(cframe_value) { + var result = ""; + result += "0x" + NumberToHex8Str(cframe_value.address); + if (!IS_UNDEFINED(cframe_value.text)) { + result += " " + cframe_value.text; + } + return result; +} + /** * Convert an Object to its debugger protocol representation. The representation diff --git a/deps/v8/src/debug.cc b/deps/v8/src/debug.cc index f3bf954da9..24f0409861 100644 --- a/deps/v8/src/debug.cc +++ b/deps/v8/src/debug.cc @@ -1839,7 +1839,6 @@ bool Debug::IsDebugGlobal(GlobalObject* global) { void Debug::ClearMirrorCache() { - PostponeInterruptsScope postpone; HandleScope scope; ASSERT(Top::context() == *Debug::debug_context()); diff --git a/deps/v8/src/double.h b/deps/v8/src/double.h index 65eded9989..e805173e07 100644 --- a/deps/v8/src/double.h +++ b/deps/v8/src/double.h @@ -54,20 +54,18 @@ class Double { explicit Double(DiyFp diy_fp) : d64_(DiyFpToUint64(diy_fp)) {} - // The value encoded by this Double must be greater or equal to +0.0. - // It must not be special (infinity, or NaN). DiyFp AsDiyFp() const { - ASSERT(Sign() > 0); ASSERT(!IsSpecial()); return DiyFp(Significand(), Exponent()); } - // The value encoded by this Double must be strictly greater than 0. + // this->Significand() must not be 0. DiyFp AsNormalizedDiyFp() const { - ASSERT(value() > 0.0); uint64_t f = Significand(); int e = Exponent(); + ASSERT(f != 0); + // The current double could be a denormal. while ((f & kHiddenBit) == 0) { f <<= 1; @@ -84,20 +82,6 @@ class Double { return d64_; } - // Returns the next greater double. Returns +infinity on input +infinity. - double NextDouble() const { - if (d64_ == kInfinity) return Double(kInfinity).value(); - if (Sign() < 0 && Significand() == 0) { - // -0.0 - return 0.0; - } - if (Sign() < 0) { - return Double(d64_ - 1).value(); - } else { - return Double(d64_ + 1).value(); - } - } - int Exponent() const { if (IsDenormal()) return kDenormalExponent; @@ -136,30 +120,24 @@ class Double { ((d64 & kSignificandMask) != 0); } + bool IsInfinite() const { uint64_t d64 = AsUint64(); return ((d64 & kExponentMask) == kExponentMask) && ((d64 & kSignificandMask) == 0); } + int Sign() const { uint64_t d64 = AsUint64(); return (d64 & kSignMask) == 0? 1: -1; } - // Precondition: the value encoded by this Double must be greater or equal - // than +0.0. - DiyFp UpperBoundary() const { - ASSERT(Sign() > 0); - return DiyFp(Significand() * 2 + 1, Exponent() - 1); - } // Returns the two boundaries of this. // The bigger boundary (m_plus) is normalized. The lower boundary has the same // exponent as m_plus. - // Precondition: the value encoded by this Double must be greater than 0. void NormalizedBoundaries(DiyFp* out_m_minus, DiyFp* out_m_plus) const { - ASSERT(value() > 0.0); DiyFp v = this->AsDiyFp(); bool significand_is_zero = (v.f() == kHiddenBit); DiyFp m_plus = DiyFp::Normalize(DiyFp((v.f() << 1) + 1, v.e() - 1)); diff --git a/deps/v8/src/flag-definitions.h b/deps/v8/src/flag-definitions.h index 46feea77ac..54501ec95d 100644 --- a/deps/v8/src/flag-definitions.h +++ b/deps/v8/src/flag-definitions.h @@ -186,7 +186,6 @@ DEFINE_bool(always_inline_smi_code, false, // heap.cc DEFINE_int(max_new_space_size, 0, "max size of the new generation (in kBytes)") DEFINE_int(max_old_space_size, 0, "max size of the old generation (in Mbytes)") -DEFINE_int(max_executable_size, 0, "max size of executable memory (in Mbytes)") DEFINE_bool(gc_global, false, "always perform global GCs") DEFINE_int(gc_interval, -1, "garbage collect after allocations") DEFINE_bool(trace_gc, false, diff --git a/deps/v8/src/full-codegen.cc b/deps/v8/src/full-codegen.cc index c770e189b3..97987c27a8 100644 --- a/deps/v8/src/full-codegen.cc +++ b/deps/v8/src/full-codegen.cc @@ -563,10 +563,9 @@ void FullCodeGenerator::SetStatementPosition(int pos) { } -void FullCodeGenerator::SetSourcePosition( - int pos, PositionRecordingType recording_type) { +void FullCodeGenerator::SetSourcePosition(int pos) { if (FLAG_debug_info && pos != RelocInfo::kNoPosition) { - masm_->positions_recorder()->RecordPosition(pos, recording_type); + masm_->RecordPosition(pos); } } @@ -1226,6 +1225,13 @@ int FullCodeGenerator::TryCatch::Exit(int stack_depth) { } +void FullCodeGenerator::EmitRegExpCloneResult(ZoneList* args) { + ASSERT(args->length() == 1); + VisitForStackValue(args->at(0)); + __ CallRuntime(Runtime::kRegExpCloneResult, 1); + context()->Plug(result_register()); +} + #undef __ diff --git a/deps/v8/src/full-codegen.h b/deps/v8/src/full-codegen.h index a3270aa774..201507b2af 100644 --- a/deps/v8/src/full-codegen.h +++ b/deps/v8/src/full-codegen.h @@ -423,9 +423,7 @@ class FullCodeGenerator: public AstVisitor { void SetStatementPosition(Statement* stmt); void SetExpressionPosition(Expression* expr, int pos); void SetStatementPosition(int pos); - void SetSourcePosition( - int pos, - PositionRecordingType recording_type = NORMAL_POSITION); + void SetSourcePosition(int pos); // Non-local control flow support. void EnterFinallyBlock(); diff --git a/deps/v8/src/global-handles.cc b/deps/v8/src/global-handles.cc index 5339840988..9ede908528 100644 --- a/deps/v8/src/global-handles.cc +++ b/deps/v8/src/global-handles.cc @@ -372,14 +372,13 @@ void GlobalHandles::IdentifyWeakHandles(WeakSlotCallback f) { int post_gc_processing_count = 0; -bool GlobalHandles::PostGarbageCollectionProcessing() { +void GlobalHandles::PostGarbageCollectionProcessing() { // Process weak global handle callbacks. This must be done after the // GC is completely done, because the callbacks may invoke arbitrary // API functions. // At the same time deallocate all DESTROYED nodes. ASSERT(Heap::gc_state() == Heap::NOT_IN_GC); const int initial_post_gc_processing_count = ++post_gc_processing_count; - bool next_gc_likely_to_collect_more = false; Node** p = &head_; while (*p != NULL) { if ((*p)->PostGarbageCollectionProcessing()) { @@ -400,7 +399,6 @@ bool GlobalHandles::PostGarbageCollectionProcessing() { } node->set_next_free(first_deallocated()); set_first_deallocated(node); - next_gc_likely_to_collect_more = true; } else { p = (*p)->next_addr(); } @@ -409,8 +407,6 @@ bool GlobalHandles::PostGarbageCollectionProcessing() { if (first_deallocated()) { first_deallocated()->set_next(head()); } - - return next_gc_likely_to_collect_more; } diff --git a/deps/v8/src/global-handles.h b/deps/v8/src/global-handles.h index 37b2b44522..659f86eca7 100644 --- a/deps/v8/src/global-handles.h +++ b/deps/v8/src/global-handles.h @@ -96,8 +96,7 @@ class GlobalHandles : public AllStatic { static bool IsWeak(Object** location); // Process pending weak handles. - // Returns true if next major GC is likely to collect more garbage. - static bool PostGarbageCollectionProcessing(); + static void PostGarbageCollectionProcessing(); // Iterates over all strong handles. static void IterateStrongRoots(ObjectVisitor* v); diff --git a/deps/v8/src/globals.h b/deps/v8/src/globals.h index a74b6c7930..c218f80dc1 100644 --- a/deps/v8/src/globals.h +++ b/deps/v8/src/globals.h @@ -193,9 +193,10 @@ const uint32_t kMaxUInt32 = 0xFFFFFFFFu; const int kCharSize = sizeof(char); // NOLINT const int kShortSize = sizeof(short); // NOLINT +const int kIntSize = sizeof(int); // NOLINT const int kDoubleSize = sizeof(double); // NOLINT +const int kPointerSize = sizeof(void*); // NOLINT const int kIntptrSize = sizeof(intptr_t); // NOLINT -// kIntSize and kPointerSize are defined in include/v8.h. #if V8_HOST_ARCH_64_BIT const int kPointerSizeLog2 = 3; diff --git a/deps/v8/src/heap-inl.h b/deps/v8/src/heap-inl.h index ba50c0f735..15feb9d5fb 100644 --- a/deps/v8/src/heap-inl.h +++ b/deps/v8/src/heap-inl.h @@ -330,11 +330,6 @@ void Heap::ScavengeObject(HeapObject** p, HeapObject* object) { } -bool Heap::CollectGarbage(AllocationSpace space) { - return CollectGarbage(space, SelectGarbageCollector(space)); -} - - MaybeObject* Heap::PrepareForCompare(String* str) { // Always flatten small strings and force flattening of long strings // after we have accumulated a certain amount we failed to flatten. @@ -418,7 +413,7 @@ void Heap::SetLastScriptId(Object* last_script_id) { } \ if (!__maybe_object__->IsRetryAfterGC()) RETURN_EMPTY; \ Counters::gc_last_resort_from_handles.Increment(); \ - Heap::CollectAllAvailableGarbage(); \ + Heap::CollectAllGarbage(false); \ { \ AlwaysAllocateScope __scope__; \ __maybe_object__ = FUNCTION_CALL; \ diff --git a/deps/v8/src/heap.cc b/deps/v8/src/heap.cc index 134f40e507..b037efd804 100644 --- a/deps/v8/src/heap.cc +++ b/deps/v8/src/heap.cc @@ -83,19 +83,16 @@ int Heap::max_semispace_size_ = 2*MB; intptr_t Heap::max_old_generation_size_ = 192*MB; int Heap::initial_semispace_size_ = 128*KB; intptr_t Heap::code_range_size_ = 0; -intptr_t Heap::max_executable_size_ = max_old_generation_size_; #elif defined(V8_TARGET_ARCH_X64) int Heap::max_semispace_size_ = 16*MB; intptr_t Heap::max_old_generation_size_ = 1*GB; int Heap::initial_semispace_size_ = 1*MB; intptr_t Heap::code_range_size_ = 512*MB; -intptr_t Heap::max_executable_size_ = 256*MB; #else int Heap::max_semispace_size_ = 8*MB; intptr_t Heap::max_old_generation_size_ = 512*MB; int Heap::initial_semispace_size_ = 512*KB; intptr_t Heap::code_range_size_ = 0; -intptr_t Heap::max_executable_size_ = 128*MB; #endif // The snapshot semispace size will be the default semispace size if @@ -175,12 +172,6 @@ intptr_t Heap::CommittedMemory() { lo_space_->Size(); } -intptr_t Heap::CommittedMemoryExecutable() { - if (!HasBeenSetup()) return 0; - - return MemoryAllocator::SizeExecutable(); -} - intptr_t Heap::Available() { if (!HasBeenSetup()) return 0; @@ -438,31 +429,7 @@ void Heap::CollectAllGarbage(bool force_compaction) { } -void Heap::CollectAllAvailableGarbage() { - // Since we are ignoring the return value, the exact choice of space does - // not matter, so long as we do not specify NEW_SPACE, which would not - // cause a full GC. - MarkCompactCollector::SetForceCompaction(true); - - // Major GC would invoke weak handle callbacks on weakly reachable - // handles, but won't collect weakly reachable objects until next - // major GC. Therefore if we collect aggressively and weak handle callback - // has been invoked, we rerun major GC to release objects which become - // garbage. - // Note: as weak callbacks can execute arbitrary code, we cannot - // hope that eventually there will be no weak callbacks invocations. - // Therefore stop recollecting after several attempts. - const int kMaxNumberOfAttempts = 7; - for (int attempt = 0; attempt < kMaxNumberOfAttempts; attempt++) { - if (!CollectGarbage(OLD_POINTER_SPACE, MARK_COMPACTOR)) { - break; - } - } - MarkCompactCollector::SetForceCompaction(false); -} - - -bool Heap::CollectGarbage(AllocationSpace space, GarbageCollector collector) { +void Heap::CollectGarbage(AllocationSpace space) { // The VM is in the GC state until exiting this function. VMState state(GC); @@ -475,14 +442,13 @@ bool Heap::CollectGarbage(AllocationSpace space, GarbageCollector collector) { allocation_timeout_ = Max(6, FLAG_gc_interval); #endif - bool next_gc_likely_to_collect_more = false; - { GCTracer tracer; GarbageCollectionPrologue(); // The GC count was incremented in the prologue. Tell the tracer about // it. tracer.set_gc_count(gc_count_); + GarbageCollector collector = SelectGarbageCollector(space); // Tell the tracer which collector we've selected. tracer.set_collector(collector); @@ -490,8 +456,7 @@ bool Heap::CollectGarbage(AllocationSpace space, GarbageCollector collector) { ? &Counters::gc_scavenger : &Counters::gc_compactor; rate->Start(); - next_gc_likely_to_collect_more = - PerformGarbageCollection(collector, &tracer); + PerformGarbageCollection(collector, &tracer); rate->Stop(); GarbageCollectionEpilogue(); @@ -502,8 +467,6 @@ bool Heap::CollectGarbage(AllocationSpace space, GarbageCollector collector) { if (FLAG_log_gc) HeapProfiler::WriteSample(); if (CpuProfiler::is_profiling()) CpuProfiler::ProcessMovedFunctions(); #endif - - return next_gc_likely_to_collect_more; } @@ -690,10 +653,8 @@ void Heap::UpdateSurvivalRateTrend(int start_new_space_size) { survival_rate_ = survival_rate; } -bool Heap::PerformGarbageCollection(GarbageCollector collector, +void Heap::PerformGarbageCollection(GarbageCollector collector, GCTracer* tracer) { - bool next_gc_likely_to_collect_more = false; - if (collector != SCAVENGER) { PROFILE(CodeMovingGCEvent()); } @@ -759,8 +720,7 @@ bool Heap::PerformGarbageCollection(GarbageCollector collector, if (collector == MARK_COMPACTOR) { DisableAssertNoAllocation allow_allocation; GCTracer::Scope scope(tracer, GCTracer::Scope::EXTERNAL); - next_gc_likely_to_collect_more = - GlobalHandles::PostGarbageCollectionProcessing(); + GlobalHandles::PostGarbageCollectionProcessing(); } // Update relocatables. @@ -787,8 +747,6 @@ bool Heap::PerformGarbageCollection(GarbageCollector collector, global_gc_epilogue_callback_(); } VerifySymbolTable(); - - return next_gc_likely_to_collect_more; } @@ -4322,9 +4280,7 @@ static bool heap_configured = false; // TODO(1236194): Since the heap size is configurable on the command line // and through the API, we should gracefully handle the case that the heap // size is not big enough to fit all the initial objects. -bool Heap::ConfigureHeap(int max_semispace_size, - int max_old_gen_size, - int max_executable_size) { +bool Heap::ConfigureHeap(int max_semispace_size, int max_old_gen_size) { if (HasBeenSetup()) return false; if (max_semispace_size > 0) max_semispace_size_ = max_semispace_size; @@ -4345,15 +4301,6 @@ bool Heap::ConfigureHeap(int max_semispace_size, } if (max_old_gen_size > 0) max_old_generation_size_ = max_old_gen_size; - if (max_executable_size > 0) { - max_executable_size_ = RoundUp(max_executable_size, Page::kPageSize); - } - - // The max executable size must be less than or equal to the max old - // generation size. - if (max_executable_size_ > max_old_generation_size_) { - max_executable_size_ = max_old_generation_size_; - } // The new space size must be a power of two to support single-bit testing // for containment. @@ -4371,9 +4318,8 @@ bool Heap::ConfigureHeap(int max_semispace_size, bool Heap::ConfigureHeapDefault() { - return ConfigureHeap(FLAG_max_new_space_size / 2 * KB, - FLAG_max_old_space_size * MB, - FLAG_max_executable_size * MB); + return ConfigureHeap( + FLAG_max_new_space_size * (KB / 2), FLAG_max_old_space_size * MB); } @@ -4456,7 +4402,7 @@ bool Heap::Setup(bool create_heap_objects) { // space. The chunk is double the size of the requested reserved // new space size to ensure that we can find a pair of semispaces that // are contiguous and aligned to their size. - if (!MemoryAllocator::Setup(MaxReserved(), MaxExecutableSize())) return false; + if (!MemoryAllocator::Setup(MaxReserved())) return false; void* chunk = MemoryAllocator::ReserveInitialChunk(4 * reserved_semispace_size_); if (chunk == NULL) return false; diff --git a/deps/v8/src/heap.h b/deps/v8/src/heap.h index c37ced3939..8ff2f5f341 100644 --- a/deps/v8/src/heap.h +++ b/deps/v8/src/heap.h @@ -222,9 +222,7 @@ class Heap : public AllStatic { public: // Configure heap size before setup. Return false if the heap has been // setup already. - static bool ConfigureHeap(int max_semispace_size, - int max_old_gen_size, - int max_executable_size); + static bool ConfigureHeap(int max_semispace_size, int max_old_gen_size); static bool ConfigureHeapDefault(); // Initializes the global object heap. If create_heap_objects is true, @@ -255,7 +253,6 @@ class Heap : public AllStatic { static int ReservedSemiSpaceSize() { return reserved_semispace_size_; } static int InitialSemiSpaceSize() { return initial_semispace_size_; } static intptr_t MaxOldGenerationSize() { return max_old_generation_size_; } - static intptr_t MaxExecutableSize() { return max_executable_size_; } // Returns the capacity of the heap in bytes w/o growing. Heap grows when // more spaces are needed until it reaches the limit. @@ -264,9 +261,6 @@ class Heap : public AllStatic { // Returns the amount of memory currently committed for the heap. static intptr_t CommittedMemory(); - // Returns the amount of executable memory currently committed for the heap. - static intptr_t CommittedMemoryExecutable(); - // Returns the available bytes in space w/o growing. // Heap doesn't guarantee that it can allocate an object that requires // all available bytes. Check MaxHeapObjectSize() instead. @@ -711,22 +705,13 @@ class Heap : public AllStatic { static void GarbageCollectionEpilogue(); // Performs garbage collection operation. - // Returns whether there is a chance that another major GC could - // collect more garbage. - static bool CollectGarbage(AllocationSpace space, GarbageCollector collector); - - // Performs garbage collection operation. - // Returns whether there is a chance that another major GC could - // collect more garbage. - inline static bool CollectGarbage(AllocationSpace space); + // Returns whether required_space bytes are available after the collection. + static void CollectGarbage(AllocationSpace space); // Performs a full garbage collection. Force compaction if the // parameter is true. static void CollectAllGarbage(bool force_compaction); - // Last hope GC, should try to squeeze as much as possible. - static void CollectAllAvailableGarbage(); - // Notify the heap that a context has been disposed. static int NotifyContextDisposed() { return ++contexts_disposed_; } @@ -1102,7 +1087,6 @@ class Heap : public AllStatic { static int max_semispace_size_; static int initial_semispace_size_; static intptr_t max_old_generation_size_; - static intptr_t max_executable_size_; static intptr_t code_range_size_; // For keeping track of how much data has survived @@ -1262,9 +1246,7 @@ class Heap : public AllStatic { static GarbageCollector SelectGarbageCollector(AllocationSpace space); // Performs garbage collection - // Returns whether there is a chance another major GC could - // collect more garbage. - static bool PerformGarbageCollection(GarbageCollector collector, + static void PerformGarbageCollection(GarbageCollector collector, GCTracer* tracer); // Allocate an uninitialized object in map space. The behavior is identical diff --git a/deps/v8/src/ia32/assembler-ia32.cc b/deps/v8/src/ia32/assembler-ia32.cc index 125f503bec..019f478adc 100644 --- a/deps/v8/src/ia32/assembler-ia32.cc +++ b/deps/v8/src/ia32/assembler-ia32.cc @@ -298,8 +298,7 @@ static void InitCoverageLog(); // Spare buffer. byte* Assembler::spare_buffer_ = NULL; -Assembler::Assembler(void* buffer, int buffer_size) - : positions_recorder_(this) { +Assembler::Assembler(void* buffer, int buffer_size) { if (buffer == NULL) { // Do our own buffer management. if (buffer_size <= kMinimalBufferSize) { @@ -340,6 +339,10 @@ Assembler::Assembler(void* buffer, int buffer_size) reloc_info_writer.Reposition(buffer_ + buffer_size, pc_); last_pc_ = NULL; + current_statement_position_ = RelocInfo::kNoPosition; + current_position_ = RelocInfo::kNoPosition; + written_statement_position_ = current_statement_position_; + written_position_ = current_position_; #ifdef GENERATED_CODE_COVERAGE InitCoverageLog(); #endif @@ -1578,7 +1581,7 @@ void Assembler::call(const Operand& adr) { void Assembler::call(Handle code, RelocInfo::Mode rmode) { - positions_recorder()->WriteRecordedPositions(); + WriteRecordedPositions(); EnsureSpace ensure_space(this); last_pc_ = pc_; ASSERT(RelocInfo::IsCodeTarget(rmode)); @@ -2461,14 +2464,14 @@ void Assembler::Print() { void Assembler::RecordJSReturn() { - positions_recorder()->WriteRecordedPositions(); + WriteRecordedPositions(); EnsureSpace ensure_space(this); RecordRelocInfo(RelocInfo::JS_RETURN); } void Assembler::RecordDebugBreakSlot() { - positions_recorder()->WriteRecordedPositions(); + WriteRecordedPositions(); EnsureSpace ensure_space(this); RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT); } @@ -2482,6 +2485,47 @@ void Assembler::RecordComment(const char* msg) { } +void Assembler::RecordPosition(int pos) { + ASSERT(pos != RelocInfo::kNoPosition); + ASSERT(pos >= 0); + current_position_ = pos; +} + + +void Assembler::RecordStatementPosition(int pos) { + ASSERT(pos != RelocInfo::kNoPosition); + ASSERT(pos >= 0); + current_statement_position_ = pos; +} + + +bool Assembler::WriteRecordedPositions() { + bool written = false; + + // Write the statement position if it is different from what was written last + // time. + if (current_statement_position_ != written_statement_position_) { + EnsureSpace ensure_space(this); + RecordRelocInfo(RelocInfo::STATEMENT_POSITION, current_statement_position_); + written_statement_position_ = current_statement_position_; + written = true; + } + + // Write the position if it is different from what was written last time and + // also different from the written statement position. + if (current_position_ != written_position_ && + current_position_ != written_statement_position_) { + EnsureSpace ensure_space(this); + RecordRelocInfo(RelocInfo::POSITION, current_position_); + written_position_ = current_position_; + written = true; + } + + // Return whether something was written. + return written; +} + + void Assembler::GrowBuffer() { ASSERT(overflow()); if (!own_buffer_) FATAL("external code buffer is too small"); diff --git a/deps/v8/src/ia32/assembler-ia32.h b/deps/v8/src/ia32/assembler-ia32.h index 79637a1901..5286788fa7 100644 --- a/deps/v8/src/ia32/assembler-ia32.h +++ b/deps/v8/src/ia32/assembler-ia32.h @@ -521,6 +521,7 @@ class Assembler : public Malloced { void push(const Immediate& x); void push(Register src); void push(const Operand& src); + void push(Label* label, RelocInfo::Mode relocation_mode); void pop(Register dst); void pop(const Operand& dst); @@ -846,11 +847,17 @@ class Assembler : public Malloced { // Use --debug_code to enable. void RecordComment(const char* msg); + void RecordPosition(int pos); + void RecordStatementPosition(int pos); + bool WriteRecordedPositions(); + // Writes a single word of data in the code stream. // Used for inline tables, e.g., jump-tables. void dd(uint32_t data, RelocInfo::Mode reloc_info); int pc_offset() const { return pc_ - buffer_; } + int current_statement_position() const { return current_statement_position_; } + int current_position() const { return current_position_; } // Check if there is less than kGap bytes available in the buffer. // If this is the case, we need to grow the buffer before emitting @@ -862,8 +869,6 @@ class Assembler : public Malloced { static bool IsNop(Address addr) { return *addr == 0x90; } - PositionsRecorder* positions_recorder() { return &positions_recorder_; } - // Avoid overflows for displacements etc. static const int kMaximalBufferSize = 512*MB; static const int kMinimalBufferSize = 4*KB; @@ -942,9 +947,11 @@ class Assembler : public Malloced { // push-pop elimination byte* last_pc_; - PositionsRecorder positions_recorder_; - - friend class PositionsRecorder; + // source position information + int current_statement_position_; + int current_position_; + int written_statement_position_; + int written_position_; }; diff --git a/deps/v8/src/ia32/code-stubs-ia32.cc b/deps/v8/src/ia32/code-stubs-ia32.cc index a7d658bdce..b2b73926b9 100644 --- a/deps/v8/src/ia32/code-stubs-ia32.cc +++ b/deps/v8/src/ia32/code-stubs-ia32.cc @@ -3067,26 +3067,6 @@ void ApiGetterEntryStub::Generate(MacroAssembler* masm) { } -void ApiCallEntryStub::Generate(MacroAssembler* masm) { - __ PrepareCallApiFunction(kStackSpace, kArgc); - STATIC_ASSERT(kArgc == 5); - - // Allocate the v8::Arguments structure in the arguments' space since - // it's not controlled by GC. - __ mov(ApiParameterOperand(1), eax); // v8::Arguments::implicit_args_. - __ mov(ApiParameterOperand(2), ebx); // v8::Arguments::values_. - __ mov(ApiParameterOperand(3), edx); // v8::Arguments::length_. - // v8::Arguments::is_construct_call_. - __ mov(ApiParameterOperand(4), Immediate(0)); - - // v8::InvocationCallback's argument. - __ lea(eax, ApiParameterOperand(1)); - __ mov(ApiParameterOperand(0), eax); - - __ CallApiFunctionAndReturn(fun(), kArgc); -} - - void CEntryStub::GenerateCore(MacroAssembler* masm, Label* throw_normal_exception, Label* throw_termination_exception, diff --git a/deps/v8/src/ia32/codegen-ia32.cc b/deps/v8/src/ia32/codegen-ia32.cc index 6f4ef87e85..6d23dd7df9 100644 --- a/deps/v8/src/ia32/codegen-ia32.cc +++ b/deps/v8/src/ia32/codegen-ia32.cc @@ -3734,7 +3734,7 @@ void CodeGenerator::VisitReturnStatement(ReturnStatement* node) { CodeForStatementPosition(node); Load(node->expression()); Result return_value = frame_->Pop(); - masm()->positions_recorder()->WriteRecordedPositions(); + masm()->WriteRecordedPositions(); if (function_return_is_shadowed_) { function_return_.Jump(&return_value); } else { @@ -7292,6 +7292,88 @@ void CodeGenerator::GenerateRegExpConstructResult(ZoneList* args) { } +void CodeGenerator::GenerateRegExpCloneResult(ZoneList* args) { + ASSERT_EQ(1, args->length()); + + Load(args->at(0)); + Result object_result = frame_->Pop(); + object_result.ToRegister(eax); + object_result.Unuse(); + { + VirtualFrame::SpilledScope spilled_scope; + + Label done; + + __ test(eax, Immediate(kSmiTagMask)); + __ j(zero, &done); + + // Load JSRegExpResult map into edx. + // Arguments to this function should be results of calling RegExp exec, + // which is either an unmodified JSRegExpResult or null. Anything not having + // the unmodified JSRegExpResult map is returned unmodified. + // This also ensures that elements are fast. + __ mov(edx, ContextOperand(esi, Context::GLOBAL_INDEX)); + __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalContextOffset)); + __ mov(edx, ContextOperand(edx, Context::REGEXP_RESULT_MAP_INDEX)); + __ cmp(edx, FieldOperand(eax, HeapObject::kMapOffset)); + __ j(not_equal, &done); + + if (FLAG_debug_code) { + // Check that object really has empty properties array, as the map + // should guarantee. + __ cmp(FieldOperand(eax, JSObject::kPropertiesOffset), + Immediate(Factory::empty_fixed_array())); + __ Check(equal, "JSRegExpResult: default map but non-empty properties."); + } + + DeferredAllocateInNewSpace* allocate_fallback = + new DeferredAllocateInNewSpace(JSRegExpResult::kSize, + ebx, + edx.bit() | eax.bit()); + + // All set, copy the contents to a new object. + __ AllocateInNewSpace(JSRegExpResult::kSize, + ebx, + ecx, + no_reg, + allocate_fallback->entry_label(), + TAG_OBJECT); + __ bind(allocate_fallback->exit_label()); + + // Copy all fields from eax to ebx. + STATIC_ASSERT(JSRegExpResult::kSize % (2 * kPointerSize) == 0); + // There is an even number of fields, so unroll the loop once + // for efficiency. + for (int i = 0; i < JSRegExpResult::kSize; i += 2 * kPointerSize) { + STATIC_ASSERT(JSObject::kMapOffset % (2 * kPointerSize) == 0); + if (i != JSObject::kMapOffset) { + // The map was already loaded into edx. + __ mov(edx, FieldOperand(eax, i)); + } + __ mov(ecx, FieldOperand(eax, i + kPointerSize)); + + STATIC_ASSERT(JSObject::kElementsOffset % (2 * kPointerSize) == 0); + if (i == JSObject::kElementsOffset) { + // If the elements array isn't empty, make it copy-on-write + // before copying it. + Label empty; + __ cmp(Operand(edx), Immediate(Factory::empty_fixed_array())); + __ j(equal, &empty); + __ mov(FieldOperand(edx, HeapObject::kMapOffset), + Immediate(Factory::fixed_cow_array_map())); + __ bind(&empty); + } + __ mov(FieldOperand(ebx, i), edx); + __ mov(FieldOperand(ebx, i + kPointerSize), ecx); + } + __ mov(eax, ebx); + + __ bind(&done); + } + frame_->Push(eax); +} + + class DeferredSearchCache: public DeferredCode { public: DeferredSearchCache(Register dst, Register cache, Register key) @@ -8578,11 +8660,9 @@ void CodeGenerator::Int32BinaryOperation(BinaryOperation* node) { } right.Unuse(); frame_->Push(&left); - if (!node->to_int32() || op == Token::MUL) { - // If ToInt32 is called on the result of ADD, SUB, we don't + if (!node->to_int32()) { + // If ToInt32 is called on the result of ADD, SUB, or MUL, we don't // care about overflows. - // Result of MUL can be non-representable precisely in double so - // we have to check for overflow. unsafe_bailout_->Branch(overflow); } break; diff --git a/deps/v8/src/ia32/codegen-ia32.h b/deps/v8/src/ia32/codegen-ia32.h index 5a12e10ea5..4594b19ddd 100644 --- a/deps/v8/src/ia32/codegen-ia32.h +++ b/deps/v8/src/ia32/codegen-ia32.h @@ -697,6 +697,11 @@ class CodeGenerator: public AstVisitor { // Construct a RegExp exec result with two in-object properties. void GenerateRegExpConstructResult(ZoneList* args); + // Clone the result of a regexp function. + // Must be an object created by GenerateRegExpConstructResult with + // no extra properties. + void GenerateRegExpCloneResult(ZoneList* args); + // Support for fast native caches. void GenerateGetFromCache(ZoneList* args); diff --git a/deps/v8/src/ia32/full-codegen-ia32.cc b/deps/v8/src/ia32/full-codegen-ia32.cc index 1ea719d713..ee4e6458ae 100644 --- a/deps/v8/src/ia32/full-codegen-ia32.cc +++ b/deps/v8/src/ia32/full-codegen-ia32.cc @@ -1996,14 +1996,12 @@ void FullCodeGenerator::EmitCallWithIC(Call* expr, // Code common for calls using the IC. ZoneList* args = expr->arguments(); int arg_count = args->length(); - { PreserveStatementPositionScope scope(masm()->positions_recorder()); - for (int i = 0; i < arg_count; i++) { - VisitForStackValue(args->at(i)); - } - __ Set(ecx, Immediate(name)); + for (int i = 0; i < arg_count; i++) { + VisitForStackValue(args->at(i)); } + __ Set(ecx, Immediate(name)); // Record source position of the IC call. - SetSourcePosition(expr->position(), FORCED_POSITION); + SetSourcePosition(expr->position()); InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; Handle ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop); EmitCallIC(ic, mode); @@ -2019,15 +2017,13 @@ void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, // Code common for calls using the IC. ZoneList* args = expr->arguments(); int arg_count = args->length(); - { PreserveStatementPositionScope scope(masm()->positions_recorder()); - for (int i = 0; i < arg_count; i++) { - VisitForStackValue(args->at(i)); - } - VisitForAccumulatorValue(key); - __ mov(ecx, eax); + for (int i = 0; i < arg_count; i++) { + VisitForStackValue(args->at(i)); } + VisitForAccumulatorValue(key); + __ mov(ecx, eax); // Record source position of the IC call. - SetSourcePosition(expr->position(), FORCED_POSITION); + SetSourcePosition(expr->position()); InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; Handle ic = CodeGenerator::ComputeKeyedCallInitialize( arg_count, in_loop); @@ -2042,13 +2038,11 @@ void FullCodeGenerator::EmitCallWithStub(Call* expr) { // Code common for calls using the call stub. ZoneList* args = expr->arguments(); int arg_count = args->length(); - { PreserveStatementPositionScope scope(masm()->positions_recorder()); - for (int i = 0; i < arg_count; i++) { - VisitForStackValue(args->at(i)); - } + for (int i = 0; i < arg_count; i++) { + VisitForStackValue(args->at(i)); } // Record source position for debugger. - SetSourcePosition(expr->position(), FORCED_POSITION); + SetSourcePosition(expr->position()); InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); __ CallStub(&stub); @@ -2068,39 +2062,37 @@ void FullCodeGenerator::VisitCall(Call* expr) { // resolve the function we need to call and the receiver of the // call. Then we call the resolved function using the given // arguments. + VisitForStackValue(fun); + __ push(Immediate(Factory::undefined_value())); // Reserved receiver slot. + + // Push the arguments. ZoneList* args = expr->arguments(); int arg_count = args->length(); - { PreserveStatementPositionScope pos_scope(masm()->positions_recorder()); - VisitForStackValue(fun); - // Reserved receiver slot. - __ push(Immediate(Factory::undefined_value())); + for (int i = 0; i < arg_count; i++) { + VisitForStackValue(args->at(i)); + } - // Push the arguments. - for (int i = 0; i < arg_count; i++) { - VisitForStackValue(args->at(i)); - } + // Push copy of the function - found below the arguments. + __ push(Operand(esp, (arg_count + 1) * kPointerSize)); - // Push copy of the function - found below the arguments. - __ push(Operand(esp, (arg_count + 1) * kPointerSize)); + // Push copy of the first argument or undefined if it doesn't exist. + if (arg_count > 0) { + __ push(Operand(esp, arg_count * kPointerSize)); + } else { + __ push(Immediate(Factory::undefined_value())); + } - // Push copy of the first argument or undefined if it doesn't exist. - if (arg_count > 0) { - __ push(Operand(esp, arg_count * kPointerSize)); - } else { - __ push(Immediate(Factory::undefined_value())); - } + // Push the receiver of the enclosing function and do runtime call. + __ push(Operand(ebp, (2 + scope()->num_parameters()) * kPointerSize)); + __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 3); - // Push the receiver of the enclosing function and do runtime call. - __ push(Operand(ebp, (2 + scope()->num_parameters()) * kPointerSize)); - __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 3); + // The runtime call returns a pair of values in eax (function) and + // edx (receiver). Touch up the stack with the right values. + __ mov(Operand(esp, (arg_count + 0) * kPointerSize), edx); + __ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax); - // The runtime call returns a pair of values in eax (function) and - // edx (receiver). Touch up the stack with the right values. - __ mov(Operand(esp, (arg_count + 0) * kPointerSize), edx); - __ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax); - } // Record source position for debugger. - SetSourcePosition(expr->position(), FORCED_POSITION); + SetSourcePosition(expr->position()); InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); __ CallStub(&stub); @@ -2116,14 +2108,12 @@ void FullCodeGenerator::VisitCall(Call* expr) { // Call to a lookup slot (dynamically introduced variable). Label slow, done; - { PreserveStatementPositionScope scope(masm()->positions_recorder()); - // Generate code for loading from variables potentially shadowed - // by eval-introduced variables. - EmitDynamicLoadFromSlotFastCase(var->AsSlot(), - NOT_INSIDE_TYPEOF, - &slow, - &done); - } + // Generate code for loading from variables potentially shadowed + // by eval-introduced variables. + EmitDynamicLoadFromSlotFastCase(var->AsSlot(), + NOT_INSIDE_TYPEOF, + &slow, + &done); __ bind(&slow); // Call the runtime to find the function to call (returned in eax) @@ -2162,15 +2152,11 @@ void FullCodeGenerator::VisitCall(Call* expr) { // Call to a keyed property. // For a synthetic property use keyed load IC followed by function call, // for a regular property use keyed EmitCallIC. - { PreserveStatementPositionScope scope(masm()->positions_recorder()); - VisitForStackValue(prop->obj()); - } + VisitForStackValue(prop->obj()); if (prop->is_synthetic()) { - { PreserveStatementPositionScope scope(masm()->positions_recorder()); - VisitForAccumulatorValue(prop->key()); - } + VisitForAccumulatorValue(prop->key()); // Record source code position for IC call. - SetSourcePosition(prop->position(), FORCED_POSITION); + SetSourcePosition(prop->position()); __ pop(edx); // We do not need to keep the receiver. Handle ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); @@ -2195,9 +2181,7 @@ void FullCodeGenerator::VisitCall(Call* expr) { loop_depth() == 0) { lit->set_try_full_codegen(true); } - { PreserveStatementPositionScope scope(masm()->positions_recorder()); - VisitForStackValue(fun); - } + VisitForStackValue(fun); // Load global receiver object. __ mov(ebx, CodeGenerator::GlobalObject()); __ push(FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset)); diff --git a/deps/v8/src/ia32/ic-ia32.cc b/deps/v8/src/ia32/ic-ia32.cc index a0bc086d87..b5f4deefeb 100644 --- a/deps/v8/src/ia32/ic-ia32.cc +++ b/deps/v8/src/ia32/ic-ia32.cc @@ -33,6 +33,7 @@ #include "ic-inl.h" #include "runtime.h" #include "stub-cache.h" +#include "utils.h" namespace v8 { namespace internal { diff --git a/deps/v8/src/ia32/macro-assembler-ia32.h b/deps/v8/src/ia32/macro-assembler-ia32.h index d65eebbc20..7b9b843939 100644 --- a/deps/v8/src/ia32/macro-assembler-ia32.h +++ b/deps/v8/src/ia32/macro-assembler-ia32.h @@ -488,7 +488,7 @@ class MacroAssembler: public Assembler { // stored in ApiParameterOperand(0), ApiParameterOperand(1) etc. void PrepareCallApiFunction(int stack_space, int argc); - // Calls an API function. Allocates HandleScope, extracts + // Tail call an API function (jump). Allocates HandleScope, extracts // returned value from handle and propagates exceptions. // Clobbers ebx, esi, edi and caller-save registers. void CallApiFunctionAndReturn(ApiFunction* function, int argc); diff --git a/deps/v8/src/ia32/stub-cache-ia32.cc b/deps/v8/src/ia32/stub-cache-ia32.cc index f59928fe2b..e387088359 100644 --- a/deps/v8/src/ia32/stub-cache-ia32.cc +++ b/deps/v8/src/ia32/stub-cache-ia32.cc @@ -413,10 +413,6 @@ static void CompileCallLoadPropertyWithInterceptor(MacroAssembler* masm, } -// Number of pointers to be reserved on stack for fast API call. -static const int kFastApiCallArguments = 3; - - // Reserves space for the extra arguments to FastHandleApiCall in the // caller's frame. // @@ -427,9 +423,10 @@ static void ReserveSpaceForFastApiCall(MacroAssembler* masm, Register scratch) { // -- esp[4] : last argument in the internal frame of the caller // ----------------------------------- __ pop(scratch); - for (int i = 0; i < kFastApiCallArguments; i++) { - __ push(Immediate(Smi::FromInt(0))); - } + __ push(Immediate(Smi::FromInt(0))); + __ push(Immediate(Smi::FromInt(0))); + __ push(Immediate(Smi::FromInt(0))); + __ push(Immediate(Smi::FromInt(0))); __ push(scratch); } @@ -437,81 +434,75 @@ static void ReserveSpaceForFastApiCall(MacroAssembler* masm, Register scratch) { // Undoes the effects of ReserveSpaceForFastApiCall. static void FreeSpaceForFastApiCall(MacroAssembler* masm, Register scratch) { // ----------- S t a t e ------------- - // -- esp[0] : return address. - // -- esp[4] : last fast api call extra argument. + // -- esp[0] : return address + // -- esp[4] : last fast api call extra argument // -- ... - // -- esp[kFastApiCallArguments * 4] : first fast api call extra argument. - // -- esp[kFastApiCallArguments * 4 + 4] : last argument in the internal - // frame. + // -- esp[16] : first fast api call extra argument + // -- esp[20] : last argument in the internal frame // ----------------------------------- __ pop(scratch); - __ add(Operand(esp), Immediate(kPointerSize * kFastApiCallArguments)); + __ add(Operand(esp), Immediate(kPointerSize * 4)); __ push(scratch); } // Generates call to FastHandleApiCall builtin. -static bool GenerateFastApiCall(MacroAssembler* masm, +static void GenerateFastApiCall(MacroAssembler* masm, const CallOptimization& optimization, - int argc, - Failure** failure) { + int argc) { // ----------- S t a t e ------------- // -- esp[0] : return address // -- esp[4] : object passing the type check // (last fast api call extra argument, // set by CheckPrototypes) - // -- esp[8] : api function + // -- esp[8] : api call data + // -- esp[12] : api callback + // -- esp[16] : api function // (first fast api call extra argument) - // -- esp[12] : api call data - // -- esp[16] : last argument + // -- esp[20] : last argument // -- ... - // -- esp[(argc + 3) * 4] : first argument - // -- esp[(argc + 4) * 4] : receiver + // -- esp[(argc + 5) * 4] : first argument + // -- esp[(argc + 6) * 4] : receiver // ----------------------------------- + // Get the function and setup the context. JSFunction* function = optimization.constant_function(); __ mov(edi, Immediate(Handle(function))); __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); // Pass the additional arguments FastHandleApiCall expects. - __ mov(Operand(esp, 2 * kPointerSize), edi); + __ mov(Operand(esp, 4 * kPointerSize), edi); + bool info_loaded = false; + Object* callback = optimization.api_call_info()->callback(); + if (Heap::InNewSpace(callback)) { + info_loaded = true; + __ mov(ecx, Handle(optimization.api_call_info())); + __ mov(ebx, FieldOperand(ecx, CallHandlerInfo::kCallbackOffset)); + __ mov(Operand(esp, 3 * kPointerSize), ebx); + } else { + __ mov(Operand(esp, 3 * kPointerSize), Immediate(Handle(callback))); + } Object* call_data = optimization.api_call_info()->data(); - Handle api_call_info_handle(optimization.api_call_info()); if (Heap::InNewSpace(call_data)) { - __ mov(ecx, api_call_info_handle); + if (!info_loaded) { + __ mov(ecx, Handle(optimization.api_call_info())); + } __ mov(ebx, FieldOperand(ecx, CallHandlerInfo::kDataOffset)); - __ mov(Operand(esp, 3 * kPointerSize), ebx); + __ mov(Operand(esp, 2 * kPointerSize), ebx); } else { - __ mov(Operand(esp, 3 * kPointerSize), + __ mov(Operand(esp, 2 * kPointerSize), Immediate(Handle(call_data))); } - // Prepare arguments for ApiCallEntryStub. - __ lea(eax, Operand(esp, 3 * kPointerSize)); - __ lea(ebx, Operand(esp, (argc + 3) * kPointerSize)); - __ Set(edx, Immediate(argc)); - - Object* callback = optimization.api_call_info()->callback(); - Address api_function_address = v8::ToCData
(callback); - ApiFunction fun(api_function_address); - - ApiCallEntryStub stub(api_call_info_handle, &fun); - - __ EnterInternalFrame(); + // Set the number of arguments. + __ mov(eax, Immediate(argc + 4)); - // Emitting a stub call may try to allocate (if the code is not - // already generated). Do not allow the assembler to perform a - // garbage collection but instead return the allocation failure - // object. - MaybeObject* result = masm->TryCallStub(&stub); - if (result->IsFailure()) { - *failure = Failure::cast(result); - return false; - } - - __ LeaveInternalFrame(); - __ ret((argc + 4) * kPointerSize); - return true; + // Jump to the fast api call builtin (tail call). + Handle code = Handle( + Builtins::builtin(Builtins::FastHandleApiCall)); + ParameterCount expected(0); + __ InvokeCode(code, expected, expected, + RelocInfo::CODE_TARGET, JUMP_FUNCTION); } @@ -524,7 +515,7 @@ class CallInterceptorCompiler BASE_EMBEDDED { arguments_(arguments), name_(name) {} - bool Compile(MacroAssembler* masm, + void Compile(MacroAssembler* masm, JSObject* object, JSObject* holder, String* name, @@ -533,8 +524,7 @@ class CallInterceptorCompiler BASE_EMBEDDED { Register scratch1, Register scratch2, Register scratch3, - Label* miss, - Failure** failure) { + Label* miss) { ASSERT(holder->HasNamedInterceptor()); ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); @@ -545,18 +535,17 @@ class CallInterceptorCompiler BASE_EMBEDDED { CallOptimization optimization(lookup); if (optimization.is_constant_call()) { - return CompileCacheable(masm, - object, - receiver, - scratch1, - scratch2, - scratch3, - holder, - lookup, - name, - optimization, - miss, - failure); + CompileCacheable(masm, + object, + receiver, + scratch1, + scratch2, + scratch3, + holder, + lookup, + name, + optimization, + miss); } else { CompileRegular(masm, object, @@ -567,12 +556,11 @@ class CallInterceptorCompiler BASE_EMBEDDED { name, holder, miss); - return true; } } private: - bool CompileCacheable(MacroAssembler* masm, + void CompileCacheable(MacroAssembler* masm, JSObject* object, Register receiver, Register scratch1, @@ -582,8 +570,7 @@ class CallInterceptorCompiler BASE_EMBEDDED { LookupResult* lookup, String* name, const CallOptimization& optimization, - Label* miss_label, - Failure** failure) { + Label* miss_label) { ASSERT(optimization.is_constant_call()); ASSERT(!lookup->holder()->IsGlobalObject()); @@ -645,11 +632,7 @@ class CallInterceptorCompiler BASE_EMBEDDED { // Invoke function. if (can_do_fast_api_call) { - bool success = GenerateFastApiCall(masm, optimization, - arguments_.immediate(), failure); - if (!success) { - return false; - } + GenerateFastApiCall(masm, optimization, arguments_.immediate()); } else { __ InvokeFunction(optimization.constant_function(), arguments_, JUMP_FUNCTION); @@ -667,8 +650,6 @@ class CallInterceptorCompiler BASE_EMBEDDED { if (can_do_fast_api_call) { FreeSpaceForFastApiCall(masm, scratch1); } - - return true; } void CompileRegular(MacroAssembler* masm, @@ -924,7 +905,7 @@ Register StubCompiler::CheckPrototypes(JSObject* object, MaybeObject* maybe_lookup_result = Heap::LookupSymbol(name); Object* lookup_result = NULL; // Initialization to please compiler. if (!maybe_lookup_result->ToObject(&lookup_result)) { - set_failure(Failure::cast(maybe_lookup_result)); + set_failure(Failure::cast(lookup_result)); return reg; } name = String::cast(lookup_result); @@ -1065,7 +1046,8 @@ bool StubCompiler::GenerateLoadCallback(JSObject* object, __ EnterInternalFrame(); // Push the stack address where the list of arguments ends. - __ lea(scratch2, Operand(esp, -2 * kPointerSize)); + __ mov(scratch2, esp); + __ sub(Operand(scratch2), Immediate(2 * kPointerSize)); __ push(scratch2); __ push(receiver); // receiver __ push(reg); // holder @@ -1079,11 +1061,12 @@ bool StubCompiler::GenerateLoadCallback(JSObject* object, __ push(name_reg); // name // Save a pointer to where we pushed the arguments pointer. // This will be passed as the const AccessorInfo& to the C++ callback. - STATIC_ASSERT(ApiGetterEntryStub::kStackSpace == 5); - __ lea(eax, Operand(esp, 4 * kPointerSize)); + __ mov(eax, esp); + __ add(Operand(eax), Immediate(4 * kPointerSize)); __ mov(ebx, esp); // Do call through the api. + ASSERT_EQ(5, ApiGetterEntryStub::kStackSpace); Address getter_address = v8::ToCData
(callback->getter()); ApiFunction fun(getter_address); ApiGetterEntryStub stub(callback_handle, &fun); @@ -1094,7 +1077,7 @@ bool StubCompiler::GenerateLoadCallback(JSObject* object, Object* result = NULL; // Initialization to please compiler. { MaybeObject* try_call_result = masm()->TryCallStub(&stub); if (!try_call_result->ToObject(&result)) { - *failure = Failure::cast(try_call_result); + *failure = Failure::cast(result); return false; } } @@ -2225,11 +2208,7 @@ MaybeObject* CallStubCompiler::CompileCallConstant(Object* object, } if (depth != kInvalidProtoDepth) { - Failure* failure; - bool success = GenerateFastApiCall(masm(), optimization, argc, &failure); - if (!success) { - return failure; - } + GenerateFastApiCall(masm(), optimization, argc); } else { __ InvokeFunction(function, arguments(), JUMP_FUNCTION); } @@ -2274,21 +2253,16 @@ MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object, __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); CallInterceptorCompiler compiler(this, arguments(), ecx); - Failure* failure; - bool success = compiler.Compile(masm(), - object, - holder, - name, - &lookup, - edx, - ebx, - edi, - eax, - &miss, - &failure); - if (!success) { - return false; - } + compiler.Compile(masm(), + object, + holder, + name, + &lookup, + edx, + ebx, + edi, + eax, + &miss); // Restore receiver. __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); diff --git a/deps/v8/src/jump-target-heavy.cc b/deps/v8/src/jump-target-heavy.cc index c3c22f1ac6..e0585e7942 100644 --- a/deps/v8/src/jump-target-heavy.cc +++ b/deps/v8/src/jump-target-heavy.cc @@ -414,9 +414,8 @@ void BreakTarget::Branch(Condition cc, Hint hint) { DeferredCode::DeferredCode() : masm_(CodeGeneratorScope::Current()->masm()), - statement_position_(masm_->positions_recorder()-> - current_statement_position()), - position_(masm_->positions_recorder()->current_position()), + statement_position_(masm_->current_statement_position()), + position_(masm_->current_position()), frame_state_(CodeGeneratorScope::Current()->frame()) { ASSERT(statement_position_ != RelocInfo::kNoPosition); ASSERT(position_ != RelocInfo::kNoPosition); diff --git a/deps/v8/src/jump-target-light.cc b/deps/v8/src/jump-target-light.cc index 36dc176bce..19f7bfec0a 100644 --- a/deps/v8/src/jump-target-light.cc +++ b/deps/v8/src/jump-target-light.cc @@ -36,9 +36,8 @@ namespace internal { DeferredCode::DeferredCode() : masm_(CodeGeneratorScope::Current()->masm()), - statement_position_(masm_->positions_recorder()-> - current_statement_position()), - position_(masm_->positions_recorder()->current_position()), + statement_position_(masm_->current_statement_position()), + position_(masm_->current_position()), frame_state_(*CodeGeneratorScope::Current()->frame()) { ASSERT(statement_position_ != RelocInfo::kNoPosition); ASSERT(position_ != RelocInfo::kNoPosition); diff --git a/deps/v8/src/objects-debug.cc b/deps/v8/src/objects-debug.cc index 2b79016a01..c0e5610aba 100644 --- a/deps/v8/src/objects-debug.cc +++ b/deps/v8/src/objects-debug.cc @@ -997,8 +997,6 @@ void AccessorInfo::AccessorInfoPrint() { data()->ShortPrint(); PrintF("\n - flag: "); flag()->ShortPrint(); - PrintF("\n - load_stub_cache: "); - load_stub_cache()->ShortPrint(); } void AccessCheckInfo::AccessCheckInfoVerify() { @@ -1048,7 +1046,6 @@ void CallHandlerInfo::CallHandlerInfoVerify() { CHECK(IsCallHandlerInfo()); VerifyPointer(callback()); VerifyPointer(data()); - VerifyPointer(call_stub_cache()); } void CallHandlerInfo::CallHandlerInfoPrint() { @@ -1057,8 +1054,6 @@ void CallHandlerInfo::CallHandlerInfoPrint() { callback()->ShortPrint(); PrintF("\n - data: "); data()->ShortPrint(); - PrintF("\n - call_stub_cache: "); - call_stub_cache()->ShortPrint(); } void TemplateInfo::TemplateInfoVerify() { diff --git a/deps/v8/src/objects-inl.h b/deps/v8/src/objects-inl.h index 79d70e1141..1852b549bf 100644 --- a/deps/v8/src/objects-inl.h +++ b/deps/v8/src/objects-inl.h @@ -2557,7 +2557,6 @@ ACCESSORS(InterceptorInfo, data, Object, kDataOffset) ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset) ACCESSORS(CallHandlerInfo, data, Object, kDataOffset) -ACCESSORS(CallHandlerInfo, call_stub_cache, Object, kCallStubCacheOffset) ACCESSORS(TemplateInfo, tag, Object, kTagOffset) ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset) @@ -2672,7 +2671,6 @@ SMI_ACCESSORS(SharedFunctionInfo, this_property_assignments_count, #else #define PSEUDO_SMI_ACCESSORS_LO(holder, name, offset) \ - STATIC_ASSERT(holder::offset % kPointerSize == 0); \ int holder::name() { \ int value = READ_INT_FIELD(this, offset); \ ASSERT(kHeapObjectTag == 1); \ @@ -2688,36 +2686,30 @@ SMI_ACCESSORS(SharedFunctionInfo, this_property_assignments_count, (value << 1) & ~kHeapObjectTag); \ } -#define PSEUDO_SMI_ACCESSORS_HI(holder, name, offset) \ - STATIC_ASSERT(holder::offset % kPointerSize == kIntSize); \ +#define PSEUDO_SMI_ACCESSORS_HI(holder, name, offset) \ INT_ACCESSORS(holder, name, offset) + PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, length, kLengthOffset) -PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, - formal_parameter_count, - kFormalParameterCountOffset) +PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, formal_parameter_count, + kFormalParameterCountOffset) -PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, - expected_nof_properties, - kExpectedNofPropertiesOffset) +PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, expected_nof_properties, + kExpectedNofPropertiesOffset) PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, num_literals, kNumLiteralsOffset) -PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, end_position, kEndPositionOffset) -PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, - start_position_and_type, - kStartPositionAndTypeOffset) - -PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, - function_token_position, - kFunctionTokenPositionOffset) -PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, - compiler_hints, - kCompilerHintsOffset) - -PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, - this_property_assignments_count, - kThisPropertyAssignmentsCountOffset) +PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, start_position_and_type, + kStartPositionAndTypeOffset) +PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, end_position, kEndPositionOffset) + +PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, function_token_position, + kFunctionTokenPositionOffset) +PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, compiler_hints, + kCompilerHintsOffset) + +PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, this_property_assignments_count, + kThisPropertyAssignmentsCountOffset) #endif diff --git a/deps/v8/src/objects.h b/deps/v8/src/objects.h index 9d975ec516..6029ad545b 100644 --- a/deps/v8/src/objects.h +++ b/deps/v8/src/objects.h @@ -5423,7 +5423,6 @@ class CallHandlerInfo: public Struct { public: DECL_ACCESSORS(callback, Object) DECL_ACCESSORS(data, Object) - DECL_ACCESSORS(call_stub_cache, Object) static inline CallHandlerInfo* cast(Object* obj); @@ -5434,8 +5433,7 @@ class CallHandlerInfo: public Struct { static const int kCallbackOffset = HeapObject::kHeaderSize; static const int kDataOffset = kCallbackOffset + kPointerSize; - static const int kCallStubCacheOffset = kDataOffset + kPointerSize; - static const int kSize = kCallStubCacheOffset + kPointerSize; + static const int kSize = kDataOffset + kPointerSize; private: DISALLOW_IMPLICIT_CONSTRUCTORS(CallHandlerInfo); diff --git a/deps/v8/src/parser.cc b/deps/v8/src/parser.cc index a0f3b7147f..aad7a615a5 100644 --- a/deps/v8/src/parser.cc +++ b/deps/v8/src/parser.cc @@ -36,9 +36,9 @@ #include "messages.h" #include "parser.h" #include "platform.h" -#include "preparser.h" #include "runtime.h" #include "scopeinfo.h" +#include "scopes.h" #include "string-stream.h" #include "ast-inl.h" @@ -323,96 +323,302 @@ TemporaryScope::~TemporaryScope() { } -Handle Parser::LookupSymbol(int symbol_id, +// A zone list wrapper lets code either access a access a zone list +// or appear to do so while actually ignoring all operations. +template +class ZoneListWrapper { + public: + ZoneListWrapper() : list_(NULL) { } + explicit ZoneListWrapper(int size) : list_(new ZoneList(size)) { } + void Add(T* that) { if (list_) list_->Add(that); } + int length() { return list_->length(); } + ZoneList* elements() { return list_; } + T* at(int index) { return list_->at(index); } + private: + ZoneList* list_; +}; + + +// Allocation macro that should be used to allocate objects that must +// only be allocated in real parsing mode. Note that in preparse mode +// not only is the syntax tree not created but the constructor +// arguments are not evaluated. +#define NEW(expr) (is_pre_parsing_ ? NULL : new expr) + + +class ParserFactory BASE_EMBEDDED { + public: + explicit ParserFactory(bool is_pre_parsing) : + is_pre_parsing_(is_pre_parsing) { } + + virtual ~ParserFactory() { } + + virtual Scope* NewScope(Scope* parent, Scope::Type type, bool inside_with); + + virtual Handle LookupSymbol(int index, Vector string) { + return Handle(); + } + + virtual Handle EmptySymbol() { + return Handle(); + } + + virtual Expression* NewProperty(Expression* obj, Expression* key, int pos) { + if (obj == VariableProxySentinel::this_proxy()) { + return Property::this_property(); + } else { + return ValidLeftHandSideSentinel::instance(); + } + } + + virtual Expression* NewCall(Expression* expression, + ZoneList* arguments, + int pos) { + return Call::sentinel(); + } + + virtual Statement* EmptyStatement() { + return NULL; + } + + template ZoneListWrapper NewList(int size) { + return is_pre_parsing_ ? ZoneListWrapper() : ZoneListWrapper(size); + } + + private: + bool is_pre_parsing_; +}; + + +class ParserLog BASE_EMBEDDED { + public: + virtual ~ParserLog() { } + + // Records the occurrence of a function. + virtual FunctionEntry LogFunction(int start) { return FunctionEntry(); } + virtual void LogSymbol(int start, Vector symbol) {} + virtual void LogError() { } + // Return the current position in the function entry log. + virtual int function_position() { return 0; } + virtual int symbol_position() { return 0; } + virtual int symbol_ids() { return 0; } + virtual void PauseRecording() {} + virtual void ResumeRecording() {} + virtual Vector ExtractData() { + return Vector(); + }; +}; + + + +class ConditionalLogPauseScope { + public: + ConditionalLogPauseScope(bool pause, ParserLog* log) + : log_(log), pause_(pause) { + if (pause) log->PauseRecording(); + } + ~ConditionalLogPauseScope() { + if (pause_) log_->ResumeRecording(); + } + private: + ParserLog* log_; + bool pause_; +}; + + +class AstBuildingParserFactory : public ParserFactory { + public: + explicit AstBuildingParserFactory(int expected_symbols) + : ParserFactory(false), symbol_cache_(expected_symbols) { } + + virtual Scope* NewScope(Scope* parent, Scope::Type type, bool inside_with); + + virtual Handle LookupSymbol(int symbol_id, + Vector string) { + // Length of symbol cache is the number of identified symbols. + // If we are larger than that, or negative, it's not a cached symbol. + // This might also happen if there is no preparser symbol data, even + // if there is some preparser data. + if (static_cast(symbol_id) + >= static_cast(symbol_cache_.length())) { + return Factory::LookupSymbol(string); + } + return LookupCachedSymbol(symbol_id, string); + } + + Handle LookupCachedSymbol(int symbol_id, Vector string) { - // Length of symbol cache is the number of identified symbols. - // If we are larger than that, or negative, it's not a cached symbol. - // This might also happen if there is no preparser symbol data, even - // if there is some preparser data. - if (static_cast(symbol_id) - >= static_cast(symbol_cache_.length())) { - return Factory::LookupSymbol(string); - } - return LookupCachedSymbol(symbol_id, string); -} - - -Handle Parser::LookupCachedSymbol(int symbol_id, - Vector string) { - // Make sure the cache is large enough to hold the symbol identifier. - if (symbol_cache_.length() <= symbol_id) { - // Increase length to index + 1. - symbol_cache_.AddBlock(Handle::null(), - symbol_id + 1 - symbol_cache_.length()); - } - Handle result = symbol_cache_.at(symbol_id); - if (result.is_null()) { - result = Factory::LookupSymbol(string); - symbol_cache_.at(symbol_id) = result; + // Make sure the cache is large enough to hold the symbol identifier. + if (symbol_cache_.length() <= symbol_id) { + // Increase length to index + 1. + symbol_cache_.AddBlock(Handle::null(), + symbol_id + 1 - symbol_cache_.length()); + } + Handle result = symbol_cache_.at(symbol_id); + if (result.is_null()) { + result = Factory::LookupSymbol(string); + symbol_cache_.at(symbol_id) = result; + return result; + } + Counters::total_preparse_symbols_skipped.Increment(); return result; } - Counters::total_preparse_symbols_skipped.Increment(); - return result; -} + virtual Handle EmptySymbol() { + return Factory::empty_symbol(); + } -Vector PartialParserRecorder::ExtractData() { - int function_size = function_store_.size(); - int total_size = ScriptDataImpl::kHeaderSize + function_size; - Vector data = Vector::New(total_size); - preamble_[ScriptDataImpl::kFunctionsSizeOffset] = function_size; - preamble_[ScriptDataImpl::kSymbolCountOffset] = 0; - memcpy(data.start(), preamble_, sizeof(preamble_)); - int symbol_start = ScriptDataImpl::kHeaderSize + function_size; - if (function_size > 0) { - function_store_.WriteTo(data.SubVector(ScriptDataImpl::kHeaderSize, - symbol_start)); + virtual Expression* NewProperty(Expression* obj, Expression* key, int pos) { + return new Property(obj, key, pos); } - return data; -} + + virtual Expression* NewCall(Expression* expression, + ZoneList* arguments, + int pos) { + return new Call(expression, arguments, pos); + } + + virtual Statement* EmptyStatement(); + private: + List > symbol_cache_; +}; -void CompleteParserRecorder::LogSymbol(int start, Vector literal) { - if (!is_recording_) return; +// Record only functions. +class PartialParserRecorder: public ParserLog { + public: + PartialParserRecorder(); + virtual FunctionEntry LogFunction(int start); + + virtual int function_position() { return function_store_.size(); } + + virtual void LogError() { } + + virtual void LogMessage(Scanner::Location loc, + const char* message, + Vector args); + + virtual Vector ExtractData() { + int function_size = function_store_.size(); + int total_size = ScriptDataImpl::kHeaderSize + function_size; + Vector data = Vector::New(total_size); + preamble_[ScriptDataImpl::kFunctionsSizeOffset] = function_size; + preamble_[ScriptDataImpl::kSymbolCountOffset] = 0; + memcpy(data.start(), preamble_, sizeof(preamble_)); + int symbol_start = ScriptDataImpl::kHeaderSize + function_size; + if (function_size > 0) { + function_store_.WriteTo(data.SubVector(ScriptDataImpl::kHeaderSize, + symbol_start)); + } + return data; + } - int hash = vector_hash(literal); - HashMap::Entry* entry = symbol_table_.Lookup(&literal, hash, true); - int id = static_cast(reinterpret_cast(entry->value)); - if (id == 0) { - // Put (symbol_id_ + 1) into entry and increment it. - id = ++symbol_id_; - entry->value = reinterpret_cast(id); - Vector > symbol = symbol_entries_.AddBlock(1, literal); - entry->key = &symbol[0]; + virtual void PauseRecording() { + pause_count_++; + is_recording_ = false; } - WriteNumber(id - 1); -} + virtual void ResumeRecording() { + ASSERT(pause_count_ > 0); + if (--pause_count_ == 0) is_recording_ = !has_error(); + } -Vector CompleteParserRecorder::ExtractData() { - int function_size = function_store_.size(); - // Add terminator to symbols, then pad to unsigned size. - int symbol_size = symbol_store_.size(); - int padding = sizeof(unsigned) - (symbol_size % sizeof(unsigned)); - symbol_store_.AddBlock(padding, ScriptDataImpl::kNumberTerminator); - symbol_size += padding; - int total_size = ScriptDataImpl::kHeaderSize + function_size - + (symbol_size / sizeof(unsigned)); - Vector data = Vector::New(total_size); - preamble_[ScriptDataImpl::kFunctionsSizeOffset] = function_size; - preamble_[ScriptDataImpl::kSymbolCountOffset] = symbol_id_; - memcpy(data.start(), preamble_, sizeof(preamble_)); - int symbol_start = ScriptDataImpl::kHeaderSize + function_size; - if (function_size > 0) { - function_store_.WriteTo(data.SubVector(ScriptDataImpl::kHeaderSize, - symbol_start)); + protected: + bool has_error() { + return static_cast(preamble_[ScriptDataImpl::kHasErrorOffset]); } - if (!has_error()) { - symbol_store_.WriteTo( - Vector::cast(data.SubVector(symbol_start, total_size))); + bool is_recording() { + return is_recording_; } - return data; -} + + void WriteString(Vector str); + + Collector function_store_; + unsigned preamble_[ScriptDataImpl::kHeaderSize]; + bool is_recording_; + int pause_count_; + +#ifdef DEBUG + int prev_start; +#endif +}; + + +// Record both functions and symbols. +class CompleteParserRecorder: public PartialParserRecorder { + public: + CompleteParserRecorder(); + + virtual void LogSymbol(int start, Vector literal) { + if (!is_recording_) return; + int hash = vector_hash(literal); + HashMap::Entry* entry = symbol_table_.Lookup(&literal, hash, true); + int id = static_cast(reinterpret_cast(entry->value)); + if (id == 0) { + // Put (symbol_id_ + 1) into entry and increment it. + id = ++symbol_id_; + entry->value = reinterpret_cast(id); + Vector > symbol = symbol_entries_.AddBlock(1, literal); + entry->key = &symbol[0]; + } + WriteNumber(id - 1); + } + + virtual Vector ExtractData() { + int function_size = function_store_.size(); + // Add terminator to symbols, then pad to unsigned size. + int symbol_size = symbol_store_.size(); + int padding = sizeof(unsigned) - (symbol_size % sizeof(unsigned)); + symbol_store_.AddBlock(padding, ScriptDataImpl::kNumberTerminator); + symbol_size += padding; + int total_size = ScriptDataImpl::kHeaderSize + function_size + + (symbol_size / sizeof(unsigned)); + Vector data = Vector::New(total_size); + preamble_[ScriptDataImpl::kFunctionsSizeOffset] = function_size; + preamble_[ScriptDataImpl::kSymbolCountOffset] = symbol_id_; + memcpy(data.start(), preamble_, sizeof(preamble_)); + int symbol_start = ScriptDataImpl::kHeaderSize + function_size; + if (function_size > 0) { + function_store_.WriteTo(data.SubVector(ScriptDataImpl::kHeaderSize, + symbol_start)); + } + if (!has_error()) { + symbol_store_.WriteTo( + Vector::cast(data.SubVector(symbol_start, total_size))); + } + return data; + } + + virtual int symbol_position() { return symbol_store_.size(); } + virtual int symbol_ids() { return symbol_id_; } + private: + static int vector_hash(Vector string) { + int hash = 0; + for (int i = 0; i < string.length(); i++) { + int c = string[i]; + hash += c; + hash += (hash << 10); + hash ^= (hash >> 6); + } + return hash; + } + + static bool vector_compare(void* a, void* b) { + Vector* string1 = reinterpret_cast* >(a); + Vector* string2 = reinterpret_cast* >(b); + int length = string1->length(); + if (string2->length() != length) return false; + return memcmp(string1->start(), string2->start(), length) == 0; + } + + // Write a non-negative number to the symbol store. + void WriteNumber(int number); + + Collector symbol_store_; + Collector > symbol_entries_; + HashMap symbol_table_; + int symbol_id_; +}; FunctionEntry ScriptDataImpl::GetFunctionEntry(int start) { @@ -485,7 +691,7 @@ PartialParserRecorder::PartialParserRecorder() preamble_[ScriptDataImpl::kSizeOffset] = 0; ASSERT_EQ(6, ScriptDataImpl::kHeaderSize); #ifdef DEBUG - prev_start_ = -1; + prev_start = -1; #endif } @@ -536,8 +742,8 @@ const char* ScriptDataImpl::ReadString(unsigned* start, int* chars) { void PartialParserRecorder::LogMessage(Scanner::Location loc, - const char* message, - Vector args) { + const char* message, + Vector args) { if (has_error()) return; preamble_[ScriptDataImpl::kHasErrorOffset] = true; function_store_.Reset(); @@ -594,12 +800,120 @@ unsigned* ScriptDataImpl::ReadAddress(int position) { } -Scope* Parser::NewScope(Scope* parent, Scope::Type type, bool inside_with) { +FunctionEntry PartialParserRecorder::LogFunction(int start) { +#ifdef DEBUG + ASSERT(start > prev_start); + prev_start = start; +#endif + if (!is_recording_) return FunctionEntry(); + FunctionEntry result(function_store_.AddBlock(FunctionEntry::kSize, 0)); + result.set_start_pos(start); + return result; +} + + +class AstBuildingParser : public Parser { + public: + AstBuildingParser(Handle