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

github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Dahl <ry@tinyclouds.org>2010-11-17 06:13:52 +0300
committerRyan Dahl <ry@tinyclouds.org>2010-11-17 06:14:14 +0300
commit03fa258df7d9e642c3ccac82d27c9c8167681cce (patch)
tree09dcbd2f391b2e81c0f50c9e2f37afd94fc1479f
parentcea3a95f9fe6faaa504542d4f03349739d08a0f3 (diff)
Revert "Upgrade V8 to 2.5.6"
This reverts commit 564a48643bd3edc6da845e458277a54c8068d0e2. Breaks cygwin
-rw-r--r--deps/v8/AUTHORS1
-rw-r--r--deps/v8/ChangeLog23
-rwxr-xr-xdeps/v8/include/v8-debug.h4
-rw-r--r--deps/v8/include/v8.h64
-rw-r--r--deps/v8/include/v8stdint.h53
-rwxr-xr-xdeps/v8/src/SConscript2
-rw-r--r--deps/v8/src/api.cc15
-rw-r--r--deps/v8/src/arm/assembler-arm.cc114
-rw-r--r--deps/v8/src/arm/assembler-arm.h41
-rw-r--r--deps/v8/src/arm/codegen-arm.cc67
-rw-r--r--deps/v8/src/arm/codegen-arm.h2
-rw-r--r--deps/v8/src/arm/constants-arm.h7
-rw-r--r--deps/v8/src/arm/full-codegen-arm.cc119
-rw-r--r--deps/v8/src/arm/ic-arm.cc4
-rw-r--r--deps/v8/src/arm/macro-assembler-arm.cc26
-rw-r--r--deps/v8/src/arm/simulator-arm.cc108
-rw-r--r--deps/v8/src/arm/simulator-arm.h3
-rw-r--r--deps/v8/src/assembler.cc49
-rw-r--r--deps/v8/src/assembler.h61
-rw-r--r--deps/v8/src/bignum.cc767
-rw-r--r--deps/v8/src/bignum.h140
-rw-r--r--deps/v8/src/checks.cc9
-rw-r--r--deps/v8/src/checks.h19
-rw-r--r--deps/v8/src/code-stubs.h28
-rw-r--r--deps/v8/src/codegen.cc32
-rwxr-xr-xdeps/v8/src/compiler.cc1
-rw-r--r--deps/v8/src/conversions.cc6
-rw-r--r--deps/v8/src/debug-debugger.js32
-rw-r--r--deps/v8/src/debug.cc1
-rw-r--r--deps/v8/src/double.h32
-rw-r--r--deps/v8/src/flag-definitions.h1
-rw-r--r--deps/v8/src/full-codegen.cc12
-rw-r--r--deps/v8/src/full-codegen.h4
-rw-r--r--deps/v8/src/global-handles.cc6
-rw-r--r--deps/v8/src/global-handles.h3
-rw-r--r--deps/v8/src/globals.h3
-rw-r--r--deps/v8/src/heap-inl.h7
-rw-r--r--deps/v8/src/heap.cc72
-rw-r--r--deps/v8/src/heap.h26
-rw-r--r--deps/v8/src/ia32/assembler-ia32.cc54
-rw-r--r--deps/v8/src/ia32/assembler-ia32.h17
-rw-r--r--deps/v8/src/ia32/code-stubs-ia32.cc20
-rw-r--r--deps/v8/src/ia32/codegen-ia32.cc90
-rw-r--r--deps/v8/src/ia32/codegen-ia32.h5
-rw-r--r--deps/v8/src/ia32/full-codegen-ia32.cc106
-rw-r--r--deps/v8/src/ia32/ic-ia32.cc1
-rw-r--r--deps/v8/src/ia32/macro-assembler-ia32.h2
-rw-r--r--deps/v8/src/ia32/stub-cache-ia32.cc178
-rw-r--r--deps/v8/src/jump-target-heavy.cc5
-rw-r--r--deps/v8/src/jump-target-light.cc5
-rw-r--r--deps/v8/src/objects-debug.cc5
-rw-r--r--deps/v8/src/objects-inl.h42
-rw-r--r--deps/v8/src/objects.h4
-rw-r--r--deps/v8/src/parser.cc1102
-rw-r--r--deps/v8/src/parser.h238
-rw-r--r--deps/v8/src/platform-linux.cc71
-rw-r--r--deps/v8/src/preparser.h1414
-rw-r--r--deps/v8/src/profile-generator.cc30
-rw-r--r--deps/v8/src/profile-generator.h2
-rw-r--r--deps/v8/src/regexp.js115
-rw-r--r--deps/v8/src/runtime.cc66
-rw-r--r--deps/v8/src/runtime.h5
-rw-r--r--deps/v8/src/scanner-base.cc167
-rw-r--r--deps/v8/src/scanner-base.h165
-rwxr-xr-xdeps/v8/src/scanner.cc136
-rw-r--r--deps/v8/src/scanner.h122
-rw-r--r--deps/v8/src/spaces.cc34
-rw-r--r--deps/v8/src/spaces.h12
-rw-r--r--deps/v8/src/string.js82
-rw-r--r--deps/v8/src/strtod.cc129
-rw-r--r--deps/v8/src/token.h2
-rw-r--r--deps/v8/src/utils.cc36
-rw-r--r--deps/v8/src/utils.h315
-rw-r--r--deps/v8/src/v8.h2
-rw-r--r--deps/v8/src/v8utils.h301
-rw-r--r--deps/v8/src/version.cc2
-rw-r--r--deps/v8/src/x64/assembler-x64.cc54
-rw-r--r--deps/v8/src/x64/assembler-x64.h15
-rw-r--r--deps/v8/src/x64/codegen-x64.cc82
-rw-r--r--deps/v8/src/x64/codegen-x64.h2
-rw-r--r--deps/v8/src/x64/full-codegen-x64.cc157
-rw-r--r--deps/v8/src/x64/ic-x64.cc1
-rw-r--r--deps/v8/test/cctest/SConscript1
-rw-r--r--deps/v8/test/cctest/test-assembler-arm.cc68
-rw-r--r--deps/v8/test/cctest/test-bignum.cc1502
-rw-r--r--deps/v8/test/cctest/test-debug.cc45
-rw-r--r--deps/v8/test/cctest/test-double.cc16
-rw-r--r--deps/v8/test/cctest/test-heap-profiler.cc35
-rw-r--r--deps/v8/test/cctest/test-mark-compact.cc4
-rwxr-xr-xdeps/v8/test/cctest/test-parsing.cc33
-rw-r--r--deps/v8/test/cctest/test-spaces.cc6
-rw-r--r--deps/v8/test/cctest/test-strtod.cc164
-rw-r--r--deps/v8/test/mjsunit/regress/regress-927.js33
-rw-r--r--deps/v8/test/mjsunit/regress/regress-conditional-position.js95
-rw-r--r--deps/v8/test/mjsunit/string-split.js91
-rw-r--r--deps/v8/tools/gyp/v8.gyp4
-rwxr-xr-xdeps/v8/tools/presubmit.py2
-rw-r--r--deps/v8/tools/v8.xcodeproj/project.pbxproj8
-rw-r--r--deps/v8/tools/visual_studio/v8_base.vcproj40
99 files changed, 2691 insertions, 6813 deletions
diff --git a/deps/v8/AUTHORS b/deps/v8/AUTHORS
index 68f9b63babb..3749cebcd17 100644
--- a/deps/v8/AUTHORS
+++ b/deps/v8/AUTHORS
@@ -9,7 +9,6 @@ ARM Ltd.
Hewlett-Packard Development Company, LP
Alexander Botero-Lowry <alexbl@FreeBSD.org>
-Alexandre Rames <alexandre.rames@arm.com>
Alexandre Vassalotti <avassalotti@gmail.com>
Andreas Anyuru <andreas.anyuru@gmail.com>
Burcu Dogan <burcujdogan@gmail.com>
diff --git a/deps/v8/ChangeLog b/deps/v8/ChangeLog
index 573ebb34977..69aff33d185 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 f17b848550d..4314727adc4 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 f6c3c8b3019..c7e4552b4d4 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 <stdio.h>
#ifdef _WIN32
+// When compiling on MinGW stdint.h is available.
+#ifdef __MINGW32__
+#include <stdint.h>
+#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 <stdint.h>
+
// 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<kPointerSize>::kSmiShiftSize;
-const int kSmiValueSize = SmiConstants<kPointerSize>::kSmiValueSize;
+const int kSmiShiftSize = SmiConstants<sizeof(void*)>::kSmiShiftSize;
+const int kSmiValueSize = SmiConstants<sizeof(void*)>::kSmiValueSize;
template <size_t ptr_size> 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<kPointerSize>::kStringResourceOffset;
+ InternalConstants<sizeof(void*)>::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<kPointerSize>::SmiToInt(value);
+ return SmiConstants<sizeof(void*)>::SmiToInt(value);
}
static inline int GetInstanceType(internal::Object* obj) {
@@ -3397,9 +3404,10 @@ class Internals {
uint8_t* addr = reinterpret_cast<uint8_t*>(ptr) + offset - kHeapObjectTag;
return *reinterpret_cast<T*>(addr);
}
+
};
-} // namespace internal
+}
template <class T>
@@ -3559,7 +3567,7 @@ Local<Value> 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<O*>(obj, offset);
O** result = HandleScope::CreateHandle(value);
return Local<Value>(reinterpret_cast<Value*>(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<O*>(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 50b4f29a64f..00000000000
--- 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 <stdio.h>
-
-#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 <stdint.h>
-
-#endif
-
-#endif // V8STDINT_H_
diff --git a/deps/v8/src/SConscript b/deps/v8/src/SConscript
index ad647dfa006..ef5485d8542 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 9da3346d794..617922dd5a7 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<Boolean> 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 4cb421c577e..ebbd9b1138a 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<Condition>(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 de3931c2cf9..5b647a7537e 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 d7fd9a49022..70ff244649c 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<Expression*>* args) {
}
+void CodeGenerator::GenerateRegExpCloneResult(ZoneList<Expression*>* 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 97e50b426be..e6fd6071e1d 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<Expression*>* args);
+ void GenerateRegExpCloneResult(ZoneList<Expression*>* args);
+
// Support for fast native caches.
void GenerateGetFromCache(ZoneList<Expression*>* args);
diff --git a/deps/v8/src/arm/constants-arm.h b/deps/v8/src/arm/constants-arm.h
index 36f6283c967..123c5e79720 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 bf27d0c7fee..9935e038f5c 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<Expression*>* 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<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop);
@@ -1712,15 +1710,13 @@ void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr,
// Code common for calls using the IC.
ZoneList<Expression*>* 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<Code> ic = CodeGenerator::ComputeKeyedCallInitialize(arg_count,
@@ -1736,13 +1732,11 @@ void FullCodeGenerator::EmitCallWithStub(Call* expr) {
// Code common for calls using the call stub.
ZoneList<Expression*>* 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<Expression*>* 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<Code> 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 4c1f9835f4d..a09afdf754e 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 d2c22af53df..7f6090bc50f 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 3ec5f449d8a..cb91520f3a5 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<FPSCRRoundingModes>((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<uint32_t>(val) :
- static_cast<int32_t>(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<uint32_t>(val) :
- static_cast<int32_t>(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<uint32_t>(val) :
- static_cast<int32_t>(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<uint32_t>(val) :
+ static_cast<int32_t>(val);
- int sint = unsigned_integer ? static_cast<uint32_t>(val) :
- static_cast<int32_t>(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<uint32_t>(val) :
+ static_cast<int32_t>(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 c37b3f7156d..3e023489eef 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 7493673e819..ce90dceacbc 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 09159fed08e..66811777fad 100644
--- a/deps/v8/src/assembler.h
+++ b/deps/v8/src/assembler.h
@@ -585,67 +585,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
static inline bool is_intn(int x, int n) {
diff --git a/deps/v8/src/bignum.cc b/deps/v8/src/bignum.cc
deleted file mode 100644
index dd1537a25a0..00000000000
--- 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<typename S>
-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<const char> 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<const char> 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<const char> 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<DoubleChunk>(factor) * bigits_[i] + carry;
- bigits_[i] = static_cast<Chunk>(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<DoubleChunk>(chunk1) * chunk2;
- bigit_index1--;
- bigit_index2++;
- }
- bigits_[i] = static_cast<Chunk>(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<DoubleChunk>(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<Chunk>(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<uint64_t>(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<typename S>
-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<DoubleChunk>(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<Chunk>((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 1d2bff61a5e..00000000000
--- 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<const char> value);
- void AssignHexString(Vector<const char> 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<Chunk> 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 1ab8802ec3f..b5df316d0f7 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 e0704774ba4..5ea59920ac1 100644
--- a/deps/v8/src/checks.h
+++ b/deps/v8/src/checks.h
@@ -30,7 +30,7 @@
#include <string.h>
-#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 <int> 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<intptr_t>(address) & HeapObjectTagMask()) == 0)
+ ASSERT((reinterpret_cast<intptr_t>(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 ec643534159..c0a8d3063c8 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<AccessorInfo> info_;
// The function to be called.
@@ -550,32 +550,6 @@ class ApiGetterEntryStub : public CodeStub {
};
-class ApiCallEntryStub : public CodeStub {
- public:
- ApiCallEntryStub(Handle<CallHandlerInfo> 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<CallHandlerInfo> 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<CallHandlerInfo> 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 e954dd66c1a..bda697abafd 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 29bbbc7034e..6f02960dda7 100755
--- a/deps/v8/src/compiler.cc
+++ b/deps/v8/src/compiler.cc
@@ -279,6 +279,7 @@ Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> 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 4cc67448508..790e807aef4 100644
--- a/deps/v8/src/conversions.cc
+++ b/deps/v8/src/conversions.cc
@@ -816,7 +816,7 @@ const char* IntToCString(int n, Vector<char> 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 d091991a119..0eab8d1b831 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 f3bf954da9b..24f04098610 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 65eded99893..e805173e07e 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 46feea77ac2..54501ec95d9 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 <n> allocations")
DEFINE_bool(trace_gc, false,
diff --git a/deps/v8/src/full-codegen.cc b/deps/v8/src/full-codegen.cc
index c770e189b35..97987c27a80 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<Expression*>* 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 a3270aa774e..201507b2af3 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 5339840988d..9ede9085283 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 37b2b44522e..659f86eca70 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 a74b6c79303..c218f80dc11 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 ba50c0f7358..15feb9d5fb9 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 134f40e5070..b037efd8045 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 c37ced39399..8ff2f5f3413 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 125f503bec3..019f478adc5 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> 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 79637a19010..5286788fa72 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 a7d658bdce5..b2b73926b9a 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 6f4ef87e85e..6d23dd7df99 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<Expression*>* args) {
}
+void CodeGenerator::GenerateRegExpCloneResult(ZoneList<Expression*>* 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 5a12e10ea5a..4594b19ddd2 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<Expression*>* args);
+ // Clone the result of a regexp function.
+ // Must be an object created by GenerateRegExpConstructResult with
+ // no extra properties.
+ void GenerateRegExpCloneResult(ZoneList<Expression*>* args);
+
// Support for fast native caches.
void GenerateGetFromCache(ZoneList<Expression*>* args);
diff --git a/deps/v8/src/ia32/full-codegen-ia32.cc b/deps/v8/src/ia32/full-codegen-ia32.cc
index 1ea719d7133..ee4e6458ae3 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<Expression*>* 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<Code> 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<Expression*>* 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<Code> 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<Expression*>* 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<Expression*>* 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<Code> 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 a0bc086d871..b5f4deefeb9 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 d65eebbc20c..7b9b843939e 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 f59928fe2bb..e3870883599 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<JSFunction>(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<CallHandlerInfo>(optimization.api_call_info()));
+ __ mov(ebx, FieldOperand(ecx, CallHandlerInfo::kCallbackOffset));
+ __ mov(Operand(esp, 3 * kPointerSize), ebx);
+ } else {
+ __ mov(Operand(esp, 3 * kPointerSize), Immediate(Handle<Object>(callback)));
+ }
Object* call_data = optimization.api_call_info()->data();
- Handle<CallHandlerInfo> 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<CallHandlerInfo>(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<Object>(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<Address>(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> code = Handle<Code>(
+ 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<Address>(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 c3c22f1ac63..e0585e79429 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 36dc176bce7..19f7bfec0a6 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 2b79016a012..c0e5610abaf 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 79d70e1141d..1852b549bf1 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 9d975ec5164..6029ad545b4 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 a0f3b7147f2..aad7a615a51 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<String> 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 <typename T>
+class ZoneListWrapper {
+ public:
+ ZoneListWrapper() : list_(NULL) { }
+ explicit ZoneListWrapper(int size) : list_(new ZoneList<T*>(size)) { }
+ void Add(T* that) { if (list_) list_->Add(that); }
+ int length() { return list_->length(); }
+ ZoneList<T*>* elements() { return list_; }
+ T* at(int index) { return list_->at(index); }
+ private:
+ ZoneList<T*>* 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<String> LookupSymbol(int index, Vector<const char> string) {
+ return Handle<String>();
+ }
+
+ virtual Handle<String> EmptySymbol() {
+ return Handle<String>();
+ }
+
+ 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<Expression*>* arguments,
+ int pos) {
+ return Call::sentinel();
+ }
+
+ virtual Statement* EmptyStatement() {
+ return NULL;
+ }
+
+ template <typename T> ZoneListWrapper<T> NewList(int size) {
+ return is_pre_parsing_ ? ZoneListWrapper<T>() : ZoneListWrapper<T>(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<const char> 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<unsigned> ExtractData() {
+ return Vector<unsigned>();
+ };
+};
+
+
+
+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<String> LookupSymbol(int symbol_id,
+ Vector<const char> 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<unsigned>(symbol_id)
+ >= static_cast<unsigned>(symbol_cache_.length())) {
+ return Factory::LookupSymbol(string);
+ }
+ return LookupCachedSymbol(symbol_id, string);
+ }
+
+ Handle<String> LookupCachedSymbol(int symbol_id,
Vector<const char> 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<unsigned>(symbol_id)
- >= static_cast<unsigned>(symbol_cache_.length())) {
- return Factory::LookupSymbol(string);
- }
- return LookupCachedSymbol(symbol_id, string);
-}
-
-
-Handle<String> Parser::LookupCachedSymbol(int symbol_id,
- Vector<const char> 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<String>::null(),
- symbol_id + 1 - symbol_cache_.length());
- }
- Handle<String> 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<String>::null(),
+ symbol_id + 1 - symbol_cache_.length());
+ }
+ Handle<String> 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<String> EmptySymbol() {
+ return Factory::empty_symbol();
+ }
-Vector<unsigned> PartialParserRecorder::ExtractData() {
- int function_size = function_store_.size();
- int total_size = ScriptDataImpl::kHeaderSize + function_size;
- Vector<unsigned> data = Vector<unsigned>::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<Expression*>* arguments,
+ int pos) {
+ return new Call(expression, arguments, pos);
+ }
+
+ virtual Statement* EmptyStatement();
+ private:
+ List<Handle<String> > symbol_cache_;
+};
-void CompleteParserRecorder::LogSymbol(int start, Vector<const char> 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<const char*> args);
+
+ virtual Vector<unsigned> ExtractData() {
+ int function_size = function_store_.size();
+ int total_size = ScriptDataImpl::kHeaderSize + function_size;
+ Vector<unsigned> data = Vector<unsigned>::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<int>(reinterpret_cast<intptr_t>(entry->value));
- if (id == 0) {
- // Put (symbol_id_ + 1) into entry and increment it.
- id = ++symbol_id_;
- entry->value = reinterpret_cast<void*>(id);
- Vector<Vector<const char> > 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<unsigned> 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<unsigned> data = Vector<unsigned>::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<bool>(preamble_[ScriptDataImpl::kHasErrorOffset]);
}
- if (!has_error()) {
- symbol_store_.WriteTo(
- Vector<byte>::cast(data.SubVector(symbol_start, total_size)));
+ bool is_recording() {
+ return is_recording_;
}
- return data;
-}
+
+ void WriteString(Vector<const char> str);
+
+ Collector<unsigned> 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<const char> literal) {
+ if (!is_recording_) return;
+ int hash = vector_hash(literal);
+ HashMap::Entry* entry = symbol_table_.Lookup(&literal, hash, true);
+ int id = static_cast<int>(reinterpret_cast<intptr_t>(entry->value));
+ if (id == 0) {
+ // Put (symbol_id_ + 1) into entry and increment it.
+ id = ++symbol_id_;
+ entry->value = reinterpret_cast<void*>(id);
+ Vector<Vector<const char> > symbol = symbol_entries_.AddBlock(1, literal);
+ entry->key = &symbol[0];
+ }
+ WriteNumber(id - 1);
+ }
+
+ virtual Vector<unsigned> 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<unsigned> data = Vector<unsigned>::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<byte>::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<const char> 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<const char>* string1 = reinterpret_cast<Vector<const char>* >(a);
+ Vector<const char>* string2 = reinterpret_cast<Vector<const char>* >(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<byte> symbol_store_;
+ Collector<Vector<const char> > 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<const char*> args) {
+ const char* message,
+ Vector<const char*> 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<Script> script, bool allow_natives_syntax,
+ v8::Extension* extension, ScriptDataImpl* pre_data)
+ : Parser(script,
+ allow_natives_syntax,
+ extension,
+ PARSE,
+ factory(),
+ log(),
+ pre_data),
+ factory_(pre_data ? pre_data->symbol_count() : 0) { }
+ virtual void ReportMessageAt(Scanner::Location loc, const char* message,
+ Vector<const char*> args);
+ virtual VariableProxy* Declare(Handle<String> name, Variable::Mode mode,
+ FunctionLiteral* fun, bool resolve, bool* ok);
+ AstBuildingParserFactory* factory() { return &factory_; }
+ ParserLog* log() { return &log_; }
+
+ private:
+ ParserLog log_;
+ AstBuildingParserFactory factory_;
+};
+
+
+class PreParser : public Parser {
+ public:
+ PreParser(Handle<Script> script, bool allow_natives_syntax,
+ v8::Extension* extension, ParserLog* recorder)
+ : Parser(script, allow_natives_syntax, extension, PREPARSE,
+ factory(), recorder, NULL),
+ factory_(true) { }
+ virtual void ReportMessageAt(Scanner::Location loc, const char* message,
+ Vector<const char*> args);
+ virtual VariableProxy* Declare(Handle<String> name, Variable::Mode mode,
+ FunctionLiteral* fun, bool resolve, bool* ok);
+ ParserFactory* factory() { return &factory_; }
+ virtual PartialParserRecorder* recorder() = 0;
+
+ private:
+ ParserFactory factory_;
+};
+
+
+class CompletePreParser : public PreParser {
+ public:
+ CompletePreParser(Handle<Script> script, bool allow_natives_syntax,
+ v8::Extension* extension)
+ : PreParser(script, allow_natives_syntax, extension, &recorder_),
+ recorder_() { }
+ virtual PartialParserRecorder* recorder() { return &recorder_; }
+ private:
+ CompleteParserRecorder recorder_;
+};
+
+
+class PartialPreParser : public PreParser {
+ public:
+ PartialPreParser(Handle<Script> script, bool allow_natives_syntax,
+ v8::Extension* extension)
+ : PreParser(script, allow_natives_syntax, extension, &recorder_),
+ recorder_() { }
+ virtual PartialParserRecorder* recorder() { return &recorder_; }
+ private:
+ PartialParserRecorder recorder_;
+};
+
+
+Scope* AstBuildingParserFactory::NewScope(Scope* parent, Scope::Type type,
+ bool inside_with) {
Scope* result = new Scope(parent, type);
result->Initialize(inside_with);
return result;
}
+
+Statement* AstBuildingParserFactory::EmptyStatement() {
+ // Use a statically allocated empty statement singleton to avoid
+ // allocating lots and lots of empty statements.
+ static v8::internal::EmptyStatement empty;
+ return &empty;
+}
+
+
+Scope* ParserFactory::NewScope(Scope* parent, Scope::Type type,
+ bool inside_with) {
+ ASSERT(parent != NULL);
+ parent->type_ = type;
+ // Initialize function is hijacked by DummyScope to increment scope depth.
+ parent->Initialize(inside_with);
+ return parent;
+}
+
+
+VariableProxy* PreParser::Declare(Handle<String> name, Variable::Mode mode,
+ FunctionLiteral* fun, bool resolve,
+ bool* ok) {
+ return NULL;
+}
+
+
+
// ----------------------------------------------------------------------------
// Target is a support class to facilitate manipulation of the
// Parser's target_stack_ (the stack of potential 'break' and
@@ -702,9 +1016,11 @@ class LexicalScope BASE_EMBEDDED {
Parser::Parser(Handle<Script> script,
bool allow_natives_syntax,
v8::Extension* extension,
+ ParserMode is_pre_parsing,
+ ParserFactory* factory,
+ ParserLog* log,
ScriptDataImpl* pre_data)
- : symbol_cache_(pre_data ? pre_data->symbol_count() : 0),
- script_(script),
+ : script_(script),
scanner_(),
top_scope_(NULL),
with_nesting_level_(0),
@@ -712,11 +1028,34 @@ Parser::Parser(Handle<Script> script,
target_stack_(NULL),
allow_natives_syntax_(allow_natives_syntax),
extension_(extension),
+ factory_(factory),
+ log_(log),
+ is_pre_parsing_(is_pre_parsing == PREPARSE),
pre_data_(pre_data),
fni_(NULL) {
}
+bool Parser::PreParseProgram(Handle<String> source,
+ unibrow::CharacterStream* stream) {
+ HistogramTimerScope timer(&Counters::pre_parse);
+ AssertNoZoneAllocation assert_no_zone_allocation;
+ AssertNoAllocation assert_no_allocation;
+ NoHandleAllocation no_handle_allocation;
+ scanner_.Initialize(source, stream, JAVASCRIPT);
+ ASSERT(target_stack_ == NULL);
+ mode_ = FLAG_lazy ? PARSE_LAZILY : PARSE_EAGERLY;
+ if (allow_natives_syntax_ || extension_ != NULL) mode_ = PARSE_EAGERLY;
+ DummyScope top_scope;
+ LexicalScope scope(&this->top_scope_, &this->with_nesting_level_, &top_scope);
+ TemporaryScope temp_scope(&this->temp_scope_);
+ ZoneListWrapper<Statement> processor;
+ bool ok = true;
+ ParseSourceElements(&processor, Token::EOS, &ok);
+ return !scanner().stack_overflow();
+}
+
+
FunctionLiteral* Parser::ParseProgram(Handle<String> source,
bool in_global_context) {
CompilationZoneScope zone_scope(DONT_DELETE_ON_EXIT);
@@ -739,21 +1078,21 @@ FunctionLiteral* Parser::ParseProgram(Handle<String> source,
in_global_context
? Scope::GLOBAL_SCOPE
: Scope::EVAL_SCOPE;
- Handle<String> no_name = Factory::empty_symbol();
+ Handle<String> no_name = factory()->EmptySymbol();
FunctionLiteral* result = NULL;
- { Scope* scope = NewScope(top_scope_, type, inside_with());
+ { Scope* scope = factory()->NewScope(top_scope_, type, inside_with());
LexicalScope lexical_scope(&this->top_scope_, &this->with_nesting_level_,
scope);
TemporaryScope temp_scope(&this->temp_scope_);
- ZoneList<Statement*>* body = new ZoneList<Statement*>(16);
+ ZoneListWrapper<Statement> body(16);
bool ok = true;
- ParseSourceElements(body, Token::EOS, &ok);
+ ParseSourceElements(&body, Token::EOS, &ok);
if (ok) {
- result = new FunctionLiteral(
+ result = NEW(FunctionLiteral(
no_name,
top_scope_,
- body,
+ body.elements(),
temp_scope.materialized_literal_count(),
temp_scope.expected_property_count(),
temp_scope.only_simple_this_property_assignments(),
@@ -762,7 +1101,7 @@ FunctionLiteral* Parser::ParseProgram(Handle<String> source,
0,
source->length(),
false,
- temp_scope.ContainsLoops());
+ temp_scope.ContainsLoops()));
} else if (scanner().stack_overflow()) {
Top::StackOverflow();
}
@@ -800,9 +1139,9 @@ FunctionLiteral* Parser::ParseLazy(Handle<SharedFunctionInfo> info) {
{
// Parse the function literal.
- Handle<String> no_name = Factory::empty_symbol();
+ Handle<String> no_name = factory()->EmptySymbol();
Scope* scope =
- NewScope(top_scope_, Scope::GLOBAL_SCOPE, inside_with());
+ factory()->NewScope(top_scope_, Scope::GLOBAL_SCOPE, inside_with());
LexicalScope lexical_scope(&this->top_scope_, &this->with_nesting_level_,
scope);
TemporaryScope temp_scope(&this->temp_scope_);
@@ -830,24 +1169,28 @@ FunctionLiteral* Parser::ParseLazy(Handle<SharedFunctionInfo> info) {
}
+void Parser::ReportMessage(const char* type, Vector<const char*> args) {
+ Scanner::Location source_location = scanner_.location();
+ ReportMessageAt(source_location, type, args);
+}
+
+
Handle<String> Parser::GetSymbol(bool* ok) {
+ if (is_pre_parsing_) {
+ log()->LogSymbol(scanner_.location().beg_pos, scanner_.literal());
+ return Handle<String>::null();
+ }
int symbol_id = -1;
if (pre_data() != NULL) {
symbol_id = pre_data()->GetSymbolIdentifier();
}
- return LookupSymbol(symbol_id, scanner_.literal());
+ return factory()->LookupSymbol(symbol_id, scanner_.literal());
}
-void Parser::ReportMessage(const char* type, Vector<const char*> args) {
- Scanner::Location source_location = scanner_.location();
- ReportMessageAt(source_location, type, args);
-}
-
-
-void Parser::ReportMessageAt(Scanner::Location source_location,
- const char* type,
- Vector<const char*> args) {
+void AstBuildingParser::ReportMessageAt(Scanner::Location source_location,
+ const char* type,
+ Vector<const char*> args) {
MessageLocation location(script_,
source_location.beg_pos, source_location.end_pos);
Handle<JSArray> array = Factory::NewJSArray(args.length());
@@ -859,6 +1202,13 @@ void Parser::ReportMessageAt(Scanner::Location source_location,
}
+void PreParser::ReportMessageAt(Scanner::Location source_location,
+ const char* type,
+ Vector<const char*> args) {
+ recorder()->LogMessage(source_location, type, args);
+}
+
+
// Base class containing common code for the different finder classes used by
// the parser.
class ParserFinder {
@@ -900,11 +1250,6 @@ class InitializationBlockFinder : public ParserFinder {
}
private:
- // The minimum number of contiguous assignment that will
- // be treated as an initialization block. Benchmarks show that
- // the overhead exceeds the savings below this limit.
- static const int kMinInitializationBlock = 3;
-
// Returns true if the expressions appear to denote the same object.
// In the context of initialization blocks, we only consider expressions
// of the form 'expr.x' or expr["x"].
@@ -957,7 +1302,7 @@ class InitializationBlockFinder : public ParserFinder {
}
void EndBlock() {
- if (block_size_ >= kMinInitializationBlock) {
+ if (block_size_ >= Parser::kMinInitializationBlock) {
first_in_block_->mark_block_start();
last_in_block_->mark_block_end();
}
@@ -1115,7 +1460,7 @@ class ThisNamedPropertyAssigmentFinder : public ParserFinder {
};
-void* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
+void* Parser::ParseSourceElements(ZoneListWrapper<Statement>* processor,
int end_token,
bool* ok) {
// SourceElements ::
@@ -1147,7 +1492,7 @@ void* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
}
// Propagate the collected information on this property assignments.
- if (top_scope_->is_function_scope()) {
+ if (!is_pre_parsing_ && top_scope_->is_function_scope()) {
bool only_simple_this_property_assignments =
this_property_assignment_finder.only_simple_this_property_assignments()
&& top_scope_->declarations()->length() == 0;
@@ -1200,7 +1545,7 @@ Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) {
case Token::SEMICOLON:
Next();
- return EmptyStatement();
+ return factory()->EmptyStatement();
case Token::IF:
stmt = ParseIfStatement(labels, ok);
@@ -1248,7 +1593,7 @@ Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) {
// one must take great care not to treat it as a
// fall-through. It is much easier just to wrap the entire
// try-statement in a statement block and put the labels there
- Block* result = new Block(labels, 1, false);
+ Block* result = NEW(Block(labels, 1, false));
Target target(&this->target_stack_, result);
TryStatement* statement = ParseTryStatement(CHECK_OK);
if (statement) {
@@ -1278,11 +1623,11 @@ Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) {
}
-VariableProxy* Parser::Declare(Handle<String> name,
- Variable::Mode mode,
- FunctionLiteral* fun,
- bool resolve,
- bool* ok) {
+VariableProxy* AstBuildingParser::Declare(Handle<String> name,
+ Variable::Mode mode,
+ FunctionLiteral* fun,
+ bool resolve,
+ bool* ok) {
Variable* var = NULL;
// If we are inside a function, a declaration of a variable
// is a truly local variable, and the scope of the variable
@@ -1337,13 +1682,13 @@ VariableProxy* Parser::Declare(Handle<String> name,
// a performance issue since it may lead to repeated
// Runtime::DeclareContextSlot() calls.
VariableProxy* proxy = top_scope_->NewUnresolved(name, inside_with());
- top_scope_->AddDeclaration(new Declaration(proxy, mode, fun));
+ top_scope_->AddDeclaration(NEW(Declaration(proxy, mode, fun)));
// For global const variables we bind the proxy to a variable.
if (mode == Variable::CONST && top_scope_->is_global_scope()) {
ASSERT(resolve); // should be set by all callers
Variable::Kind kind = Variable::NORMAL;
- var = new Variable(top_scope_, name, Variable::CONST, true, kind);
+ var = NEW(Variable(top_scope_, name, Variable::CONST, true, kind));
}
// If requested and we have a local variable, bind the proxy to the variable
@@ -1395,13 +1740,13 @@ Statement* Parser::ParseNativeDeclaration(bool* ok) {
while (!done) {
ParseIdentifier(CHECK_OK);
done = (peek() == Token::RPAREN);
- if (!done) {
- Expect(Token::COMMA, CHECK_OK);
- }
+ if (!done) Expect(Token::COMMA, CHECK_OK);
}
Expect(Token::RPAREN, CHECK_OK);
Expect(Token::SEMICOLON, CHECK_OK);
+ if (is_pre_parsing_) return NULL;
+
// Make sure that the function containing the native declaration
// isn't lazily compiled. The extension structures are only
// accessible while parsing the first time not when reparsing
@@ -1431,10 +1776,10 @@ Statement* Parser::ParseNativeDeclaration(bool* ok) {
// TODO(1240846): It's weird that native function declarations are
// introduced dynamically when we meet their declarations, whereas
// other functions are setup when entering the surrounding scope.
- SharedFunctionInfoLiteral* lit = new SharedFunctionInfoLiteral(shared);
+ SharedFunctionInfoLiteral* lit = NEW(SharedFunctionInfoLiteral(shared));
VariableProxy* var = Declare(name, Variable::VAR, NULL, true, CHECK_OK);
- return new ExpressionStatement(
- new Assignment(Token::INIT_VAR, var, lit, RelocInfo::kNoPosition));
+ return NEW(ExpressionStatement(
+ new Assignment(Token::INIT_VAR, var, lit, RelocInfo::kNoPosition)));
}
@@ -1452,7 +1797,7 @@ Statement* Parser::ParseFunctionDeclaration(bool* ok) {
// scope, we treat is as such and introduce the function with it's
// initial value upon entering the corresponding scope.
Declare(name, Variable::VAR, fun, true, CHECK_OK);
- return EmptyStatement();
+ return factory()->EmptyStatement();
}
@@ -1464,7 +1809,7 @@ Block* Parser::ParseBlock(ZoneStringList* labels, bool* ok) {
// (ECMA-262, 3rd, 12.2)
//
// Construct block expecting 16 statements.
- Block* result = new Block(labels, 16, false);
+ Block* result = NEW(Block(labels, 16, false));
Target target(&this->target_stack_, result);
Expect(Token::LBRACE, CHECK_OK);
while (peek() != Token::RBRACE) {
@@ -1523,7 +1868,7 @@ Block* Parser::ParseVariableDeclarations(bool accept_IN,
// is inside an initializer block, it is ignored.
//
// Create new block with one expected declaration.
- Block* block = new Block(NULL, 1, true);
+ Block* block = NEW(Block(NULL, 1, true));
VariableProxy* last_var = NULL; // the last variable declared
int nvars = 0; // the number of variables declared
do {
@@ -1614,14 +1959,14 @@ Block* Parser::ParseVariableDeclarations(bool accept_IN,
// browsers where the global object (window) has lots of
// properties defined in prototype objects.
- if (top_scope_->is_global_scope()) {
+ if (!is_pre_parsing_ && top_scope_->is_global_scope()) {
// Compute the arguments for the runtime call.
ZoneList<Expression*>* arguments = new ZoneList<Expression*>(2);
// Be careful not to assign a value to the global variable if
// we're in a with. The initialization value should not
// necessarily be stored in the global object in that case,
// which is why we need to generate a separate assignment node.
- arguments->Add(new Literal(name)); // we have at least 1 parameter
+ arguments->Add(NEW(Literal(name))); // we have at least 1 parameter
if (is_const || (value != NULL && !inside_with())) {
arguments->Add(value);
value = NULL; // zap the value to avoid the unnecessary assignment
@@ -1633,18 +1978,18 @@ Block* Parser::ParseVariableDeclarations(bool accept_IN,
CallRuntime* initialize;
if (is_const) {
initialize =
- new CallRuntime(
+ NEW(CallRuntime(
Factory::InitializeConstGlobal_symbol(),
Runtime::FunctionForId(Runtime::kInitializeConstGlobal),
- arguments);
+ arguments));
} else {
initialize =
- new CallRuntime(
+ NEW(CallRuntime(
Factory::InitializeVarGlobal_symbol(),
Runtime::FunctionForId(Runtime::kInitializeVarGlobal),
- arguments);
+ arguments));
}
- block->AddStatement(new ExpressionStatement(initialize));
+ block->AddStatement(NEW(ExpressionStatement(initialize)));
}
// Add an assignment node to the initialization statement block if
@@ -1659,8 +2004,8 @@ Block* Parser::ParseVariableDeclarations(bool accept_IN,
// the top context for variables). Sigh...
if (value != NULL) {
Token::Value op = (is_const ? Token::INIT_CONST : Token::INIT_VAR);
- Assignment* assignment = new Assignment(op, last_var, value, position);
- if (block) block->AddStatement(new ExpressionStatement(assignment));
+ Assignment* assignment = NEW(Assignment(op, last_var, value, position));
+ if (block) block->AddStatement(NEW(ExpressionStatement(assignment)));
}
if (fni_ != NULL) fni_->Leave();
@@ -1668,8 +2013,14 @@ Block* Parser::ParseVariableDeclarations(bool accept_IN,
if (!is_const && nvars == 1) {
// We have a single, non-const variable.
- ASSERT(last_var != NULL);
- *var = last_var;
+ if (is_pre_parsing_) {
+ // If we're preparsing then we need to set the var to something
+ // in order for for-in loops to parse correctly.
+ *var = ValidLeftHandSideSentinel::instance();
+ } else {
+ ASSERT(last_var != NULL);
+ *var = last_var;
+ }
}
return block;
@@ -1704,27 +2055,29 @@ Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels,
// labels requires nontrivial changes to the way scopes are
// structured. However, these are probably changes we want to
// make later anyway so we should go back and fix this then.
- if (ContainsLabel(labels, label) || TargetStackContainsLabel(label)) {
- SmartPointer<char> c_string = label->ToCString(DISALLOW_NULLS);
- const char* elms[2] = { "Label", *c_string };
- Vector<const char*> args(elms, 2);
- ReportMessage("redeclaration", args);
- *ok = false;
- return NULL;
+ if (!is_pre_parsing_) {
+ if (ContainsLabel(labels, label) || TargetStackContainsLabel(label)) {
+ SmartPointer<char> c_string = label->ToCString(DISALLOW_NULLS);
+ const char* elms[2] = { "Label", *c_string };
+ Vector<const char*> args(elms, 2);
+ ReportMessage("redeclaration", args);
+ *ok = false;
+ return NULL;
+ }
+ if (labels == NULL) labels = new ZoneStringList(4);
+ labels->Add(label);
+ // Remove the "ghost" variable that turned out to be a label
+ // from the top scope. This way, we don't try to resolve it
+ // during the scope processing.
+ top_scope_->RemoveUnresolved(var);
}
- if (labels == NULL) labels = new ZoneStringList(4);
- labels->Add(label);
- // Remove the "ghost" variable that turned out to be a label
- // from the top scope. This way, we don't try to resolve it
- // during the scope processing.
- top_scope_->RemoveUnresolved(var);
Expect(Token::COLON, CHECK_OK);
return ParseStatement(labels, ok);
}
// Parsed expression statement.
ExpectSemicolon(CHECK_OK);
- return new ExpressionStatement(expr);
+ return NEW(ExpressionStatement(expr));
}
@@ -1741,10 +2094,10 @@ IfStatement* Parser::ParseIfStatement(ZoneStringList* labels, bool* ok) {
if (peek() == Token::ELSE) {
Next();
else_statement = ParseStatement(labels, CHECK_OK);
- } else {
- else_statement = EmptyStatement();
+ } else if (!is_pre_parsing_) {
+ else_statement = factory()->EmptyStatement();
}
- return new IfStatement(condition, then_statement, else_statement);
+ return NEW(IfStatement(condition, then_statement, else_statement));
}
@@ -1760,17 +2113,19 @@ Statement* Parser::ParseContinueStatement(bool* ok) {
label = ParseIdentifier(CHECK_OK);
}
IterationStatement* target = NULL;
- target = LookupContinueTarget(label, CHECK_OK);
- if (target == NULL) {
- // Illegal continue statement. To be consistent with KJS we delay
- // reporting of the syntax error until runtime.
- Handle<String> error_type = Factory::illegal_continue_symbol();
- if (!label.is_null()) error_type = Factory::unknown_label_symbol();
- Expression* throw_error = NewThrowSyntaxError(error_type, label);
- return new ExpressionStatement(throw_error);
+ if (!is_pre_parsing_) {
+ target = LookupContinueTarget(label, CHECK_OK);
+ if (target == NULL) {
+ // Illegal continue statement. To be consistent with KJS we delay
+ // reporting of the syntax error until runtime.
+ Handle<String> error_type = Factory::illegal_continue_symbol();
+ if (!label.is_null()) error_type = Factory::unknown_label_symbol();
+ Expression* throw_error = NewThrowSyntaxError(error_type, label);
+ return NEW(ExpressionStatement(throw_error));
+ }
}
ExpectSemicolon(CHECK_OK);
- return new ContinueStatement(target);
+ return NEW(ContinueStatement(target));
}
@@ -1788,20 +2143,22 @@ Statement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) {
// Parse labeled break statements that target themselves into
// empty statements, e.g. 'l1: l2: l3: break l2;'
if (!label.is_null() && ContainsLabel(labels, label)) {
- return EmptyStatement();
+ return factory()->EmptyStatement();
}
BreakableStatement* target = NULL;
- target = LookupBreakTarget(label, CHECK_OK);
- if (target == NULL) {
- // Illegal break statement. To be consistent with KJS we delay
- // reporting of the syntax error until runtime.
- Handle<String> error_type = Factory::illegal_break_symbol();
- if (!label.is_null()) error_type = Factory::unknown_label_symbol();
- Expression* throw_error = NewThrowSyntaxError(error_type, label);
- return new ExpressionStatement(throw_error);
+ if (!is_pre_parsing_) {
+ target = LookupBreakTarget(label, CHECK_OK);
+ if (target == NULL) {
+ // Illegal break statement. To be consistent with KJS we delay
+ // reporting of the syntax error until runtime.
+ Handle<String> error_type = Factory::illegal_break_symbol();
+ if (!label.is_null()) error_type = Factory::unknown_label_symbol();
+ Expression* throw_error = NewThrowSyntaxError(error_type, label);
+ return NEW(ExpressionStatement(throw_error));
+ }
}
ExpectSemicolon(CHECK_OK);
- return new BreakStatement(target);
+ return NEW(BreakStatement(target));
}
@@ -1819,10 +2176,10 @@ Statement* Parser::ParseReturnStatement(bool* ok) {
// function. See ECMA-262, section 12.9, page 67.
//
// To be consistent with KJS we report the syntax error at runtime.
- if (!top_scope_->is_function_scope()) {
+ if (!is_pre_parsing_ && !top_scope_->is_function_scope()) {
Handle<String> type = Factory::illegal_return_symbol();
Expression* throw_error = NewThrowSyntaxError(type, Handle<Object>::null());
- return new ExpressionStatement(throw_error);
+ return NEW(ExpressionStatement(throw_error));
}
Token::Value tok = peek();
@@ -1831,12 +2188,12 @@ Statement* Parser::ParseReturnStatement(bool* ok) {
tok == Token::RBRACE ||
tok == Token::EOS) {
ExpectSemicolon(CHECK_OK);
- return new ReturnStatement(GetLiteralUndefined());
+ return NEW(ReturnStatement(GetLiteralUndefined()));
}
Expression* expr = ParseExpression(true, CHECK_OK);
ExpectSemicolon(CHECK_OK);
- return new ReturnStatement(expr);
+ return NEW(ReturnStatement(expr));
}
@@ -1845,7 +2202,7 @@ Block* Parser::WithHelper(Expression* obj,
bool is_catch_block,
bool* ok) {
// Parse the statement and collect escaping labels.
- ZoneList<BreakTarget*>* target_list = new ZoneList<BreakTarget*>(0);
+ ZoneList<BreakTarget*>* target_list = NEW(ZoneList<BreakTarget*>(0));
TargetCollector collector(target_list);
Statement* stat;
{ Target target(&this->target_stack_, &collector);
@@ -1857,21 +2214,21 @@ Block* Parser::WithHelper(Expression* obj,
// Create resulting block with two statements.
// 1: Evaluate the with expression.
// 2: The try-finally block evaluating the body.
- Block* result = new Block(NULL, 2, false);
+ Block* result = NEW(Block(NULL, 2, false));
if (result != NULL) {
- result->AddStatement(new WithEnterStatement(obj, is_catch_block));
+ result->AddStatement(NEW(WithEnterStatement(obj, is_catch_block)));
// Create body block.
- Block* body = new Block(NULL, 1, false);
+ Block* body = NEW(Block(NULL, 1, false));
body->AddStatement(stat);
// Create exit block.
- Block* exit = new Block(NULL, 1, false);
- exit->AddStatement(new WithExitStatement());
+ Block* exit = NEW(Block(NULL, 1, false));
+ exit->AddStatement(NEW(WithExitStatement()));
// Return a try-finally statement.
- TryFinallyStatement* wrapper = new TryFinallyStatement(body, exit);
+ TryFinallyStatement* wrapper = NEW(TryFinallyStatement(body, exit));
wrapper->set_escaping_targets(collector.targets());
result->AddStatement(wrapper);
}
@@ -1913,15 +2270,15 @@ CaseClause* Parser::ParseCaseClause(bool* default_seen_ptr, bool* ok) {
}
Expect(Token::COLON, CHECK_OK);
- ZoneList<Statement*>* statements = new ZoneList<Statement*>(5);
+ ZoneListWrapper<Statement> statements = factory()->NewList<Statement>(5);
while (peek() != Token::CASE &&
peek() != Token::DEFAULT &&
peek() != Token::RBRACE) {
Statement* stat = ParseStatement(NULL, CHECK_OK);
- statements->Add(stat);
+ statements.Add(stat);
}
- return new CaseClause(label, statements);
+ return NEW(CaseClause(label, statements.elements()));
}
@@ -1930,7 +2287,7 @@ SwitchStatement* Parser::ParseSwitchStatement(ZoneStringList* labels,
// SwitchStatement ::
// 'switch' '(' Expression ')' '{' CaseClause* '}'
- SwitchStatement* statement = new SwitchStatement(labels);
+ SwitchStatement* statement = NEW(SwitchStatement(labels));
Target target(&this->target_stack_, statement);
Expect(Token::SWITCH, CHECK_OK);
@@ -1939,15 +2296,15 @@ SwitchStatement* Parser::ParseSwitchStatement(ZoneStringList* labels,
Expect(Token::RPAREN, CHECK_OK);
bool default_seen = false;
- ZoneList<CaseClause*>* cases = new ZoneList<CaseClause*>(4);
+ ZoneListWrapper<CaseClause> cases = factory()->NewList<CaseClause>(4);
Expect(Token::LBRACE, CHECK_OK);
while (peek() != Token::RBRACE) {
CaseClause* clause = ParseCaseClause(&default_seen, CHECK_OK);
- cases->Add(clause);
+ cases.Add(clause);
}
Expect(Token::RBRACE, CHECK_OK);
- if (statement) statement->Initialize(tag, cases);
+ if (statement) statement->Initialize(tag, cases.elements());
return statement;
}
@@ -1966,7 +2323,7 @@ Statement* Parser::ParseThrowStatement(bool* ok) {
Expression* exception = ParseExpression(true, CHECK_OK);
ExpectSemicolon(CHECK_OK);
- return new ExpressionStatement(new Throw(exception, pos));
+ return NEW(ExpressionStatement(new Throw(exception, pos)));
}
@@ -1984,7 +2341,7 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
Expect(Token::TRY, CHECK_OK);
- ZoneList<BreakTarget*>* target_list = new ZoneList<BreakTarget*>(0);
+ ZoneList<BreakTarget*>* target_list = NEW(ZoneList<BreakTarget*>(0));
TargetCollector collector(target_list);
Block* try_block;
@@ -2007,7 +2364,7 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
// then we will need to collect jump targets from the catch block. Since
// we don't know yet if there will be a finally block, we always collect
// the jump targets.
- ZoneList<BreakTarget*>* catch_target_list = new ZoneList<BreakTarget*>(0);
+ ZoneList<BreakTarget*>* catch_target_list = NEW(ZoneList<BreakTarget*>(0));
TargetCollector catch_collector(catch_target_list);
bool has_catch = false;
if (tok == Token::CATCH) {
@@ -2022,8 +2379,8 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
// Allocate a temporary for holding the finally state while
// executing the finally block.
catch_var = top_scope_->NewTemporary(Factory::catch_var_symbol());
- Literal* name_literal = new Literal(name);
- Expression* obj = new CatchExtensionObject(name_literal, catch_var);
+ Literal* name_literal = NEW(Literal(name));
+ Expression* obj = NEW(CatchExtensionObject(name_literal, catch_var));
{ Target target(&this->target_stack_, &catch_collector);
catch_block = WithHelper(obj, NULL, true, CHECK_OK);
}
@@ -2046,28 +2403,30 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
// to:
// 'try { try { } catch { } } finally { }'
- if (catch_block != NULL && finally_block != NULL) {
+ if (!is_pre_parsing_ && catch_block != NULL && finally_block != NULL) {
TryCatchStatement* statement =
- new TryCatchStatement(try_block, catch_var, catch_block);
+ NEW(TryCatchStatement(try_block, catch_var, catch_block));
statement->set_escaping_targets(collector.targets());
- try_block = new Block(NULL, 1, false);
+ try_block = NEW(Block(NULL, 1, false));
try_block->AddStatement(statement);
catch_block = NULL;
}
TryStatement* result = NULL;
- if (catch_block != NULL) {
- ASSERT(finally_block == NULL);
- result = new TryCatchStatement(try_block, catch_var, catch_block);
- result->set_escaping_targets(collector.targets());
- } else {
- ASSERT(finally_block != NULL);
- result = new TryFinallyStatement(try_block, finally_block);
- // Add the jump targets of the try block and the catch block.
- for (int i = 0; i < collector.targets()->length(); i++) {
- catch_collector.AddTarget(collector.targets()->at(i));
+ if (!is_pre_parsing_) {
+ if (catch_block != NULL) {
+ ASSERT(finally_block == NULL);
+ result = NEW(TryCatchStatement(try_block, catch_var, catch_block));
+ result->set_escaping_targets(collector.targets());
+ } else {
+ ASSERT(finally_block != NULL);
+ result = NEW(TryFinallyStatement(try_block, finally_block));
+ // Add the jump targets of the try block and the catch block.
+ for (int i = 0; i < collector.targets()->length(); i++) {
+ catch_collector.AddTarget(collector.targets()->at(i));
+ }
+ result->set_escaping_targets(catch_collector.targets());
}
- result->set_escaping_targets(catch_collector.targets());
}
return result;
@@ -2080,7 +2439,7 @@ DoWhileStatement* Parser::ParseDoWhileStatement(ZoneStringList* labels,
// 'do' Statement 'while' '(' Expression ')' ';'
temp_scope_->AddLoop();
- DoWhileStatement* loop = new DoWhileStatement(labels);
+ DoWhileStatement* loop = NEW(DoWhileStatement(labels));
Target target(&this->target_stack_, loop);
Expect(Token::DO, CHECK_OK);
@@ -2113,7 +2472,7 @@ WhileStatement* Parser::ParseWhileStatement(ZoneStringList* labels, bool* ok) {
// 'while' '(' Expression ')' Statement
temp_scope_->AddLoop();
- WhileStatement* loop = new WhileStatement(labels);
+ WhileStatement* loop = NEW(WhileStatement(labels));
Target target(&this->target_stack_, loop);
Expect(Token::WHILE, CHECK_OK);
@@ -2143,7 +2502,7 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
Block* variable_statement =
ParseVariableDeclarations(false, &each, CHECK_OK);
if (peek() == Token::IN && each != NULL) {
- ForInStatement* loop = new ForInStatement(labels);
+ ForInStatement* loop = NEW(ForInStatement(labels));
Target target(&this->target_stack_, loop);
Expect(Token::IN, CHECK_OK);
@@ -2151,12 +2510,17 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
Expect(Token::RPAREN, CHECK_OK);
Statement* body = ParseStatement(NULL, CHECK_OK);
- loop->Initialize(each, enumerable, body);
- Block* result = new Block(NULL, 2, false);
- result->AddStatement(variable_statement);
- result->AddStatement(loop);
- // Parsed for-in loop w/ variable/const declaration.
- return result;
+ if (is_pre_parsing_) {
+ return NULL;
+ } else {
+ loop->Initialize(each, enumerable, body);
+ Block* result = NEW(Block(NULL, 2, false));
+ result->AddStatement(variable_statement);
+ result->AddStatement(loop);
+ // Parsed for-in loop w/ variable/const declaration.
+ return result;
+ }
+
} else {
init = variable_statement;
}
@@ -2172,7 +2536,7 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
Handle<String> type = Factory::invalid_lhs_in_for_in_symbol();
expression = NewThrowReferenceError(type);
}
- ForInStatement* loop = new ForInStatement(labels);
+ ForInStatement* loop = NEW(ForInStatement(labels));
Target target(&this->target_stack_, loop);
Expect(Token::IN, CHECK_OK);
@@ -2185,13 +2549,13 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
return loop;
} else {
- init = new ExpressionStatement(expression);
+ init = NEW(ExpressionStatement(expression));
}
}
}
// Standard 'for' loop
- ForStatement* loop = new ForStatement(labels);
+ ForStatement* loop = NEW(ForStatement(labels));
Target target(&this->target_stack_, loop);
// Parsed initializer at this point.
@@ -2207,7 +2571,7 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
Statement* next = NULL;
if (peek() != Token::RPAREN) {
Expression* exp = ParseExpression(true, CHECK_OK);
- next = new ExpressionStatement(exp);
+ next = NEW(ExpressionStatement(exp));
}
Expect(Token::RPAREN, CHECK_OK);
@@ -2228,7 +2592,7 @@ Expression* Parser::ParseExpression(bool accept_IN, bool* ok) {
Expect(Token::COMMA, CHECK_OK);
int position = scanner().location().beg_pos;
Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
- result = new BinaryOperation(Token::COMMA, result, right, position);
+ result = NEW(BinaryOperation(Token::COMMA, result, right, position));
}
return result;
}
@@ -2288,7 +2652,7 @@ Expression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) {
fni_->Leave();
}
- return new Assignment(op, expression, right, pos);
+ return NEW(Assignment(op, expression, right, pos));
}
@@ -2310,8 +2674,8 @@ Expression* Parser::ParseConditionalExpression(bool accept_IN, bool* ok) {
Expect(Token::COLON, CHECK_OK);
int right_position = scanner().peek_location().beg_pos;
Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
- return new Conditional(expression, left, right,
- left_position, right_position);
+ return NEW(Conditional(expression, left, right,
+ left_position, right_position));
}
@@ -2418,12 +2782,12 @@ Expression* Parser::ParseBinaryExpression(int prec, bool accept_IN, bool* ok) {
x = NewCompareNode(cmp, x, y, position);
if (cmp != op) {
// The comparison was negated - add a NOT.
- x = new UnaryOperation(Token::NOT, x);
+ x = NEW(UnaryOperation(Token::NOT, x));
}
} else {
// We have a "normal" binary operation.
- x = new BinaryOperation(op, x, y, position);
+ x = NEW(BinaryOperation(op, x, y, position));
}
}
}
@@ -2436,19 +2800,19 @@ Expression* Parser::NewCompareNode(Token::Value op,
Expression* y,
int position) {
ASSERT(op != Token::NE && op != Token::NE_STRICT);
- if (op == Token::EQ || op == Token::EQ_STRICT) {
+ if (!is_pre_parsing_ && (op == Token::EQ || op == Token::EQ_STRICT)) {
bool is_strict = (op == Token::EQ_STRICT);
Literal* x_literal = x->AsLiteral();
if (x_literal != NULL && x_literal->IsNull()) {
- return new CompareToNull(is_strict, y);
+ return NEW(CompareToNull(is_strict, y));
}
Literal* y_literal = y->AsLiteral();
if (y_literal != NULL && y_literal->IsNull()) {
- return new CompareToNull(is_strict, x);
+ return NEW(CompareToNull(is_strict, x));
}
}
- return new CompareOperation(op, x, y, position);
+ return NEW(CompareOperation(op, x, y, position));
}
@@ -2485,7 +2849,7 @@ Expression* Parser::ParseUnaryExpression(bool* ok) {
}
}
- return new UnaryOperation(op, expression);
+ return NEW(UnaryOperation(op, expression));
} else if (Token::IsCountOp(op)) {
op = Next();
@@ -2499,8 +2863,8 @@ Expression* Parser::ParseUnaryExpression(bool* ok) {
expression = NewThrowReferenceError(type);
}
int position = scanner().location().beg_pos;
- IncrementOperation* increment = new IncrementOperation(op, expression);
- return new CountOperation(true /* prefix */, increment, position);
+ IncrementOperation* increment = NEW(IncrementOperation(op, expression));
+ return NEW(CountOperation(true /* prefix */, increment, position));
} else {
return ParsePostfixExpression(ok);
@@ -2524,8 +2888,8 @@ Expression* Parser::ParsePostfixExpression(bool* ok) {
}
Token::Value next = Next();
int position = scanner().location().beg_pos;
- IncrementOperation* increment = new IncrementOperation(next, expression);
- expression = new CountOperation(false /* postfix */, increment, position);
+ IncrementOperation* increment = NEW(IncrementOperation(next, expression));
+ expression = NEW(CountOperation(false /* postfix */, increment, position));
}
return expression;
}
@@ -2548,7 +2912,7 @@ Expression* Parser::ParseLeftHandSideExpression(bool* ok) {
Consume(Token::LBRACK);
int pos = scanner().location().beg_pos;
Expression* index = ParseExpression(true, CHECK_OK);
- result = new Property(result, index, pos);
+ result = factory()->NewProperty(result, index, pos);
Expect(Token::RBRACK, CHECK_OK);
break;
}
@@ -2565,15 +2929,17 @@ Expression* Parser::ParseLeftHandSideExpression(bool* ok) {
// declared in the current scope chain. These calls are marked as
// potentially direct eval calls. Whether they are actually direct calls
// to eval is determined at run time.
- VariableProxy* callee = result->AsVariableProxy();
- if (callee != NULL && callee->IsVariable(Factory::eval_symbol())) {
- Handle<String> name = callee->name();
- Variable* var = top_scope_->Lookup(name);
- if (var == NULL) {
- top_scope_->RecordEvalCall();
+ if (!is_pre_parsing_) {
+ VariableProxy* callee = result->AsVariableProxy();
+ if (callee != NULL && callee->IsVariable(Factory::eval_symbol())) {
+ Handle<String> name = callee->name();
+ Variable* var = top_scope_->Lookup(name);
+ if (var == NULL) {
+ top_scope_->RecordEvalCall();
+ }
}
}
- result = NewCall(result, args, pos);
+ result = factory()->NewCall(result, args, pos);
break;
}
@@ -2581,7 +2947,7 @@ Expression* Parser::ParseLeftHandSideExpression(bool* ok) {
Consume(Token::PERIOD);
int pos = scanner().location().beg_pos;
Handle<String> name = ParseIdentifierName(CHECK_OK);
- result = new Property(result, new Literal(name), pos);
+ result = factory()->NewProperty(result, NEW(Literal(name)), pos);
if (fni_ != NULL) fni_->PushLiteralName(name);
break;
}
@@ -2593,6 +2959,7 @@ Expression* Parser::ParseLeftHandSideExpression(bool* ok) {
}
+
Expression* Parser::ParseNewPrefix(PositionStack* stack, bool* ok) {
// NewExpression ::
// ('new')+ MemberExpression
@@ -2617,7 +2984,7 @@ Expression* Parser::ParseNewPrefix(PositionStack* stack, bool* ok) {
if (!stack->is_empty()) {
int last = stack->pop();
- result = new CallNew(result, new ZoneList<Expression*>(0), last);
+ result = NEW(CallNew(result, new ZoneList<Expression*>(0), last));
}
return result;
}
@@ -2659,7 +3026,7 @@ Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack,
Consume(Token::LBRACK);
int pos = scanner().location().beg_pos;
Expression* index = ParseExpression(true, CHECK_OK);
- result = new Property(result, index, pos);
+ result = factory()->NewProperty(result, index, pos);
Expect(Token::RBRACK, CHECK_OK);
break;
}
@@ -2667,7 +3034,7 @@ Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack,
Consume(Token::PERIOD);
int pos = scanner().location().beg_pos;
Handle<String> name = ParseIdentifierName(CHECK_OK);
- result = new Property(result, new Literal(name), pos);
+ result = factory()->NewProperty(result, NEW(Literal(name)), pos);
if (fni_ != NULL) fni_->PushLiteralName(name);
break;
}
@@ -2676,7 +3043,7 @@ Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack,
// Consume one of the new prefixes (already parsed).
ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
int last = stack->pop();
- result = new CallNew(result, args, last);
+ result = NEW(CallNew(result, args, last));
break;
}
default:
@@ -2695,7 +3062,7 @@ DebuggerStatement* Parser::ParseDebuggerStatement(bool* ok) {
Expect(Token::DEBUGGER, CHECK_OK);
ExpectSemicolon(CHECK_OK);
- return new DebuggerStatement();
+ return NEW(DebuggerStatement());
}
@@ -2753,30 +3120,38 @@ Expression* Parser::ParsePrimaryExpression(bool* ok) {
switch (peek()) {
case Token::THIS: {
Consume(Token::THIS);
- VariableProxy* recv = top_scope_->receiver();
- result = recv;
+ if (is_pre_parsing_) {
+ result = VariableProxySentinel::this_proxy();
+ } else {
+ VariableProxy* recv = top_scope_->receiver();
+ result = recv;
+ }
break;
}
case Token::NULL_LITERAL:
Consume(Token::NULL_LITERAL);
- result = new Literal(Factory::null_value());
+ result = NEW(Literal(Factory::null_value()));
break;
case Token::TRUE_LITERAL:
Consume(Token::TRUE_LITERAL);
- result = new Literal(Factory::true_value());
+ result = NEW(Literal(Factory::true_value()));
break;
case Token::FALSE_LITERAL:
Consume(Token::FALSE_LITERAL);
- result = new Literal(Factory::false_value());
+ result = NEW(Literal(Factory::false_value()));
break;
case Token::IDENTIFIER: {
Handle<String> name = ParseIdentifier(CHECK_OK);
if (fni_ != NULL) fni_->PushVariableName(name);
- result = top_scope_->NewUnresolved(name, inside_with());
+ if (is_pre_parsing_) {
+ result = VariableProxySentinel::identifier_proxy();
+ } else {
+ result = top_scope_->NewUnresolved(name, inside_with());
+ }
break;
}
@@ -2791,7 +3166,7 @@ Expression* Parser::ParsePrimaryExpression(bool* ok) {
case Token::STRING: {
Consume(Token::STRING);
Handle<String> symbol = GetSymbol(CHECK_OK);
- result = new Literal(symbol);
+ result = NEW(Literal(symbol));
if (fni_ != NULL) fni_->PushLiteralName(symbol);
break;
}
@@ -2869,7 +3244,7 @@ Expression* Parser::ParseArrayLiteral(bool* ok) {
// ArrayLiteral ::
// '[' Expression? (',' Expression?)* ']'
- ZoneList<Expression*>* values = new ZoneList<Expression*>(4);
+ ZoneListWrapper<Expression> values = factory()->NewList<Expression>(4);
Expect(Token::LBRACK, CHECK_OK);
while (peek() != Token::RBRACK) {
Expression* elem;
@@ -2878,7 +3253,7 @@ Expression* Parser::ParseArrayLiteral(bool* ok) {
} else {
elem = ParseAssignmentExpression(true, CHECK_OK);
}
- values->Add(elem);
+ values.Add(elem);
if (peek() != Token::RBRACK) {
Expect(Token::COMMA, CHECK_OK);
}
@@ -2888,19 +3263,21 @@ Expression* Parser::ParseArrayLiteral(bool* ok) {
// Update the scope information before the pre-parsing bailout.
int literal_index = temp_scope_->NextMaterializedLiteralIndex();
+ if (is_pre_parsing_) return NULL;
+
// Allocate a fixed array with all the literals.
Handle<FixedArray> literals =
- Factory::NewFixedArray(values->length(), TENURED);
+ Factory::NewFixedArray(values.length(), TENURED);
// Fill in the literals.
bool is_simple = true;
int depth = 1;
- for (int i = 0, n = values->length(); i < n; i++) {
- MaterializedLiteral* m_literal = values->at(i)->AsMaterializedLiteral();
+ for (int i = 0; i < values.length(); i++) {
+ MaterializedLiteral* m_literal = values.at(i)->AsMaterializedLiteral();
if (m_literal != NULL && m_literal->depth() + 1 > depth) {
depth = m_literal->depth() + 1;
}
- Handle<Object> boilerplate_value = GetBoilerplateValue(values->at(i));
+ Handle<Object> boilerplate_value = GetBoilerplateValue(values.at(i));
if (boilerplate_value->IsUndefined()) {
literals->set_the_hole(i);
is_simple = false;
@@ -2911,12 +3288,12 @@ Expression* Parser::ParseArrayLiteral(bool* ok) {
// Simple and shallow arrays can be lazily copied, we transform the
// elements array to a copy-on-write array.
- if (is_simple && depth == 1 && values->length() > 0) {
+ if (is_simple && depth == 1 && values.length() > 0) {
literals->set_map(Heap::fixed_cow_array_map());
}
- return new ArrayLiteral(literals, values,
- literal_index, is_simple, depth);
+ return NEW(ArrayLiteral(literals, values.elements(),
+ literal_index, is_simple, depth));
}
@@ -3063,7 +3440,7 @@ ObjectLiteral::Property* Parser::ParseObjectLiteralGetSet(bool is_getter,
DECLARATION,
CHECK_OK);
ObjectLiteral::Property* property =
- new ObjectLiteral::Property(is_getter, value);
+ NEW(ObjectLiteral::Property(is_getter, value));
return property;
} else {
ReportUnexpectedToken(next);
@@ -3080,8 +3457,8 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
// | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
// )*[','] '}'
- ZoneList<ObjectLiteral::Property*>* properties =
- new ZoneList<ObjectLiteral::Property*>(4);
+ ZoneListWrapper<ObjectLiteral::Property> properties =
+ factory()->NewList<ObjectLiteral::Property>(4);
int number_of_boilerplate_properties = 0;
Expect(Token::LBRACE, CHECK_OK);
@@ -3104,7 +3481,7 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
if (IsBoilerplateProperty(property)) {
number_of_boilerplate_properties++;
}
- properties->Add(property);
+ properties.Add(property);
if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
if (fni_ != NULL) {
@@ -3115,7 +3492,7 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
}
// Failed to parse as get/set property, so it's just a property
// called "get" or "set".
- key = new Literal(id);
+ key = NEW(Literal(id));
break;
}
case Token::STRING: {
@@ -3127,7 +3504,7 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
key = NewNumberLiteral(index);
break;
}
- key = new Literal(string);
+ key = NEW(Literal(string));
break;
}
case Token::NUMBER: {
@@ -3141,7 +3518,7 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
if (Token::IsKeyword(next)) {
Consume(next);
Handle<String> string = GetSymbol(CHECK_OK);
- key = new Literal(string);
+ key = NEW(Literal(string));
} else {
// Unexpected token.
Token::Value next = Next();
@@ -3155,11 +3532,11 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
Expression* value = ParseAssignmentExpression(true, CHECK_OK);
ObjectLiteral::Property* property =
- new ObjectLiteral::Property(key, value);
+ NEW(ObjectLiteral::Property(key, value));
// Count CONSTANT or COMPUTED properties to maintain the enumeration order.
if (IsBoilerplateProperty(property)) number_of_boilerplate_properties++;
- properties->Add(property);
+ properties.Add(property);
// TODO(1240767): Consider allowing trailing comma.
if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
@@ -3172,6 +3549,7 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
Expect(Token::RBRACE, CHECK_OK);
// Computation of literal_index must happen before pre parse bailout.
int literal_index = temp_scope_->NextMaterializedLiteralIndex();
+ if (is_pre_parsing_) return NULL;
Handle<FixedArray> constant_properties =
Factory::NewFixedArray(number_of_boilerplate_properties * 2, TENURED);
@@ -3179,13 +3557,13 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
bool is_simple = true;
bool fast_elements = true;
int depth = 1;
- BuildObjectLiteralConstantProperties(properties,
+ BuildObjectLiteralConstantProperties(properties.elements(),
constant_properties,
&is_simple,
&fast_elements,
&depth);
return new ObjectLiteral(constant_properties,
- properties,
+ properties.elements(),
literal_index,
is_simple,
fast_elements,
@@ -3203,6 +3581,19 @@ Expression* Parser::ParseRegExpLiteral(bool seen_equal, bool* ok) {
int literal_index = temp_scope_->NextMaterializedLiteralIndex();
+ if (is_pre_parsing_) {
+ // If we're preparsing we just do all the parsing stuff without
+ // building anything.
+ if (!scanner_.ScanRegExpFlags()) {
+ Next();
+ ReportMessage("invalid_regexp_flags", Vector<const char*>::empty());
+ *ok = false;
+ return NULL;
+ }
+ Next();
+ return NULL;
+ }
+
Handle<String> js_pattern =
Factory::NewStringFromUtf8(scanner_.next_literal(), TENURED);
scanner_.ScanRegExpFlags();
@@ -3218,17 +3609,17 @@ ZoneList<Expression*>* Parser::ParseArguments(bool* ok) {
// Arguments ::
// '(' (AssignmentExpression)*[','] ')'
- ZoneList<Expression*>* result = new ZoneList<Expression*>(4);
+ ZoneListWrapper<Expression> result = factory()->NewList<Expression>(4);
Expect(Token::LPAREN, CHECK_OK);
bool done = (peek() == Token::RPAREN);
while (!done) {
Expression* argument = ParseAssignmentExpression(true, CHECK_OK);
- result->Add(argument);
+ result.Add(argument);
done = (peek() == Token::RPAREN);
if (!done) Expect(Token::COMMA, CHECK_OK);
}
Expect(Token::RPAREN, CHECK_OK);
- return result;
+ return result.elements();
}
@@ -3244,9 +3635,9 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name,
// this is the actual function name, otherwise this is the name of the
// variable declared and initialized with the function (expression). In
// that case, we don't have a function name (it's empty).
- Handle<String> name = is_named ? var_name : Factory::empty_symbol();
+ Handle<String> name = is_named ? var_name : factory()->EmptySymbol();
// The function name, if any.
- Handle<String> function_name = Factory::empty_symbol();
+ Handle<String> function_name = factory()->EmptySymbol();
if (is_named && (type == EXPRESSION || type == NESTED)) {
function_name = name;
}
@@ -3254,7 +3645,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name,
int num_parameters = 0;
// Parse function body.
{ Scope* scope =
- NewScope(top_scope_, Scope::FUNCTION_SCOPE, inside_with());
+ factory()->NewScope(top_scope_, Scope::FUNCTION_SCOPE, inside_with());
LexicalScope lexical_scope(&this->top_scope_, &this->with_nesting_level_,
scope);
TemporaryScope temp_scope(&this->temp_scope_);
@@ -3267,16 +3658,18 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name,
bool done = (peek() == Token::RPAREN);
while (!done) {
Handle<String> param_name = ParseIdentifier(CHECK_OK);
- top_scope_->AddParameter(top_scope_->DeclareLocal(param_name,
- Variable::VAR));
- num_parameters++;
+ if (!is_pre_parsing_) {
+ top_scope_->AddParameter(top_scope_->DeclareLocal(param_name,
+ Variable::VAR));
+ num_parameters++;
+ }
done = (peek() == Token::RPAREN);
if (!done) Expect(Token::COMMA, CHECK_OK);
}
Expect(Token::RPAREN, CHECK_OK);
Expect(Token::LBRACE, CHECK_OK);
- ZoneList<Statement*>* body = new ZoneList<Statement*>(8);
+ ZoneListWrapper<Statement> body = factory()->NewList<Statement>(8);
// If we have a named function expression, we add a local variable
// declaration to the body of the function with the name of the
@@ -3284,15 +3677,17 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name,
// NOTE: We create a proxy and resolve it here so that in the
// future we can change the AST to only refer to VariableProxies
// instead of Variables and Proxis as is the case now.
- if (!function_name.is_null() && function_name->length() > 0) {
+ if (!is_pre_parsing_
+ && !function_name.is_null()
+ && function_name->length() > 0) {
Variable* fvar = top_scope_->DeclareFunctionVar(function_name);
VariableProxy* fproxy =
top_scope_->NewUnresolved(function_name, inside_with());
fproxy->BindTo(fvar);
- body->Add(new ExpressionStatement(
- new Assignment(Token::INIT_CONST, fproxy,
- new ThisFunction(),
- RelocInfo::kNoPosition)));
+ body.Add(new ExpressionStatement(
+ new Assignment(Token::INIT_CONST, fproxy,
+ NEW(ThisFunction()),
+ RelocInfo::kNoPosition)));
}
// Determine if the function will be lazily compiled. The mode can
@@ -3324,8 +3719,12 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name,
this_property_assignments = Factory::empty_fixed_array();
Expect(Token::RBRACE, CHECK_OK);
} else {
- ParseSourceElements(body, Token::RBRACE, CHECK_OK);
-
+ FunctionEntry entry;
+ if (is_lazily_compiled) entry = log()->LogFunction(function_block_pos);
+ {
+ ConditionalLogPauseScope pause_if(is_lazily_compiled, log());
+ ParseSourceElements(&body, Token::RBRACE, CHECK_OK);
+ }
materialized_literal_count = temp_scope.materialized_literal_count();
expected_property_count = temp_scope.expected_property_count();
only_simple_this_property_assignments =
@@ -3334,12 +3733,19 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name,
Expect(Token::RBRACE, CHECK_OK);
end_pos = scanner_.location().end_pos;
+ if (entry.is_valid()) {
+ ASSERT(is_lazily_compiled);
+ ASSERT(is_pre_parsing_);
+ entry.set_end_pos(end_pos);
+ entry.set_literal_count(materialized_literal_count);
+ entry.set_property_count(expected_property_count);
+ }
}
FunctionLiteral* function_literal =
- new FunctionLiteral(name,
+ NEW(FunctionLiteral(name,
top_scope_,
- body,
+ body.elements(),
materialized_literal_count,
expected_property_count,
only_simple_this_property_assignments,
@@ -3348,8 +3754,10 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name,
start_pos,
end_pos,
function_name->length() > 0,
- temp_scope.ContainsLoops());
- function_literal->set_function_token_position(function_token_position);
+ temp_scope.ContainsLoops()));
+ if (!is_pre_parsing_) {
+ function_literal->set_function_token_position(function_token_position);
+ }
if (fni_ != NULL && !is_named) fni_->AddFunction(function_literal);
return function_literal;
@@ -3364,6 +3772,7 @@ Expression* Parser::ParseV8Intrinsic(bool* ok) {
Expect(Token::MOD, CHECK_OK);
Handle<String> name = ParseIdentifier(CHECK_OK);
ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
+ if (is_pre_parsing_) return NULL;
if (extension_ != NULL) {
// The extension structures are only accessible while parsing the
@@ -3399,7 +3808,7 @@ Expression* Parser::ParseV8Intrinsic(bool* ok) {
}
// We have a valid intrinsics call or a call to a builtin.
- return new CallRuntime(name, function, args);
+ return NEW(CallRuntime(name, function, args));
}
@@ -3447,12 +3856,12 @@ void Parser::ExpectSemicolon(bool* ok) {
Literal* Parser::GetLiteralUndefined() {
- return new Literal(Factory::undefined_value());
+ return NEW(Literal(Factory::undefined_value()));
}
Literal* Parser::GetLiteralTheHole() {
- return new Literal(Factory::the_hole_value());
+ return NEW(Literal(Factory::the_hole_value()));
}
@@ -3555,7 +3964,7 @@ void Parser::RegisterTargetUse(BreakTarget* target, Target* stop) {
Literal* Parser::NewNumberLiteral(double number) {
- return new Literal(Factory::NewNumber(number, TENURED));
+ return NEW(Literal(Factory::NewNumber(number, TENURED)));
}
@@ -3587,6 +3996,8 @@ Expression* Parser::NewThrowTypeError(Handle<String> type,
Expression* Parser::NewThrowError(Handle<String> constructor,
Handle<String> type,
Vector< Handle<Object> > arguments) {
+ if (is_pre_parsing_) return NULL;
+
int argc = arguments.length();
Handle<JSArray> array = Factory::NewJSArray(argc, TENURED);
ASSERT(array->IsJSArray() && array->HasFastElements());
@@ -3774,17 +4185,17 @@ Handle<Object> JsonParser::ParseJsonArray() {
RegExpParser::RegExpParser(FlatStringReader* in,
Handle<String>* error,
bool multiline)
- : error_(error),
- captures_(NULL),
- in_(in),
- current_(kEndMarker),
- next_pos_(0),
- capture_count_(0),
+ : current_(kEndMarker),
has_more_(true),
multiline_(multiline),
+ next_pos_(0),
+ in_(in),
+ error_(error),
simple_(false),
contains_anchor_(false),
+ captures_(NULL),
is_scanned_for_captures_(false),
+ capture_count_(0),
failed_(false) {
Advance(1);
}
@@ -4592,6 +5003,23 @@ bool ScriptDataImpl::HasError() {
}
+// Preparse, but only collect data that is immediately useful,
+// even if the preparser data is only used once.
+ScriptDataImpl* ParserApi::PartialPreParse(Handle<String> source,
+ unibrow::CharacterStream* stream,
+ v8::Extension* extension) {
+ Handle<Script> no_script;
+ bool allow_natives_syntax =
+ FLAG_allow_natives_syntax || Bootstrapper::IsActive();
+ PartialPreParser parser(no_script, allow_natives_syntax, extension);
+ if (!parser.PreParseProgram(source, stream)) return NULL;
+ // Extract the accumulated data from the recorder as a single
+ // contiguous vector that we are responsible for disposing.
+ Vector<unsigned> store = parser.recorder()->ExtractData();
+ return new ScriptDataImpl(store);
+}
+
+
void ScriptDataImpl::Initialize() {
// Prepares state for use.
if (store_.length() >= kHeaderSize) {
@@ -4635,50 +5063,17 @@ int ScriptDataImpl::ReadNumber(byte** source) {
}
-// Preparse, but only collect data that is immediately useful,
-// even if the preparser data is only used once.
-ScriptDataImpl* ParserApi::PartialPreParse(Handle<String> source,
- unibrow::CharacterStream* stream,
- v8::Extension* extension) {
- Handle<Script> no_script;
- bool allow_lazy = FLAG_lazy && (extension == NULL);
- if (!allow_lazy) {
- // Partial preparsing is only about lazily compiled functions.
- // If we don't allow lazy compilation, the log data will be empty.
- return NULL;
- }
- preparser::PreParser<Scanner, PartialParserRecorder> parser;
- Scanner scanner;
- scanner.Initialize(source, stream, JAVASCRIPT);
- PartialParserRecorder recorder;
- if (!parser.PreParseProgram(&scanner, &recorder, allow_lazy)) {
- Top::StackOverflow();
- return NULL;
- }
-
- // Extract the accumulated data from the recorder as a single
- // contiguous vector that we are responsible for disposing.
- Vector<unsigned> store = recorder.ExtractData();
- return new ScriptDataImpl(store);
-}
-
-
ScriptDataImpl* ParserApi::PreParse(Handle<String> source,
unibrow::CharacterStream* stream,
v8::Extension* extension) {
Handle<Script> no_script;
- preparser::PreParser<Scanner, CompleteParserRecorder> parser;
- Scanner scanner;
- scanner.Initialize(source, stream, JAVASCRIPT);
- bool allow_lazy = FLAG_lazy && (extension == NULL);
- CompleteParserRecorder recorder;
- if (!parser.PreParseProgram(&scanner, &recorder, allow_lazy)) {
- Top::StackOverflow();
- return NULL;
- }
+ bool allow_natives_syntax =
+ FLAG_allow_natives_syntax || Bootstrapper::IsActive();
+ CompletePreParser parser(no_script, allow_natives_syntax, extension);
+ if (!parser.PreParseProgram(source, stream)) return NULL;
// Extract the accumulated data from the recorder as a single
// contiguous vector that we are responsible for disposing.
- Vector<unsigned> store = recorder.ExtractData();
+ Vector<unsigned> store = parser.recorder()->ExtractData();
return new ScriptDataImpl(store);
}
@@ -4710,13 +5105,14 @@ bool ParserApi::Parse(CompilationInfo* info) {
FunctionLiteral* result = NULL;
Handle<Script> script = info->script();
if (info->is_lazy()) {
- Parser parser(script, true, NULL, NULL);
+ AstBuildingParser parser(script, true, NULL, NULL);
result = parser.ParseLazy(info->shared_info());
} else {
bool allow_natives_syntax =
FLAG_allow_natives_syntax || Bootstrapper::IsActive();
ScriptDataImpl* pre_data = info->pre_parse_data();
- Parser parser(script, allow_natives_syntax, info->extension(), pre_data);
+ AstBuildingParser parser(script, allow_natives_syntax, info->extension(),
+ pre_data);
if (pre_data != NULL && pre_data->has_error()) {
Scanner::Location loc = pre_data->MessageLocation();
const char* message = pre_data->BuildMessage();
@@ -4738,4 +5134,6 @@ bool ParserApi::Parse(CompilationInfo* info) {
return (result != NULL);
}
+#undef NEW
+
} } // namespace v8::internal
diff --git a/deps/v8/src/parser.h b/deps/v8/src/parser.h
index 667410b3ce3..19b382e8ded 100644
--- a/deps/v8/src/parser.h
+++ b/deps/v8/src/parser.h
@@ -31,13 +31,13 @@
#include "allocation.h"
#include "ast.h"
#include "scanner.h"
-#include "scopes.h"
namespace v8 {
namespace internal {
class CompilationInfo;
class FuncNameInferrer;
+class ParserFactory;
class ParserLog;
class PositionStack;
class Target;
@@ -177,125 +177,6 @@ class ScriptDataImpl : public ScriptData {
};
-// Record only functions.
-class PartialParserRecorder {
- public:
- PartialParserRecorder();
-
- void LogFunction(int start, int end, int literals, int properties) {
- function_store_.Add(start);
- function_store_.Add(end);
- function_store_.Add(literals);
- function_store_.Add(properties);
- }
-
- void LogSymbol(int start, const char* symbol, int length) { }
-
- // Logs an error message and marks the log as containing an error.
- // Further logging will be ignored, and ExtractData will return a vector
- // representing the error only.
- void LogMessage(int start,
- int end,
- const char* message,
- const char* argument_opt) {
- Scanner::Location location(start, end);
- Vector<const char*> arguments;
- if (argument_opt != NULL) {
- arguments = Vector<const char*>(&argument_opt, 1);
- }
- this->LogMessage(location, message, arguments);
- }
-
- int function_position() { return function_store_.size(); }
-
- void LogMessage(Scanner::Location loc,
- const char* message,
- Vector<const char*> args);
-
- Vector<unsigned> ExtractData();
-
- void PauseRecording() {
- pause_count_++;
- is_recording_ = false;
- }
-
- void ResumeRecording() {
- ASSERT(pause_count_ > 0);
- if (--pause_count_ == 0) is_recording_ = !has_error();
- }
-
- int symbol_position() { return 0; }
- int symbol_ids() { return 0; }
-
- protected:
- bool has_error() {
- return static_cast<bool>(preamble_[ScriptDataImpl::kHasErrorOffset]);
- }
-
- bool is_recording() {
- return is_recording_;
- }
-
- void WriteString(Vector<const char> str);
-
- Collector<unsigned> 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();
-
- void LogSymbol(int start, Vector<const char> literal);
-
- void LogSymbol(int start, const char* symbol, int length) {
- LogSymbol(start, Vector<const char>(symbol, length));
- }
-
- Vector<unsigned> ExtractData();
-
- int symbol_position() { return symbol_store_.size(); }
- int symbol_ids() { return symbol_id_; }
-
- private:
- static int vector_hash(Vector<const char> 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<const char>* string1 = reinterpret_cast<Vector<const char>* >(a);
- Vector<const char>* string2 = reinterpret_cast<Vector<const char>* >(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<byte> symbol_store_;
- Collector<Vector<const char> > symbol_entries_;
- HashMap symbol_table_;
- int symbol_id_;
-};
-
-
-
class ParserApi {
public:
// Parses the source code represented by the compilation info and sets its
@@ -315,8 +196,6 @@ class ParserApi {
v8::Extension* extension);
};
-// ----------------------------------------------------------------------------
-// REGEXP PARSING
// A BuffferedZoneList is an automatically growing list, just like (and backed
// by) a ZoneList, that is optimized for the case of adding and removing
@@ -532,44 +411,51 @@ class RegExpParser {
uc32 Next();
FlatStringReader* in() { return in_; }
void ScanForCaptures();
-
- Handle<String>* error_;
- ZoneList<RegExpCapture*>* captures_;
- FlatStringReader* in_;
uc32 current_;
- int next_pos_;
- // The capture count is only valid after we have scanned for captures.
- int capture_count_;
bool has_more_;
bool multiline_;
+ int next_pos_;
+ FlatStringReader* in_;
+ Handle<String>* error_;
bool simple_;
bool contains_anchor_;
+ ZoneList<RegExpCapture*>* captures_;
bool is_scanned_for_captures_;
+ // The capture count is only valid after we have scanned for captures.
+ int capture_count_;
bool failed_;
};
-// ----------------------------------------------------------------------------
-// JAVASCRIPT PARSING
class Parser {
public:
- Parser(Handle<Script> script,
- bool allow_natives_syntax,
- v8::Extension* extension,
- ScriptDataImpl* pre_data);
+ Parser(Handle<Script> script, bool allow_natives_syntax,
+ v8::Extension* extension, ParserMode is_pre_parsing,
+ ParserFactory* factory, ParserLog* log, ScriptDataImpl* pre_data);
virtual ~Parser() { }
+ // Pre-parse the program from the character stream; returns true on
+ // success, false if a stack-overflow happened during parsing.
+ bool PreParseProgram(Handle<String> source, unibrow::CharacterStream* stream);
+
+ void ReportMessage(const char* message, Vector<const char*> args);
+ virtual void ReportMessageAt(Scanner::Location loc,
+ const char* message,
+ Vector<const char*> args) = 0;
+
+
// Returns NULL if parsing failed.
FunctionLiteral* ParseProgram(Handle<String> source,
bool in_global_context);
-
FunctionLiteral* ParseLazy(Handle<SharedFunctionInfo> info);
- void ReportMessageAt(Scanner::Location loc,
- const char* message,
- Vector<const char*> args);
+ // The minimum number of contiguous assignment that will
+ // be treated as an initialization block. Benchmarks show that
+ // the overhead exceeds the savings below this limit.
+ static const int kMinInitializationBlock = 3;
protected:
+
enum Mode {
PARSE_LAZILY,
PARSE_EAGERLY
@@ -578,9 +464,28 @@ class Parser {
// Report syntax error
void ReportUnexpectedToken(Token::Value token);
void ReportInvalidPreparseData(Handle<String> name, bool* ok);
- void ReportMessage(const char* message, Vector<const char*> args);
+
+ Handle<Script> script_;
+ Scanner scanner_;
+
+ Scope* top_scope_;
+ int with_nesting_level_;
+
+ TemporaryScope* temp_scope_;
+ Mode mode_;
+
+ Target* target_stack_; // for break, continue statements
+ bool allow_natives_syntax_;
+ v8::Extension* extension_;
+ ParserFactory* factory_;
+ ParserLog* log_;
+ bool is_pre_parsing_;
+ ScriptDataImpl* pre_data_;
+ FuncNameInferrer* fni_;
bool inside_with() const { return with_nesting_level_ > 0; }
+ ParserFactory* factory() const { return factory_; }
+ ParserLog* log() const { return log_; }
Scanner& scanner() { return scanner_; }
Mode mode() const { return mode_; }
ScriptDataImpl* pre_data() const { return pre_data_; }
@@ -589,7 +494,7 @@ class Parser {
// which is set to false if parsing failed; it is unchanged otherwise.
// By making the 'exception handling' explicit, we are forced to check
// for failure at the call sites.
- void* ParseSourceElements(ZoneList<Statement*>* processor,
+ void* ParseSourceElements(ZoneListWrapper<Statement>* processor,
int end_token, bool* ok);
Statement* ParseStatement(ZoneStringList* labels, bool* ok);
Statement* ParseFunctionDeclaration(bool* ok);
@@ -702,10 +607,10 @@ class Parser {
bool* ok);
// Parser support
- VariableProxy* Declare(Handle<String> name, Variable::Mode mode,
- FunctionLiteral* fun,
- bool resolve,
- bool* ok);
+ virtual VariableProxy* Declare(Handle<String> name, Variable::Mode mode,
+ FunctionLiteral* fun,
+ bool resolve,
+ bool* ok) = 0;
bool TargetStackContainsLabel(Handle<String> label);
BreakableStatement* LookupBreakTarget(Handle<String> label, bool* ok);
@@ -713,28 +618,6 @@ class Parser {
void RegisterTargetUse(BreakTarget* target, Target* stop);
- // Factory methods.
-
- Statement* EmptyStatement() {
- static v8::internal::EmptyStatement empty;
- return &empty;
- }
-
- Scope* NewScope(Scope* parent, Scope::Type type, bool inside_with);
-
- Handle<String> LookupSymbol(int symbol_id,
- Vector<const char> string);
-
- Handle<String> LookupCachedSymbol(int symbol_id,
- Vector<const char> string);
-
- Expression* NewCall(Expression* expression,
- ZoneList<Expression*>* arguments,
- int pos) {
- return new Call(expression, arguments, pos);
- }
-
-
// Create a number literal.
Literal* NewNumberLiteral(double value);
@@ -756,24 +639,6 @@ class Parser {
Expression* NewThrowError(Handle<String> constructor,
Handle<String> type,
Vector< Handle<Object> > arguments);
-
- ZoneList<Handle<String> > symbol_cache_;
-
- Handle<Script> script_;
- Scanner scanner_;
-
- Scope* top_scope_;
- int with_nesting_level_;
-
- TemporaryScope* temp_scope_;
- Mode mode_;
-
- Target* target_stack_; // for break, continue statements
- bool allow_natives_syntax_;
- v8::Extension* extension_;
- bool is_pre_parsing_;
- ScriptDataImpl* pre_data_;
- FuncNameInferrer* fni_;
};
@@ -808,9 +673,6 @@ class CompileTimeValue: public AllStatic {
};
-// ----------------------------------------------------------------------------
-// JSON PARSING
-
// JSON is a subset of JavaScript, as specified in, e.g., the ECMAScript 5
// specification section 15.12.1 (and appendix A.8).
// The grammar is given section 15.12.1.2 (and appendix A.8.2).
diff --git a/deps/v8/src/platform-linux.cc b/deps/v8/src/platform-linux.cc
index 89003ba83f9..c0eb21395fe 100644
--- a/deps/v8/src/platform-linux.cc
+++ b/deps/v8/src/platform-linux.cc
@@ -99,12 +99,30 @@ uint64_t OS::CpuFeaturesImpliedByPlatform() {
#ifdef __arm__
-static bool CPUInfoContainsString(const char * search_string) {
+bool OS::ArmCpuHasFeature(CpuFeature feature) {
+ const char* search_string = NULL;
const char* file_name = "/proc/cpuinfo";
+ // Simple detection of VFP at runtime for Linux.
+ // It is based on /proc/cpuinfo, which reveals hardware configuration
+ // to user-space applications. According to ARM (mid 2009), no similar
+ // facility is universally available on the ARM architectures,
+ // so it's up to individual OSes to provide such.
+ //
// This is written as a straight shot one pass parser
// and not using STL string and ifstream because,
// on Linux, it's reading from a (non-mmap-able)
// character special device.
+ switch (feature) {
+ case VFP3:
+ search_string = "vfp";
+ break;
+ case ARMv7:
+ search_string = "ARMv7";
+ break;
+ default:
+ UNREACHABLE();
+ }
+
FILE* f = NULL;
const char* what = search_string;
@@ -131,43 +149,6 @@ static bool CPUInfoContainsString(const char * search_string) {
// Did not find string in the proc file.
return false;
}
-
-bool OS::ArmCpuHasFeature(CpuFeature feature) {
- const int max_items = 2;
- const char* search_strings[max_items] = { NULL, NULL };
- int search_items = 0;
- // Simple detection of VFP at runtime for Linux.
- // It is based on /proc/cpuinfo, which reveals hardware configuration
- // to user-space applications. According to ARM (mid 2009), no similar
- // facility is universally available on the ARM architectures,
- // so it's up to individual OSes to provide such.
- switch (feature) {
- case VFP3:
- search_strings[0] = "vfpv3";
- // Some old kernels will report vfp for A8, not vfpv3, so we check for
- // A8 explicitely. The cpuinfo file report the CPU Part which for Cortex
- // A8 is 0xc08.
- search_strings[1] = "0xc08";
- search_items = 2;
- ASSERT(search_items <= max_items);
- break;
- case ARMv7:
- search_strings[0] = "ARMv7" ;
- search_items = 1;
- ASSERT(search_items <= max_items);
- break;
- default:
- UNREACHABLE();
- }
-
- for (int i = 0; i < search_items; ++i) {
- if (CPUInfoContainsString(search_strings[i])) {
- return true;
- }
- }
-
- return false;
-}
#endif // def __arm__
@@ -828,17 +809,8 @@ class Sampler::PlatformData : public Malloced {
syscall(SYS_tgkill, vm_tgid_, vm_tid_, SIGPROF);
// Convert ms to us and subtract 100 us to compensate delays
// occuring during signal delivery.
- const useconds_t interval = sampler_->interval_ * 1000 - 100;
- int result = usleep(interval);
-#ifdef DEBUG
- if (result != 0 && errno != EINTR) {
- fprintf(stderr,
- "SignalSender usleep error; interval = %u, errno = %d\n",
- interval,
- errno);
- ASSERT(result == 0 || errno == EINTR);
- }
-#endif
+ int result = usleep(sampler_->interval_ * 1000 - 100);
+ ASSERT(result == 0 || errno == EINTR);
USE(result);
}
}
@@ -871,7 +843,6 @@ Sampler::Sampler(int interval, bool profiling)
Sampler::~Sampler() {
- ASSERT(!data_->signal_sender_launched_);
delete data_;
}
diff --git a/deps/v8/src/preparser.h b/deps/v8/src/preparser.h
deleted file mode 100644
index 44c55cf7db7..00000000000
--- a/deps/v8/src/preparser.h
+++ /dev/null
@@ -1,1414 +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_PREPARSER_H
-#define V8_PREPARSER_H
-
-#include "unicode.h"
-
-namespace v8 {
-namespace preparser {
-
-// Preparsing checks a JavaScript program and emits preparse-data that helps
-// a later parsing to be faster.
-// See preparser-data.h for the data.
-
-// The PreParser checks that the syntax follows the grammar for JavaScript,
-// and collects some information about the program along the way.
-// The grammar check is only performed in order to understand the program
-// sufficiently to deduce some information about it, that can be used
-// to speed up later parsing. Finding errors is not the goal of pre-parsing,
-// rather it is to speed up properly written and correct programs.
-// That means that contextual checks (like a label being declared where
-// it is used) are generally omitted.
-
-namespace i = v8::internal;
-
-enum StatementType {
- kUnknownStatement
-};
-
-enum ExpressionType {
- kUnknownExpression,
- kIdentifierExpression, // Used to detect labels.
- kThisExpression,
- kThisPropertyExpression
-};
-
-enum IdentifierType {
- kUnknownIdentifier
-};
-
-enum SourceElementTypes {
- kUnknownSourceElements
-};
-
-
-typedef int SourceElements;
-typedef int Expression;
-typedef int Statement;
-typedef int Identifier;
-typedef int Arguments;
-
-
-template <typename Scanner, typename PreParserLog>
-class PreParser {
- public:
- PreParser() : scope_(NULL), allow_lazy_(true) { }
- ~PreParser() { }
-
- // Pre-parse the program from the character stream; returns true on
- // success (even if parsing failed, the pre-parse data successfully
- // captured the syntax error), and false if a stack-overflow happened
- // during parsing.
- bool PreParseProgram(Scanner* scanner,
- PreParserLog* log,
- bool allow_lazy) {
- allow_lazy_ = allow_lazy;
- scanner_ = scanner;
- log_ = log;
- Scope top_scope(&scope_, kTopLevelScope);
- bool ok = true;
- ParseSourceElements(i::Token::EOS, &ok);
- bool stack_overflow = scanner_->stack_overflow();
- if (!ok && !stack_overflow) {
- ReportUnexpectedToken(scanner_->current_token());
- }
- return !stack_overflow;
- }
-
- private:
- enum ScopeType {
- kTopLevelScope,
- kFunctionScope
- };
-
- class Scope {
- public:
- Scope(Scope** variable, ScopeType type)
- : variable_(variable),
- prev_(*variable),
- type_(type),
- materialized_literal_count_(0),
- expected_properties_(0),
- with_nesting_count_(0) {
- *variable = this;
- }
- ~Scope() { *variable_ = prev_; }
- void NextMaterializedLiteralIndex() { materialized_literal_count_++; }
- void AddProperty() { expected_properties_++; }
- ScopeType type() { return type_; }
- int expected_properties() { return expected_properties_; }
- int materialized_literal_count() { return materialized_literal_count_; }
- bool IsInsideWith() { return with_nesting_count_ != 0; }
- void EnterWith() { with_nesting_count_++; }
- void LeaveWith() { with_nesting_count_--; }
-
- private:
- Scope** const variable_;
- Scope* const prev_;
- const ScopeType type_;
- int materialized_literal_count_;
- int expected_properties_;
- int with_nesting_count_;
- };
-
- // Types that allow us to recognize simple this-property assignments.
- // A simple this-property assignment is a statement on the form
- // "this.propertyName = {primitive constant or function parameter name);"
- // where propertyName isn't "__proto__".
- // The result is only relevant if the function body contains only
- // simple this-property assignments.
-
- // Report syntax error
- void ReportUnexpectedToken(i::Token::Value token);
- void ReportMessageAt(int start_pos,
- int end_pos,
- const char* type,
- const char* name_opt) {
- log_->LogMessage(start_pos, end_pos, type, name_opt);
- }
-
- // All ParseXXX functions take as the last argument an *ok parameter
- // which is set to false if parsing failed; it is unchanged otherwise.
- // By making the 'exception handling' explicit, we are forced to check
- // for failure at the call sites.
- SourceElements ParseSourceElements(int end_token, bool* ok);
- Statement ParseStatement(bool* ok);
- Statement ParseFunctionDeclaration(bool* ok);
- Statement ParseNativeDeclaration(bool* ok);
- Statement ParseBlock(bool* ok);
- Statement ParseVariableStatement(bool* ok);
- Statement ParseVariableDeclarations(bool accept_IN, int* num_decl, bool* ok);
- Statement ParseExpressionOrLabelledStatement(bool* ok);
- Statement ParseIfStatement(bool* ok);
- Statement ParseContinueStatement(bool* ok);
- Statement ParseBreakStatement(bool* ok);
- Statement ParseReturnStatement(bool* ok);
- Statement ParseWithStatement(bool* ok);
- Statement ParseSwitchStatement(bool* ok);
- Statement ParseDoWhileStatement(bool* ok);
- Statement ParseWhileStatement(bool* ok);
- Statement ParseForStatement(bool* ok);
- Statement ParseThrowStatement(bool* ok);
- Statement ParseTryStatement(bool* ok);
- Statement ParseDebuggerStatement(bool* ok);
-
- Expression ParseExpression(bool accept_IN, bool* ok);
- Expression ParseAssignmentExpression(bool accept_IN, bool* ok);
- Expression ParseConditionalExpression(bool accept_IN, bool* ok);
- Expression ParseBinaryExpression(int prec, bool accept_IN, bool* ok);
- Expression ParseUnaryExpression(bool* ok);
- Expression ParsePostfixExpression(bool* ok);
- Expression ParseLeftHandSideExpression(bool* ok);
- Expression ParseNewExpression(bool* ok);
- Expression ParseMemberExpression(bool* ok);
- Expression ParseMemberWithNewPrefixesExpression(unsigned new_count, bool* ok);
- Expression ParsePrimaryExpression(bool* ok);
- Expression ParseArrayLiteral(bool* ok);
- Expression ParseObjectLiteral(bool* ok);
- Expression ParseRegExpLiteral(bool seen_equal, bool* ok);
- Expression ParseV8Intrinsic(bool* ok);
-
- Arguments ParseArguments(bool* ok);
- Expression ParseFunctionLiteral(bool* ok);
-
- Identifier ParseIdentifier(bool* ok);
- Identifier ParseIdentifierName(bool* ok);
- Identifier ParseIdentifierOrGetOrSet(bool* is_get, bool* is_set, bool* ok);
-
- Identifier GetIdentifierSymbol();
- unsigned int HexDigitValue(char digit);
- Expression GetStringSymbol();
-
-
- i::Token::Value peek() { return scanner_->peek(); }
- i::Token::Value Next() {
- i::Token::Value next = scanner_->Next();
- return next;
- }
-
- void Consume(i::Token::Value token) {
- Next();
- }
-
- void Expect(i::Token::Value token, bool* ok) {
- if (Next() != token) {
- *ok = false;
- }
- }
-
- bool Check(i::Token::Value token) {
- i::Token::Value next = peek();
- if (next == token) {
- Consume(next);
- return true;
- }
- return false;
- }
- void ExpectSemicolon(bool* ok);
-
- static int Precedence(i::Token::Value tok, bool accept_IN);
-
- Scanner* scanner_;
- PreParserLog* log_;
- Scope* scope_;
- bool allow_lazy_;
-};
-
-
-#define CHECK_OK ok); \
- if (!*ok) return -1; \
- ((void)0
-#define DUMMY ) // to make indentation work
-#undef DUMMY
-
-
-template <typename Scanner, typename Log>
-void PreParser<Scanner, Log>::ReportUnexpectedToken(i::Token::Value token) {
- // We don't report stack overflows here, to avoid increasing the
- // stack depth even further. Instead we report it after parsing is
- // over, in ParseProgram.
- if (token == i::Token::ILLEGAL && scanner_->stack_overflow()) {
- return;
- }
- typename Scanner::Location source_location = scanner_->location();
-
- // Four of the tokens are treated specially
- switch (token) {
- case i::Token::EOS:
- return ReportMessageAt(source_location.beg_pos, source_location.end_pos,
- "unexpected_eos", NULL);
- case i::Token::NUMBER:
- return ReportMessageAt(source_location.beg_pos, source_location.end_pos,
- "unexpected_token_number", NULL);
- case i::Token::STRING:
- return ReportMessageAt(source_location.beg_pos, source_location.end_pos,
- "unexpected_token_string", NULL);
- case i::Token::IDENTIFIER:
- return ReportMessageAt(source_location.beg_pos, source_location.end_pos,
- "unexpected_token_identifier", NULL);
- default:
- const char* name = i::Token::String(token);
- ReportMessageAt(source_location.beg_pos, source_location.end_pos,
- "unexpected_token", name);
- }
-}
-
-
-template <typename Scanner, typename Log>
-SourceElements PreParser<Scanner, Log>::ParseSourceElements(int end_token,
- bool* ok) {
- // SourceElements ::
- // (Statement)* <end_token>
-
- while (peek() != end_token) {
- ParseStatement(CHECK_OK);
- }
- return kUnknownSourceElements;
-}
-
-
-template <typename Scanner, typename Log>
-Statement PreParser<Scanner, Log>::ParseStatement(bool* ok) {
- // Statement ::
- // Block
- // VariableStatement
- // EmptyStatement
- // ExpressionStatement
- // IfStatement
- // IterationStatement
- // ContinueStatement
- // BreakStatement
- // ReturnStatement
- // WithStatement
- // LabelledStatement
- // SwitchStatement
- // ThrowStatement
- // TryStatement
- // DebuggerStatement
-
- // Note: Since labels can only be used by 'break' and 'continue'
- // statements, which themselves are only valid within blocks,
- // iterations or 'switch' statements (i.e., BreakableStatements),
- // labels can be simply ignored in all other cases; except for
- // trivial labeled break statements 'label: break label' which is
- // parsed into an empty statement.
-
- // Keep the source position of the statement
- switch (peek()) {
- case i::Token::LBRACE:
- return ParseBlock(ok);
-
- case i::Token::CONST:
- case i::Token::VAR:
- return ParseVariableStatement(ok);
-
- case i::Token::SEMICOLON:
- Next();
- return kUnknownStatement;
-
- case i::Token::IF:
- return ParseIfStatement(ok);
-
- case i::Token::DO:
- return ParseDoWhileStatement(ok);
-
- case i::Token::WHILE:
- return ParseWhileStatement(ok);
-
- case i::Token::FOR:
- return ParseForStatement(ok);
-
- case i::Token::CONTINUE:
- return ParseContinueStatement(ok);
-
- case i::Token::BREAK:
- return ParseBreakStatement(ok);
-
- case i::Token::RETURN:
- return ParseReturnStatement(ok);
-
- case i::Token::WITH:
- return ParseWithStatement(ok);
-
- case i::Token::SWITCH:
- return ParseSwitchStatement(ok);
-
- case i::Token::THROW:
- return ParseThrowStatement(ok);
-
- case i::Token::TRY:
- return ParseTryStatement(ok);
-
- case i::Token::FUNCTION:
- return ParseFunctionDeclaration(ok);
-
- case i::Token::NATIVE:
- return ParseNativeDeclaration(ok);
-
- case i::Token::DEBUGGER:
- return ParseDebuggerStatement(ok);
-
- default:
- return ParseExpressionOrLabelledStatement(ok);
- }
-}
-
-
-template <typename Scanner, typename Log>
-Statement PreParser<Scanner, Log>::ParseFunctionDeclaration(bool* ok) {
- // FunctionDeclaration ::
- // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}'
- Expect(i::Token::FUNCTION, CHECK_OK);
- ParseIdentifier(CHECK_OK);
- ParseFunctionLiteral(CHECK_OK);
- return kUnknownStatement;
-}
-
-
-// Language extension which is only enabled for source files loaded
-// through the API's extension mechanism. A native function
-// declaration is resolved by looking up the function through a
-// callback provided by the extension.
-template <typename Scanner, typename Log>
-Statement PreParser<Scanner, Log>::ParseNativeDeclaration(bool* ok) {
- Expect(i::Token::NATIVE, CHECK_OK);
- Expect(i::Token::FUNCTION, CHECK_OK);
- ParseIdentifier(CHECK_OK);
- Expect(i::Token::LPAREN, CHECK_OK);
- bool done = (peek() == i::Token::RPAREN);
- while (!done) {
- ParseIdentifier(CHECK_OK);
- done = (peek() == i::Token::RPAREN);
- if (!done) {
- Expect(i::Token::COMMA, CHECK_OK);
- }
- }
- Expect(i::Token::RPAREN, CHECK_OK);
- Expect(i::Token::SEMICOLON, CHECK_OK);
- return kUnknownStatement;
-}
-
-
-template <typename Scanner, typename Log>
-Statement PreParser<Scanner, Log>::ParseBlock(bool* ok) {
- // Block ::
- // '{' Statement* '}'
-
- // Note that a Block does not introduce a new execution scope!
- // (ECMA-262, 3rd, 12.2)
- //
- Expect(i::Token::LBRACE, CHECK_OK);
- while (peek() != i::Token::RBRACE) {
- ParseStatement(CHECK_OK);
- }
- Expect(i::Token::RBRACE, CHECK_OK);
- return kUnknownStatement;
-}
-
-
-template <typename Scanner, typename Log>
-Statement PreParser<Scanner, Log>::ParseVariableStatement(bool* ok) {
- // VariableStatement ::
- // VariableDeclarations ';'
-
- Statement result = ParseVariableDeclarations(true, NULL, CHECK_OK);
- ExpectSemicolon(CHECK_OK);
- return result;
-}
-
-
-// If the variable declaration declares exactly one non-const
-// variable, then *var is set to that variable. In all other cases,
-// *var is untouched; in particular, it is the caller's responsibility
-// to initialize it properly. This mechanism is also used for the parsing
-// of 'for-in' loops.
-template <typename Scanner, typename Log>
-Statement PreParser<Scanner, Log>::ParseVariableDeclarations(bool accept_IN,
- int* num_decl,
- bool* ok) {
- // VariableDeclarations ::
- // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[',']
-
- if (peek() == i::Token::VAR) {
- Consume(i::Token::VAR);
- } else if (peek() == i::Token::CONST) {
- Consume(i::Token::CONST);
- } else {
- *ok = false;
- return 0;
- }
-
- // The scope of a variable/const declared anywhere inside a function
- // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). .
- int nvars = 0; // the number of variables declared
- do {
- // Parse variable name.
- if (nvars > 0) Consume(i::Token::COMMA);
- ParseIdentifier(CHECK_OK);
- nvars++;
- if (peek() == i::Token::ASSIGN) {
- Expect(i::Token::ASSIGN, CHECK_OK);
- ParseAssignmentExpression(accept_IN, CHECK_OK);
- }
- } while (peek() == i::Token::COMMA);
-
- if (num_decl != NULL) *num_decl = nvars;
- return kUnknownStatement;
-}
-
-
-template <typename Scanner, typename Log>
-Statement PreParser<Scanner, Log>::ParseExpressionOrLabelledStatement(
- bool* ok) {
- // ExpressionStatement | LabelledStatement ::
- // Expression ';'
- // Identifier ':' Statement
-
- Expression expr = ParseExpression(true, CHECK_OK);
- if (peek() == i::Token::COLON && expr == kIdentifierExpression) {
- Consume(i::Token::COLON);
- return ParseStatement(ok);
- }
- // Parsed expression statement.
- ExpectSemicolon(CHECK_OK);
- return kUnknownStatement;
-}
-
-
-template <typename Scanner, typename Log>
-Statement PreParser<Scanner, Log>::ParseIfStatement(bool* ok) {
- // IfStatement ::
- // 'if' '(' Expression ')' Statement ('else' Statement)?
-
- Expect(i::Token::IF, CHECK_OK);
- Expect(i::Token::LPAREN, CHECK_OK);
- ParseExpression(true, CHECK_OK);
- Expect(i::Token::RPAREN, CHECK_OK);
- ParseStatement(CHECK_OK);
- if (peek() == i::Token::ELSE) {
- Next();
- ParseStatement(CHECK_OK);
- }
- return kUnknownStatement;
-}
-
-
-template <typename Scanner, typename Log>
-Statement PreParser<Scanner, Log>::ParseContinueStatement(bool* ok) {
- // ContinueStatement ::
- // 'continue' [no line terminator] Identifier? ';'
-
- Expect(i::Token::CONTINUE, CHECK_OK);
- i::Token::Value tok = peek();
- if (!scanner_->has_line_terminator_before_next() &&
- tok != i::Token::SEMICOLON &&
- tok != i::Token::RBRACE &&
- tok != i::Token::EOS) {
- ParseIdentifier(CHECK_OK);
- }
- ExpectSemicolon(CHECK_OK);
- return kUnknownStatement;
-}
-
-
-template <typename Scanner, typename Log>
-Statement PreParser<Scanner, Log>::ParseBreakStatement(bool* ok) {
- // BreakStatement ::
- // 'break' [no line terminator] Identifier? ';'
-
- Expect(i::Token::BREAK, CHECK_OK);
- i::Token::Value tok = peek();
- if (!scanner_->has_line_terminator_before_next() &&
- tok != i::Token::SEMICOLON &&
- tok != i::Token::RBRACE &&
- tok != i::Token::EOS) {
- ParseIdentifier(CHECK_OK);
- }
- ExpectSemicolon(CHECK_OK);
- return kUnknownStatement;
-}
-
-
-template <typename Scanner, typename Log>
-Statement PreParser<Scanner, Log>::ParseReturnStatement(bool* ok) {
- // ReturnStatement ::
- // 'return' [no line terminator] Expression? ';'
-
- // Consume the return token. It is necessary to do the before
- // reporting any errors on it, because of the way errors are
- // reported (underlining).
- Expect(i::Token::RETURN, CHECK_OK);
-
- // An ECMAScript program is considered syntactically incorrect if it
- // contains a return statement that is not within the body of a
- // function. See ECMA-262, section 12.9, page 67.
- // This is not handled during preparsing.
-
- i::Token::Value tok = peek();
- if (!scanner_->has_line_terminator_before_next() &&
- tok != i::Token::SEMICOLON &&
- tok != i::Token::RBRACE &&
- tok != i::Token::EOS) {
- ParseExpression(true, CHECK_OK);
- }
- ExpectSemicolon(CHECK_OK);
- return kUnknownStatement;
-}
-
-
-template <typename Scanner, typename Log>
-Statement PreParser<Scanner, Log>::ParseWithStatement(bool* ok) {
- // WithStatement ::
- // 'with' '(' Expression ')' Statement
- Expect(i::Token::WITH, CHECK_OK);
- Expect(i::Token::LPAREN, CHECK_OK);
- ParseExpression(true, CHECK_OK);
- Expect(i::Token::RPAREN, CHECK_OK);
-
- scope_->EnterWith();
- ParseStatement(CHECK_OK);
- scope_->LeaveWith();
- return kUnknownStatement;
-}
-
-
-template <typename Scanner, typename Log>
-Statement PreParser<Scanner, Log>::ParseSwitchStatement(bool* ok) {
- // SwitchStatement ::
- // 'switch' '(' Expression ')' '{' CaseClause* '}'
-
- Expect(i::Token::SWITCH, CHECK_OK);
- Expect(i::Token::LPAREN, CHECK_OK);
- ParseExpression(true, CHECK_OK);
- Expect(i::Token::RPAREN, CHECK_OK);
-
- Expect(i::Token::LBRACE, CHECK_OK);
- i::Token::Value token = peek();
- while (token != i::Token::RBRACE) {
- if (token == i::Token::CASE) {
- Expect(i::Token::CASE, CHECK_OK);
- ParseExpression(true, CHECK_OK);
- Expect(i::Token::COLON, CHECK_OK);
- } else if (token == i::Token::DEFAULT) {
- Expect(i::Token::DEFAULT, CHECK_OK);
- Expect(i::Token::COLON, CHECK_OK);
- } else {
- ParseStatement(CHECK_OK);
- }
- token = peek();
- }
- Expect(i::Token::RBRACE, CHECK_OK);
-
- return kUnknownStatement;
-}
-
-
-template <typename Scanner, typename Log>
-Statement PreParser<Scanner, Log>::ParseDoWhileStatement(bool* ok) {
- // DoStatement ::
- // 'do' Statement 'while' '(' Expression ')' ';'
-
- Expect(i::Token::DO, CHECK_OK);
- ParseStatement(CHECK_OK);
- Expect(i::Token::WHILE, CHECK_OK);
- Expect(i::Token::LPAREN, CHECK_OK);
- ParseExpression(true, CHECK_OK);
- Expect(i::Token::RPAREN, CHECK_OK);
- return kUnknownStatement;
-}
-
-
-template <typename Scanner, typename Log>
-Statement PreParser<Scanner, Log>::ParseWhileStatement(bool* ok) {
- // WhileStatement ::
- // 'while' '(' Expression ')' Statement
-
- Expect(i::Token::WHILE, CHECK_OK);
- Expect(i::Token::LPAREN, CHECK_OK);
- ParseExpression(true, CHECK_OK);
- Expect(i::Token::RPAREN, CHECK_OK);
- ParseStatement(CHECK_OK);
- return kUnknownStatement;
-}
-
-
-template <typename Scanner, typename Log>
-Statement PreParser<Scanner, Log>::ParseForStatement(bool* ok) {
- // ForStatement ::
- // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
-
- Expect(i::Token::FOR, CHECK_OK);
- Expect(i::Token::LPAREN, CHECK_OK);
- if (peek() != i::Token::SEMICOLON) {
- if (peek() == i::Token::VAR || peek() == i::Token::CONST) {
- int decl_count;
- ParseVariableDeclarations(false, &decl_count, CHECK_OK);
- if (peek() == i::Token::IN && decl_count == 1) {
- Expect(i::Token::IN, CHECK_OK);
- ParseExpression(true, CHECK_OK);
- Expect(i::Token::RPAREN, CHECK_OK);
-
- ParseStatement(CHECK_OK);
- return kUnknownStatement;
- }
- } else {
- ParseExpression(false, CHECK_OK);
- if (peek() == i::Token::IN) {
- Expect(i::Token::IN, CHECK_OK);
- ParseExpression(true, CHECK_OK);
- Expect(i::Token::RPAREN, CHECK_OK);
-
- ParseStatement(CHECK_OK);
- return kUnknownStatement;
- }
- }
- }
-
- // Parsed initializer at this point.
- Expect(i::Token::SEMICOLON, CHECK_OK);
-
- if (peek() != i::Token::SEMICOLON) {
- ParseExpression(true, CHECK_OK);
- }
- Expect(i::Token::SEMICOLON, CHECK_OK);
-
- if (peek() != i::Token::RPAREN) {
- ParseExpression(true, CHECK_OK);
- }
- Expect(i::Token::RPAREN, CHECK_OK);
-
- ParseStatement(CHECK_OK);
- return kUnknownStatement;
-}
-
-
-template <typename Scanner, typename Log>
-Statement PreParser<Scanner, Log>::ParseThrowStatement(bool* ok) {
- // ThrowStatement ::
- // 'throw' [no line terminator] Expression ';'
-
- Expect(i::Token::THROW, CHECK_OK);
- if (scanner_->has_line_terminator_before_next()) {
- typename Scanner::Location pos = scanner_->location();
- ReportMessageAt(pos.beg_pos, pos.end_pos,
- "newline_after_throw", NULL);
- *ok = false;
- return NULL;
- }
- ParseExpression(true, CHECK_OK);
- ExpectSemicolon(CHECK_OK);
-
- return kUnknownStatement;
-}
-
-
-template <typename Scanner, typename Log>
-Statement PreParser<Scanner, Log>::ParseTryStatement(bool* ok) {
- // TryStatement ::
- // 'try' Block Catch
- // 'try' Block Finally
- // 'try' Block Catch Finally
- //
- // Catch ::
- // 'catch' '(' Identifier ')' Block
- //
- // Finally ::
- // 'finally' Block
-
- // In preparsing, allow any number of catch/finally blocks, including zero
- // of both.
-
- Expect(i::Token::TRY, CHECK_OK);
-
- ParseBlock(CHECK_OK);
-
- bool catch_or_finally_seen = false;
- if (peek() == i::Token::CATCH) {
- Expect(i::Token::CATCH, CHECK_OK);
- Expect(i::Token::LPAREN, CHECK_OK);
- ParseIdentifier(CHECK_OK);
- Expect(i::Token::RPAREN, CHECK_OK);
- ParseBlock(CHECK_OK);
- catch_or_finally_seen = true;
- }
- if (peek() == i::Token::FINALLY) {
- Expect(i::Token::FINALLY, CHECK_OK);
- ParseBlock(CHECK_OK);
- catch_or_finally_seen = true;
- }
- if (!catch_or_finally_seen) {
- *ok = false;
- }
- return kUnknownStatement;
-}
-
-
-template <typename Scanner, typename Log>
-Statement PreParser<Scanner, Log>::ParseDebuggerStatement(bool* ok) {
- // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser
- // contexts this is used as a statement which invokes the debugger as if a
- // break point is present.
- // DebuggerStatement ::
- // 'debugger' ';'
-
- Expect(i::Token::DEBUGGER, CHECK_OK);
- ExpectSemicolon(CHECK_OK);
- return kUnknownStatement;
-}
-
-
-// Precedence = 1
-template <typename Scanner, typename Log>
-Expression PreParser<Scanner, Log>::ParseExpression(bool accept_IN, bool* ok) {
- // Expression ::
- // AssignmentExpression
- // Expression ',' AssignmentExpression
-
- Expression result = ParseAssignmentExpression(accept_IN, CHECK_OK);
- while (peek() == i::Token::COMMA) {
- Expect(i::Token::COMMA, CHECK_OK);
- ParseAssignmentExpression(accept_IN, CHECK_OK);
- result = kUnknownExpression;
- }
- return result;
-}
-
-
-// Precedence = 2
-template <typename Scanner, typename Log>
-Expression PreParser<Scanner, Log>::ParseAssignmentExpression(bool accept_IN,
- bool* ok) {
- // AssignmentExpression ::
- // ConditionalExpression
- // LeftHandSideExpression AssignmentOperator AssignmentExpression
-
- Expression expression = ParseConditionalExpression(accept_IN, CHECK_OK);
-
- if (!i::Token::IsAssignmentOp(peek())) {
- // Parsed conditional expression only (no assignment).
- return expression;
- }
-
- i::Token::Value op = Next(); // Get assignment operator.
- ParseAssignmentExpression(accept_IN, CHECK_OK);
-
- if ((op == i::Token::ASSIGN) && (expression == kThisPropertyExpression)) {
- scope_->AddProperty();
- }
-
- return kUnknownExpression;
-}
-
-
-// Precedence = 3
-template <typename Scanner, typename Log>
-Expression PreParser<Scanner, Log>::ParseConditionalExpression(bool accept_IN,
- bool* ok) {
- // ConditionalExpression ::
- // LogicalOrExpression
- // LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression
-
- // We start using the binary expression parser for prec >= 4 only!
- Expression expression = ParseBinaryExpression(4, accept_IN, CHECK_OK);
- if (peek() != i::Token::CONDITIONAL) return expression;
- Consume(i::Token::CONDITIONAL);
- // In parsing the first assignment expression in conditional
- // expressions we always accept the 'in' keyword; see ECMA-262,
- // section 11.12, page 58.
- ParseAssignmentExpression(true, CHECK_OK);
- Expect(i::Token::COLON, CHECK_OK);
- ParseAssignmentExpression(accept_IN, CHECK_OK);
- return kUnknownExpression;
-}
-
-
-template <typename Scanner, typename Log>
-int PreParser<Scanner, Log>::Precedence(i::Token::Value tok, bool accept_IN) {
- if (tok == i::Token::IN && !accept_IN)
- return 0; // 0 precedence will terminate binary expression parsing
-
- return i::Token::Precedence(tok);
-}
-
-
-// Precedence >= 4
-template <typename Scanner, typename Log>
-Expression PreParser<Scanner, Log>::ParseBinaryExpression(int prec,
- bool accept_IN,
- bool* ok) {
- Expression result = ParseUnaryExpression(CHECK_OK);
- for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) {
- // prec1 >= 4
- while (Precedence(peek(), accept_IN) == prec1) {
- Next();
- ParseBinaryExpression(prec1 + 1, accept_IN, CHECK_OK);
- result = kUnknownExpression;
- }
- }
- return result;
-}
-
-
-template <typename Scanner, typename Log>
-Expression PreParser<Scanner, Log>::ParseUnaryExpression(bool* ok) {
- // UnaryExpression ::
- // PostfixExpression
- // 'delete' UnaryExpression
- // 'void' UnaryExpression
- // 'typeof' UnaryExpression
- // '++' UnaryExpression
- // '--' UnaryExpression
- // '+' UnaryExpression
- // '-' UnaryExpression
- // '~' UnaryExpression
- // '!' UnaryExpression
-
- i::Token::Value op = peek();
- if (i::Token::IsUnaryOp(op) || i::Token::IsCountOp(op)) {
- op = Next();
- ParseUnaryExpression(ok);
- return kUnknownExpression;
- } else {
- return ParsePostfixExpression(ok);
- }
-}
-
-
-template <typename Scanner, typename Log>
-Expression PreParser<Scanner, Log>::ParsePostfixExpression(bool* ok) {
- // PostfixExpression ::
- // LeftHandSideExpression ('++' | '--')?
-
- Expression expression = ParseLeftHandSideExpression(CHECK_OK);
- if (!scanner_->has_line_terminator_before_next() &&
- i::Token::IsCountOp(peek())) {
- Next();
- return kUnknownExpression;
- }
- return expression;
-}
-
-
-template <typename Scanner, typename Log>
-Expression PreParser<Scanner, Log>::ParseLeftHandSideExpression(bool* ok) {
- // LeftHandSideExpression ::
- // (NewExpression | MemberExpression) ...
-
- Expression result;
- if (peek() == i::Token::NEW) {
- result = ParseNewExpression(CHECK_OK);
- } else {
- result = ParseMemberExpression(CHECK_OK);
- }
-
- while (true) {
- switch (peek()) {
- case i::Token::LBRACK: {
- Consume(i::Token::LBRACK);
- ParseExpression(true, CHECK_OK);
- Expect(i::Token::RBRACK, CHECK_OK);
- if (result == kThisExpression) {
- result = kThisPropertyExpression;
- } else {
- result = kUnknownExpression;
- }
- break;
- }
-
- case i::Token::LPAREN: {
- ParseArguments(CHECK_OK);
- result = kUnknownExpression;
- break;
- }
-
- case i::Token::PERIOD: {
- Consume(i::Token::PERIOD);
- ParseIdentifierName(CHECK_OK);
- if (result == kThisExpression) {
- result = kThisPropertyExpression;
- } else {
- result = kUnknownExpression;
- }
- break;
- }
-
- default:
- return result;
- }
- }
-}
-
-
-template <typename Scanner, typename Log>
-Expression PreParser<Scanner, Log>::ParseNewExpression(bool* ok) {
- // NewExpression ::
- // ('new')+ MemberExpression
-
- // The grammar for new expressions is pretty warped. The keyword
- // 'new' can either be a part of the new expression (where it isn't
- // followed by an argument list) or a part of the member expression,
- // where it must be followed by an argument list. To accommodate
- // this, we parse the 'new' keywords greedily and keep track of how
- // many we have parsed. This information is then passed on to the
- // member expression parser, which is only allowed to match argument
- // lists as long as it has 'new' prefixes left
- unsigned new_count = 0;
- do {
- Consume(i::Token::NEW);
- new_count++;
- } while (peek() == i::Token::NEW);
-
- return ParseMemberWithNewPrefixesExpression(new_count, ok);
-}
-
-
-template <typename Scanner, typename Log>
-Expression PreParser<Scanner, Log>::ParseMemberExpression(bool* ok) {
- return ParseMemberWithNewPrefixesExpression(0, ok);
-}
-
-
-template <typename Scanner, typename Log>
-Expression PreParser<Scanner, Log>::ParseMemberWithNewPrefixesExpression(
- unsigned new_count, bool* ok) {
- // MemberExpression ::
- // (PrimaryExpression | FunctionLiteral)
- // ('[' Expression ']' | '.' Identifier | Arguments)*
-
- // Parse the initial primary or function expression.
- Expression result = NULL;
- if (peek() == i::Token::FUNCTION) {
- Consume(i::Token::FUNCTION);
- if (peek() == i::Token::IDENTIFIER) {
- ParseIdentifier(CHECK_OK);
- }
- result = ParseFunctionLiteral(CHECK_OK);
- } else {
- result = ParsePrimaryExpression(CHECK_OK);
- }
-
- while (true) {
- switch (peek()) {
- case i::Token::LBRACK: {
- Consume(i::Token::LBRACK);
- ParseExpression(true, CHECK_OK);
- Expect(i::Token::RBRACK, CHECK_OK);
- if (result == kThisExpression) {
- result = kThisPropertyExpression;
- } else {
- result = kUnknownExpression;
- }
- break;
- }
- case i::Token::PERIOD: {
- Consume(i::Token::PERIOD);
- ParseIdentifierName(CHECK_OK);
- if (result == kThisExpression) {
- result = kThisPropertyExpression;
- } else {
- result = kUnknownExpression;
- }
- break;
- }
- case i::Token::LPAREN: {
- if (new_count == 0) return result;
- // Consume one of the new prefixes (already parsed).
- ParseArguments(CHECK_OK);
- new_count--;
- result = kUnknownExpression;
- break;
- }
- default:
- return result;
- }
- }
-}
-
-
-template <typename Scanner, typename Log>
-Expression PreParser<Scanner, Log>::ParsePrimaryExpression(bool* ok) {
- // PrimaryExpression ::
- // 'this'
- // 'null'
- // 'true'
- // 'false'
- // Identifier
- // Number
- // String
- // ArrayLiteral
- // ObjectLiteral
- // RegExpLiteral
- // '(' Expression ')'
-
- Expression result = kUnknownExpression;
- switch (peek()) {
- case i::Token::THIS: {
- Next();
- result = kThisExpression;
- break;
- }
-
- case i::Token::IDENTIFIER: {
- ParseIdentifier(CHECK_OK);
- result = kIdentifierExpression;
- break;
- }
-
- case i::Token::NULL_LITERAL:
- case i::Token::TRUE_LITERAL:
- case i::Token::FALSE_LITERAL:
- case i::Token::NUMBER: {
- Next();
- break;
- }
- case i::Token::STRING: {
- Next();
- result = GetStringSymbol();
- break;
- }
-
- case i::Token::ASSIGN_DIV:
- result = ParseRegExpLiteral(true, CHECK_OK);
- break;
-
- case i::Token::DIV:
- result = ParseRegExpLiteral(false, CHECK_OK);
- break;
-
- case i::Token::LBRACK:
- result = ParseArrayLiteral(CHECK_OK);
- break;
-
- case i::Token::LBRACE:
- result = ParseObjectLiteral(CHECK_OK);
- break;
-
- case i::Token::LPAREN:
- Consume(i::Token::LPAREN);
- result = ParseExpression(true, CHECK_OK);
- Expect(i::Token::RPAREN, CHECK_OK);
- if (result == kIdentifierExpression) result = kUnknownExpression;
- break;
-
- case i::Token::MOD:
- result = ParseV8Intrinsic(CHECK_OK);
- break;
-
- default: {
- Next();
- *ok = false;
- return kUnknownExpression;
- }
- }
-
- return result;
-}
-
-
-template <typename Scanner, typename Log>
-Expression PreParser<Scanner, Log>::ParseArrayLiteral(bool* ok) {
- // ArrayLiteral ::
- // '[' Expression? (',' Expression?)* ']'
- Expect(i::Token::LBRACK, CHECK_OK);
- while (peek() != i::Token::RBRACK) {
- if (peek() != i::Token::COMMA) {
- ParseAssignmentExpression(true, CHECK_OK);
- }
- if (peek() != i::Token::RBRACK) {
- Expect(i::Token::COMMA, CHECK_OK);
- }
- }
- Expect(i::Token::RBRACK, CHECK_OK);
-
- scope_->NextMaterializedLiteralIndex();
- return kUnknownExpression;
-}
-
-
-template <typename Scanner, typename Log>
-Expression PreParser<Scanner, Log>::ParseObjectLiteral(bool* ok) {
- // ObjectLiteral ::
- // '{' (
- // ((IdentifierName | String | Number) ':' AssignmentExpression)
- // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
- // )*[','] '}'
-
- Expect(i::Token::LBRACE, CHECK_OK);
- while (peek() != i::Token::RBRACE) {
- i::Token::Value next = peek();
- switch (next) {
- case i::Token::IDENTIFIER: {
- bool is_getter = false;
- bool is_setter = false;
- ParseIdentifierOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
- if ((is_getter || is_setter) && peek() != i::Token::COLON) {
- i::Token::Value name = Next();
- if (name != i::Token::IDENTIFIER &&
- name != i::Token::NUMBER &&
- name != i::Token::STRING &&
- !i::Token::IsKeyword(name)) {
- *ok = false;
- return kUnknownExpression;
- }
- ParseFunctionLiteral(CHECK_OK);
- if (peek() != i::Token::RBRACE) {
- Expect(i::Token::COMMA, CHECK_OK);
- }
- continue; // restart the while
- }
- break;
- }
- case i::Token::STRING:
- Consume(next);
- GetStringSymbol();
- break;
- case i::Token::NUMBER:
- Consume(next);
- break;
- default:
- if (i::Token::IsKeyword(next)) {
- Consume(next);
- } else {
- // Unexpected token.
- *ok = false;
- return kUnknownExpression;
- }
- }
-
- Expect(i::Token::COLON, CHECK_OK);
- ParseAssignmentExpression(true, CHECK_OK);
-
- // TODO(1240767): Consider allowing trailing comma.
- if (peek() != i::Token::RBRACE) Expect(i::Token::COMMA, CHECK_OK);
- }
- Expect(i::Token::RBRACE, CHECK_OK);
-
- scope_->NextMaterializedLiteralIndex();
- return kUnknownExpression;
-}
-
-
-template <typename Scanner, typename Log>
-Expression PreParser<Scanner, Log>::ParseRegExpLiteral(bool seen_equal,
- bool* ok) {
- if (!scanner_->ScanRegExpPattern(seen_equal)) {
- Next();
- typename Scanner::Location location = scanner_->location();
- ReportMessageAt(location.beg_pos, location.end_pos,
- "unterminated_regexp", NULL);
- *ok = false;
- return kUnknownExpression;
- }
-
- scope_->NextMaterializedLiteralIndex();
-
- if (!scanner_->ScanRegExpFlags()) {
- Next();
- typename Scanner::Location location = scanner_->location();
- ReportMessageAt(location.beg_pos, location.end_pos,
- "invalid_regexp_flags", NULL);
- *ok = false;
- return kUnknownExpression;
- }
- Next();
- return kUnknownExpression;
-}
-
-
-template <typename Scanner, typename Log>
-Arguments PreParser<Scanner, Log>::ParseArguments(bool* ok) {
- // Arguments ::
- // '(' (AssignmentExpression)*[','] ')'
-
- Expect(i::Token::LPAREN, CHECK_OK);
- bool done = (peek() == i::Token::RPAREN);
- int argc = 0;
- while (!done) {
- ParseAssignmentExpression(true, CHECK_OK);
- argc++;
- done = (peek() == i::Token::RPAREN);
- if (!done) Expect(i::Token::COMMA, CHECK_OK);
- }
- Expect(i::Token::RPAREN, CHECK_OK);
- return argc;
-}
-
-
-template <typename Scanner, typename Log>
-Expression PreParser<Scanner, Log>::ParseFunctionLiteral(bool* ok) {
- // Function ::
- // '(' FormalParameterList? ')' '{' FunctionBody '}'
-
- // Parse function body.
- ScopeType outer_scope_type = scope_->type();
- bool inside_with = scope_->IsInsideWith();
- Scope function_scope(&scope_, kFunctionScope);
-
- // FormalParameterList ::
- // '(' (Identifier)*[','] ')'
- Expect(i::Token::LPAREN, CHECK_OK);
- bool done = (peek() == i::Token::RPAREN);
- while (!done) {
- ParseIdentifier(CHECK_OK);
- done = (peek() == i::Token::RPAREN);
- if (!done) {
- Expect(i::Token::COMMA, CHECK_OK);
- }
- }
- Expect(i::Token::RPAREN, CHECK_OK);
-
- Expect(i::Token::LBRACE, CHECK_OK);
- int function_block_pos = scanner_->location().beg_pos;
-
- // Determine if the function will be lazily compiled.
- // Currently only happens to top-level functions.
- // Optimistically assume that all top-level functions are lazily compiled.
- bool is_lazily_compiled =
- (outer_scope_type == kTopLevelScope && !inside_with && allow_lazy_);
-
- if (is_lazily_compiled) {
- log_->PauseRecording();
- ParseSourceElements(i::Token::RBRACE, ok);
- log_->ResumeRecording();
- if (!*ok) return kUnknownExpression;
-
- Expect(i::Token::RBRACE, CHECK_OK);
-
- int end_pos = scanner_->location().end_pos;
- log_->LogFunction(function_block_pos, end_pos,
- function_scope.materialized_literal_count(),
- function_scope.expected_properties());
- } else {
- ParseSourceElements(i::Token::RBRACE, CHECK_OK);
- Expect(i::Token::RBRACE, CHECK_OK);
- }
- return kUnknownExpression;
-}
-
-
-template <typename Scanner, typename Log>
-Expression PreParser<Scanner, Log>::ParseV8Intrinsic(bool* ok) {
- // CallRuntime ::
- // '%' Identifier Arguments
-
- Expect(i::Token::MOD, CHECK_OK);
- ParseIdentifier(CHECK_OK);
- ParseArguments(CHECK_OK);
-
- return kUnknownExpression;
-}
-
-
-template <typename Scanner, typename Log>
-void PreParser<Scanner, Log>::ExpectSemicolon(bool* ok) {
- // Check for automatic semicolon insertion according to
- // the rules given in ECMA-262, section 7.9, page 21.
- i::Token::Value tok = peek();
- if (tok == i::Token::SEMICOLON) {
- Next();
- return;
- }
- if (scanner_->has_line_terminator_before_next() ||
- tok == i::Token::RBRACE ||
- tok == i::Token::EOS) {
- return;
- }
- Expect(i::Token::SEMICOLON, ok);
-}
-
-
-template <typename Scanner, typename Log>
-Identifier PreParser<Scanner, Log>::GetIdentifierSymbol() {
- const char* literal_chars = scanner_->literal_string();
- int literal_length = scanner_->literal_length();
- int identifier_pos = scanner_->location().beg_pos;
-
- log_->LogSymbol(identifier_pos, literal_chars, literal_length);
-
- return kUnknownExpression;
-}
-
-
-template <typename Scanner, typename Log>
-Expression PreParser<Scanner, Log>::GetStringSymbol() {
- const char* literal_chars = scanner_->literal_string();
- int literal_length = scanner_->literal_length();
-
- int literal_position = scanner_->location().beg_pos;
- log_->LogSymbol(literal_position, literal_chars, literal_length);
-
- return kUnknownExpression;
-}
-
-
-template <typename Scanner, typename Log>
-Identifier PreParser<Scanner, Log>::ParseIdentifier(bool* ok) {
- Expect(i::Token::IDENTIFIER, ok);
- return GetIdentifierSymbol();
-}
-
-
-template <typename Scanner, typename Log>
-Identifier PreParser<Scanner, Log>::ParseIdentifierName(bool* ok) {
- i::Token::Value next = Next();
- if (i::Token::IsKeyword(next)) {
- int pos = scanner_->location().beg_pos;
- const char* keyword = i::Token::String(next);
- log_->LogSymbol(pos, keyword, strlen(keyword));
- return kUnknownExpression;
- }
- if (next == i::Token::IDENTIFIER) {
- return GetIdentifierSymbol();
- }
- *ok = false;
- return kUnknownIdentifier;
-}
-
-
-// This function reads an identifier and determines whether or not it
-// is 'get' or 'set'. The reason for not using ParseIdentifier and
-// checking on the output is that this involves heap allocation which
-// we can't do during preparsing.
-template <typename Scanner, typename Log>
-Identifier PreParser<Scanner, Log>::ParseIdentifierOrGetOrSet(bool* is_get,
- bool* is_set,
- bool* ok) {
- Expect(i::Token::IDENTIFIER, CHECK_OK);
- if (scanner_->literal_length() == 3) {
- const char* token = scanner_->literal_string();
- *is_get = strncmp(token, "get", 3) == 0;
- *is_set = !*is_get && strncmp(token, "set", 3) == 0;
- }
- return GetIdentifierSymbol();
-}
-
-#undef CHECK_OK
-} } // v8::preparser
-
-#endif // V8_PREPARSER_H
diff --git a/deps/v8/src/profile-generator.cc b/deps/v8/src/profile-generator.cc
index 29f9ab4d353..a4d9a828dd4 100644
--- a/deps/v8/src/profile-generator.cc
+++ b/deps/v8/src/profile-generator.cc
@@ -1848,6 +1848,22 @@ HeapEntry* HeapSnapshotGenerator::GetEntry(Object* obj) {
}
+int HeapSnapshotGenerator::GetGlobalSecurityToken() {
+ return collection_->token_enumerator()->GetTokenId(
+ Top::context()->global()->global_context()->security_token());
+}
+
+
+int HeapSnapshotGenerator::GetObjectSecurityToken(HeapObject* obj) {
+ if (obj->IsGlobalContext()) {
+ return collection_->token_enumerator()->GetTokenId(
+ Context::cast(obj)->security_token());
+ } else {
+ return TokenEnumerator::kNoSecurityToken;
+ }
+}
+
+
class IndexedReferencesExtractor : public ObjectVisitor {
public:
IndexedReferencesExtractor(HeapSnapshotGenerator* generator,
@@ -1877,11 +1893,19 @@ class IndexedReferencesExtractor : public ObjectVisitor {
void HeapSnapshotGenerator::ExtractReferences(HeapObject* obj) {
// We need to reference JS global objects from snapshot's root.
- // We use JSGlobalProxy because this is what embedder (e.g. browser)
- // uses for the global object.
+ // We also need to only include global objects from the current
+ // security context. And we don't want to add the global proxy,
+ // as we don't have a special type for it.
if (obj->IsJSGlobalProxy()) {
+ int global_security_token = GetGlobalSecurityToken();
JSGlobalProxy* proxy = JSGlobalProxy::cast(obj);
- SetRootReference(proxy->map()->prototype());
+ int object_security_token =
+ collection_->token_enumerator()->GetTokenId(
+ Context::cast(proxy->context())->security_token());
+ if (object_security_token == TokenEnumerator::kNoSecurityToken
+ || object_security_token == global_security_token) {
+ SetRootReference(proxy->map()->prototype());
+ }
return;
}
diff --git a/deps/v8/src/profile-generator.h b/deps/v8/src/profile-generator.h
index b691a056e85..6f63f6a122b 100644
--- a/deps/v8/src/profile-generator.h
+++ b/deps/v8/src/profile-generator.h
@@ -948,6 +948,8 @@ class HeapSnapshotGenerator {
private:
HeapEntry* GetEntry(Object* obj);
+ int GetGlobalSecurityToken();
+ int GetObjectSecurityToken(HeapObject* obj);
void ExtractReferences(HeapObject* obj);
void ExtractClosureReferences(JSObject* js_obj, HeapEntry* entry);
void ExtractPropertyReferences(JSObject* js_obj, HeapEntry* entry);
diff --git a/deps/v8/src/regexp.js b/deps/v8/src/regexp.js
index 9e708fd07b8..51f4b094d37 100644
--- a/deps/v8/src/regexp.js
+++ b/deps/v8/src/regexp.js
@@ -71,6 +71,9 @@ function DoConstructRegExp(object, pattern, flags, isConstructorCall) {
}
}
+ if (!isConstructorCall) {
+ regExpCache.type = 'none';
+ }
%RegExpInitializeObject(object, pattern, global, ignoreCase, multiline);
// Call internal function to compile the pattern.
@@ -118,6 +121,22 @@ function DoRegExpExec(regexp, string, index) {
}
+function RegExpCache() {
+ this.type = 'none';
+ this.regExp = 0;
+ this.subject = 0;
+ this.replaceString = 0;
+ this.answer = 0;
+ // answerSaved marks whether the contents of answer is valid for a cache
+ // hit in RegExpExec, StringMatch and StringSplit.
+ this.answerSaved = false;
+ this.splitLimit = 0; // Used only when type is "split".
+}
+
+
+var regExpCache = new RegExpCache();
+
+
function BuildResultFromMatchInfo(lastMatchInfo, s) {
var numResults = NUMBER_OF_CAPTURES(lastMatchInfo) >> 1;
var result = %_RegExpConstructResult(numResults, lastMatchInfo[CAPTURE0], s);
@@ -159,6 +178,32 @@ function RegExpExec(string) {
['RegExp.prototype.exec', this]);
}
+ var cache = regExpCache;
+ var saveAnswer = false;
+
+ var lastIndex = this.lastIndex;
+
+ // Since cache.subject is always a string, a matching input can not
+ // cause visible side-effects when converted to a string, so we can omit
+ // the conversion required by the specification.
+ // Likewise, the regexp.lastIndex and regexp.global properties are value
+ // properties that are not configurable, so reading them can also not cause
+ // any side effects (converting lastIndex to a number can, though).
+ if (%_ObjectEquals(cache.type, 'exec') &&
+ %_ObjectEquals(0, lastIndex) &&
+ %_IsRegExpEquivalent(cache.regExp, this) &&
+ %_ObjectEquals(cache.subject, string)) {
+ if (cache.answerSaved) {
+ // The regexp.lastIndex value must be 0 for non-global RegExps, and for
+ // global RegExps we only cache negative results, which gives a lastIndex
+ // of zero as well.
+ this.lastIndex = 0;
+ return %_RegExpCloneResult(cache.answer);
+ } else {
+ saveAnswer = true;
+ }
+ }
+
if (%_ArgumentsLength() === 0) {
var regExpInput = LAST_INPUT(lastMatchInfo);
if (IS_UNDEFINED(regExpInput)) {
@@ -172,13 +217,11 @@ function RegExpExec(string) {
} else {
s = ToString(string);
}
- var lastIndex = this.lastIndex;
+ var global = this.global;
// Conversion is required by the ES5 specification (RegExp.prototype.exec
// algorithm, step 5) even if the value is discarded for non-global RegExps.
var i = TO_INTEGER(lastIndex);
-
- var global = this.global;
if (global) {
if (i < 0 || i > s.length) {
this.lastIndex = 0;
@@ -194,9 +237,16 @@ function RegExpExec(string) {
if (matchIndices === null) {
if (global) {
+ // Cache negative result only if initial lastIndex was zero.
this.lastIndex = 0;
+ if (lastIndex !== 0) return matchIndices;
}
- return null;
+ cache.regExp = this;
+ cache.subject = s; // Always a string.
+ cache.answer = null;
+ cache.answerSaved = true; // Safe since no cloning is needed.
+ cache.type = 'exec';
+ return matchIndices; // No match.
}
// Successful match.
@@ -204,9 +254,17 @@ function RegExpExec(string) {
var result = BuildResultFromMatchInfo(matchIndices, s);
if (global) {
+ // Don't cache positive results for global regexps.
this.lastIndex = lastMatchInfo[CAPTURE1];
+ } else {
+ cache.regExp = this;
+ cache.subject = s;
+ if (saveAnswer) cache.answer = %_RegExpCloneResult(result);
+ cache.answerSaved = saveAnswer;
+ cache.type = 'exec';
}
return result;
+
}
@@ -231,22 +289,33 @@ function RegExpTest(string) {
string = regExpInput;
}
+ var lastIndex = this.lastIndex;
+
+ var cache = regExpCache;
+ if (%_ObjectEquals(cache.type, 'test') &&
+ %_IsRegExpEquivalent(cache.regExp, this) &&
+ %_ObjectEquals(cache.subject, string) &&
+ %_ObjectEquals(0, lastIndex)) {
+ // The regexp.lastIndex value must be 0 for non-global RegExps, and for
+ // global RegExps we only cache negative results, which gives a resulting
+ // lastIndex of zero as well.
+ if (global) this.lastIndex = 0;
+ return cache.answer;
+ }
+
var s;
if (IS_STRING(string)) {
s = string;
} else {
s = ToString(string);
}
-
- var lastIndex = this.lastIndex;
+ var length = s.length;
// Conversion is required by the ES5 specification (RegExp.prototype.exec
// algorithm, step 5) even if the value is discarded for non-global RegExps.
var i = TO_INTEGER(lastIndex);
-
- var global = this.global;
if (global) {
- if (i < 0 || i > s.length) {
+ if (i < 0 || i > length) {
this.lastIndex = 0;
return false;
}
@@ -254,6 +323,8 @@ function RegExpTest(string) {
i = 0;
}
+ var global = this.global;
+
// Remove irrelevant preceeding '.*' in a test regexp. The expression
// checks whether this.source starts with '.*' and that the third
// char is not a '?'
@@ -263,7 +334,7 @@ function RegExpTest(string) {
if (!%_ObjectEquals(regexp_key, this)) {
regexp_key = this;
regexp_val = new $RegExp(this.source.substring(2, this.source.length),
- (global ? 'g' : '')
+ (this.global ? 'g' : '')
+ (this.ignoreCase ? 'i' : '')
+ (this.multiline ? 'm' : ''));
}
@@ -274,13 +345,24 @@ function RegExpTest(string) {
// matchIndices is either null or the lastMatchInfo array.
var matchIndices = %_RegExpExec(this, s, i, lastMatchInfo);
- if (matchIndices === null) {
- if (global) this.lastIndex = 0;
- return false;
+ var result = (matchIndices !== null);
+ if (result) {
+ lastMatchInfoOverride = null;
}
- lastMatchInfoOverride = null;
- if (global) this.lastIndex = lastMatchInfo[CAPTURE1];
- return true;
+ if (global) {
+ if (result) {
+ this.lastIndex = lastMatchInfo[CAPTURE1];
+ return true;
+ } else {
+ this.lastIndex = 0;
+ if (lastIndex !== 0) return false;
+ }
+ }
+ cache.type = 'test';
+ cache.regExp = this;
+ cache.subject = s;
+ cache.answer = result;
+ return result;
}
@@ -428,6 +510,7 @@ function SetupRegExp() {
return IS_UNDEFINED(regExpInput) ? "" : regExpInput;
}
function RegExpSetInput(string) {
+ regExpCache.type = 'none';
LAST_INPUT(lastMatchInfo) = ToString(string);
};
diff --git a/deps/v8/src/runtime.cc b/deps/v8/src/runtime.cc
index 5534db557ce..fc1a0232295 100644
--- a/deps/v8/src/runtime.cc
+++ b/deps/v8/src/runtime.cc
@@ -1424,6 +1424,66 @@ static MaybeObject* Runtime_RegExpConstructResult(Arguments args) {
}
+static MaybeObject* Runtime_RegExpCloneResult(Arguments args) {
+ ASSERT(args.length() == 1);
+ Map* regexp_result_map;
+ {
+ AssertNoAllocation no_gc;
+ HandleScope handles;
+ regexp_result_map = Top::global_context()->regexp_result_map();
+ }
+ if (!args[0]->IsJSArray()) return args[0];
+
+ JSArray* result = JSArray::cast(args[0]);
+ // Arguments to RegExpCloneResult should always be fresh RegExp exec call
+ // results (either a fresh JSRegExpResult or null).
+ // If the argument is not a JSRegExpResult, or isn't unmodified, just return
+ // the argument uncloned.
+ if (result->map() != regexp_result_map) return result;
+
+ // Having the original JSRegExpResult map guarantees that we have
+ // fast elements and no properties except the two in-object properties.
+ ASSERT(result->HasFastElements());
+ ASSERT(result->properties() == Heap::empty_fixed_array());
+ ASSERT_EQ(2, regexp_result_map->inobject_properties());
+
+ Object* new_array_alloc;
+ { MaybeObject* maybe_new_array_alloc =
+ Heap::AllocateRaw(JSRegExpResult::kSize, NEW_SPACE, OLD_POINTER_SPACE);
+ if (!maybe_new_array_alloc->ToObject(&new_array_alloc)) {
+ return maybe_new_array_alloc;
+ }
+ }
+
+ // Set HeapObject map to JSRegExpResult map.
+ reinterpret_cast<HeapObject*>(new_array_alloc)->set_map(regexp_result_map);
+
+ JSArray* new_array = JSArray::cast(new_array_alloc);
+
+ // Copy JSObject properties.
+ new_array->set_properties(result->properties()); // Empty FixedArray.
+
+ // Copy JSObject elements as copy-on-write.
+ FixedArray* elements = FixedArray::cast(result->elements());
+ if (elements != Heap::empty_fixed_array()) {
+ elements->set_map(Heap::fixed_cow_array_map());
+ }
+ new_array->set_elements(elements);
+
+ // Copy JSArray length.
+ new_array->set_length(result->length());
+
+ // Copy JSRegExpResult in-object property fields input and index.
+ new_array->FastPropertyAtPut(JSRegExpResult::kIndexIndex,
+ result->FastPropertyAt(
+ JSRegExpResult::kIndexIndex));
+ new_array->FastPropertyAtPut(JSRegExpResult::kInputIndex,
+ result->FastPropertyAt(
+ JSRegExpResult::kInputIndex));
+ return new_array;
+}
+
+
static MaybeObject* Runtime_RegExpInitializeObject(Arguments args) {
AssertNoAllocation no_alloc;
ASSERT(args.length() == 5);
@@ -8831,6 +8891,12 @@ static MaybeObject* Runtime_DebugPrintScopes(Arguments args) {
}
+static MaybeObject* Runtime_GetCFrames(Arguments args) {
+ // See bug 906.
+ return Heap::undefined_value();
+}
+
+
static MaybeObject* Runtime_GetThreadCount(Arguments args) {
HandleScope scope;
ASSERT(args.length() == 1);
diff --git a/deps/v8/src/runtime.h b/deps/v8/src/runtime.h
index 756099b413f..72a80379701 100644
--- a/deps/v8/src/runtime.h
+++ b/deps/v8/src/runtime.h
@@ -162,6 +162,7 @@ namespace internal {
F(RegExpExecMultiple, 4, 1) \
F(RegExpInitializeObject, 5, 1) \
F(RegExpConstructResult, 3, 1) \
+ F(RegExpCloneResult, 1, 1) \
\
/* JSON */ \
F(ParseJson, 1, 1) \
@@ -324,6 +325,7 @@ namespace internal {
F(GetScopeCount, 2, 1) \
F(GetScopeDetails, 3, 1) \
F(DebugPrintScopes, 0, 1) \
+ F(GetCFrames, 1, 1) \
F(GetThreadCount, 1, 1) \
F(GetThreadDetails, 2, 1) \
F(SetDisableBreak, 1, 1) \
@@ -424,7 +426,7 @@ namespace internal {
// ----------------------------------------------------------------------------
// INLINE_AND_RUNTIME_FUNCTION_LIST defines all inlined functions accessed
// with a native call of the form %_name from within JS code that also have
-// a corresponding runtime function, that is called for slow cases.
+ // a corresponding runtime function, that is called for slow cases.
// Entries have the form F(name, number of arguments, number of return values).
#define INLINE_RUNTIME_FUNCTION_LIST(F) \
F(IsConstructCall, 0, 1) \
@@ -436,6 +438,7 @@ namespace internal {
F(StringCompare, 2, 1) \
F(RegExpExec, 4, 1) \
F(RegExpConstructResult, 3, 1) \
+ F(RegExpCloneResult, 1, 1) \
F(GetFromCache, 2, 1) \
F(NumberToString, 1, 1) \
F(SwapElements, 3, 1)
diff --git a/deps/v8/src/scanner-base.cc b/deps/v8/src/scanner-base.cc
deleted file mode 100644
index 6e9d40e0d19..00000000000
--- a/deps/v8/src/scanner-base.cc
+++ /dev/null
@@ -1,167 +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.
-
-// Features shared by parsing and pre-parsing scanners.
-
-#include "scanner-base.h"
-
-namespace v8 {
-namespace internal {
-
-// ----------------------------------------------------------------------------
-// Keyword Matcher
-
-KeywordMatcher::FirstState KeywordMatcher::first_states_[] = {
- { "break", KEYWORD_PREFIX, Token::BREAK },
- { NULL, C, Token::ILLEGAL },
- { NULL, D, Token::ILLEGAL },
- { "else", KEYWORD_PREFIX, Token::ELSE },
- { NULL, F, Token::ILLEGAL },
- { NULL, UNMATCHABLE, Token::ILLEGAL },
- { NULL, UNMATCHABLE, Token::ILLEGAL },
- { NULL, I, Token::ILLEGAL },
- { NULL, UNMATCHABLE, Token::ILLEGAL },
- { NULL, UNMATCHABLE, Token::ILLEGAL },
- { NULL, UNMATCHABLE, Token::ILLEGAL },
- { NULL, UNMATCHABLE, Token::ILLEGAL },
- { NULL, N, Token::ILLEGAL },
- { NULL, UNMATCHABLE, Token::ILLEGAL },
- { NULL, UNMATCHABLE, Token::ILLEGAL },
- { NULL, UNMATCHABLE, Token::ILLEGAL },
- { "return", KEYWORD_PREFIX, Token::RETURN },
- { "switch", KEYWORD_PREFIX, Token::SWITCH },
- { NULL, T, Token::ILLEGAL },
- { NULL, UNMATCHABLE, Token::ILLEGAL },
- { NULL, V, Token::ILLEGAL },
- { NULL, W, Token::ILLEGAL }
-};
-
-
-void KeywordMatcher::Step(unibrow::uchar input) {
- switch (state_) {
- case INITIAL: {
- // matching the first character is the only state with significant fanout.
- // Match only lower-case letters in range 'b'..'w'.
- unsigned int offset = input - kFirstCharRangeMin;
- if (offset < kFirstCharRangeLength) {
- state_ = first_states_[offset].state;
- if (state_ == KEYWORD_PREFIX) {
- keyword_ = first_states_[offset].keyword;
- counter_ = 1;
- keyword_token_ = first_states_[offset].token;
- }
- return;
- }
- break;
- }
- case KEYWORD_PREFIX:
- if (static_cast<unibrow::uchar>(keyword_[counter_]) == input) {
- counter_++;
- if (keyword_[counter_] == '\0') {
- state_ = KEYWORD_MATCHED;
- token_ = keyword_token_;
- }
- return;
- }
- break;
- case KEYWORD_MATCHED:
- token_ = Token::IDENTIFIER;
- break;
- case C:
- if (MatchState(input, 'a', CA)) return;
- if (MatchState(input, 'o', CO)) return;
- break;
- case CA:
- if (MatchKeywordStart(input, "case", 2, Token::CASE)) return;
- if (MatchKeywordStart(input, "catch", 2, Token::CATCH)) return;
- break;
- case CO:
- if (MatchState(input, 'n', CON)) return;
- break;
- case CON:
- if (MatchKeywordStart(input, "const", 3, Token::CONST)) return;
- if (MatchKeywordStart(input, "continue", 3, Token::CONTINUE)) return;
- break;
- case D:
- if (MatchState(input, 'e', DE)) return;
- if (MatchKeyword(input, 'o', KEYWORD_MATCHED, Token::DO)) return;
- break;
- case DE:
- if (MatchKeywordStart(input, "debugger", 2, Token::DEBUGGER)) return;
- if (MatchKeywordStart(input, "default", 2, Token::DEFAULT)) return;
- if (MatchKeywordStart(input, "delete", 2, Token::DELETE)) return;
- break;
- case F:
- if (MatchKeywordStart(input, "false", 1, Token::FALSE_LITERAL)) return;
- if (MatchKeywordStart(input, "finally", 1, Token::FINALLY)) return;
- if (MatchKeywordStart(input, "for", 1, Token::FOR)) return;
- if (MatchKeywordStart(input, "function", 1, Token::FUNCTION)) return;
- break;
- case I:
- if (MatchKeyword(input, 'f', KEYWORD_MATCHED, Token::IF)) return;
- if (MatchKeyword(input, 'n', IN, Token::IN)) return;
- break;
- case IN:
- token_ = Token::IDENTIFIER;
- if (MatchKeywordStart(input, "instanceof", 2, Token::INSTANCEOF)) {
- return;
- }
- break;
- case N:
- if (MatchKeywordStart(input, "native", 1, Token::NATIVE)) return;
- if (MatchKeywordStart(input, "new", 1, Token::NEW)) return;
- if (MatchKeywordStart(input, "null", 1, Token::NULL_LITERAL)) return;
- break;
- case T:
- if (MatchState(input, 'h', TH)) return;
- if (MatchState(input, 'r', TR)) return;
- if (MatchKeywordStart(input, "typeof", 1, Token::TYPEOF)) return;
- break;
- case TH:
- if (MatchKeywordStart(input, "this", 2, Token::THIS)) return;
- if (MatchKeywordStart(input, "throw", 2, Token::THROW)) return;
- break;
- case TR:
- if (MatchKeywordStart(input, "true", 2, Token::TRUE_LITERAL)) return;
- if (MatchKeyword(input, 'y', KEYWORD_MATCHED, Token::TRY)) return;
- break;
- case V:
- if (MatchKeywordStart(input, "var", 1, Token::VAR)) return;
- if (MatchKeywordStart(input, "void", 1, Token::VOID)) return;
- break;
- case W:
- if (MatchKeywordStart(input, "while", 1, Token::WHILE)) return;
- if (MatchKeywordStart(input, "with", 1, Token::WITH)) return;
- break;
- case UNMATCHABLE:
- break;
- }
- // On fallthrough, it's a failure.
- state_ = UNMATCHABLE;
-}
-
-} } // namespace v8::internal
diff --git a/deps/v8/src/scanner-base.h b/deps/v8/src/scanner-base.h
deleted file mode 100644
index 500870b5759..00000000000
--- a/deps/v8/src/scanner-base.h
+++ /dev/null
@@ -1,165 +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.
-
-// Features shared by parsing and pre-parsing scanners.
-
-#ifndef V8_SCANNER_BASE_H_
-#define V8_SCANNER_BASE_H_
-
-#include "token.h"
-#include "unicode.h"
-
-namespace v8 {
-namespace internal {
-
-class KeywordMatcher {
-// Incrementally recognize keywords.
-//
-// Recognized keywords:
-// break case catch const* continue debugger* default delete do else
-// finally false for function if in instanceof native* new null
-// return switch this throw true try typeof var void while with
-//
-// *: Actually "future reserved keywords". These are the only ones we
-// recognized, the remaining are allowed as identifiers.
- public:
- KeywordMatcher()
- : state_(INITIAL),
- token_(Token::IDENTIFIER),
- keyword_(NULL),
- counter_(0),
- keyword_token_(Token::ILLEGAL) {}
-
- Token::Value token() { return token_; }
-
- inline void AddChar(unibrow::uchar input) {
- if (state_ != UNMATCHABLE) {
- Step(input);
- }
- }
-
- void Fail() {
- token_ = Token::IDENTIFIER;
- state_ = UNMATCHABLE;
- }
-
- private:
- enum State {
- UNMATCHABLE,
- INITIAL,
- KEYWORD_PREFIX,
- KEYWORD_MATCHED,
- C,
- CA,
- CO,
- CON,
- D,
- DE,
- F,
- I,
- IN,
- N,
- T,
- TH,
- TR,
- V,
- W
- };
-
- struct FirstState {
- const char* keyword;
- State state;
- Token::Value token;
- };
-
- // Range of possible first characters of a keyword.
- static const unsigned int kFirstCharRangeMin = 'b';
- static const unsigned int kFirstCharRangeMax = 'w';
- static const unsigned int kFirstCharRangeLength =
- kFirstCharRangeMax - kFirstCharRangeMin + 1;
- // State map for first keyword character range.
- static FirstState first_states_[kFirstCharRangeLength];
-
- // If input equals keyword's character at position, continue matching keyword
- // from that position.
- inline bool MatchKeywordStart(unibrow::uchar input,
- const char* keyword,
- int position,
- Token::Value token_if_match) {
- if (input == static_cast<unibrow::uchar>(keyword[position])) {
- state_ = KEYWORD_PREFIX;
- this->keyword_ = keyword;
- this->counter_ = position + 1;
- this->keyword_token_ = token_if_match;
- return true;
- }
- return false;
- }
-
- // If input equals match character, transition to new state and return true.
- inline bool MatchState(unibrow::uchar input, char match, State new_state) {
- if (input == static_cast<unibrow::uchar>(match)) {
- state_ = new_state;
- return true;
- }
- return false;
- }
-
- inline bool MatchKeyword(unibrow::uchar input,
- char match,
- State new_state,
- Token::Value keyword_token) {
- if (input != static_cast<unibrow::uchar>(match)) {
- return false;
- }
- state_ = new_state;
- token_ = keyword_token;
- return true;
- }
-
- void Step(unibrow::uchar input);
-
- // Current state.
- State state_;
- // Token for currently added characters.
- Token::Value token_;
-
- // Matching a specific keyword string (there is only one possible valid
- // keyword with the current prefix).
- const char* keyword_;
- int counter_;
- Token::Value keyword_token_;
-};
-
-
-
-
-
-
-} } // namespace v8::internal
-
-#endif // V8_SCANNER_BASE_H_
diff --git a/deps/v8/src/scanner.cc b/deps/v8/src/scanner.cc
index a24952ac247..79d63f1774d 100755
--- a/deps/v8/src/scanner.cc
+++ b/deps/v8/src/scanner.cc
@@ -184,6 +184,142 @@ void ExternalStringUTF16Buffer<StringType, CharType>::SeekForward(int pos) {
pos_ = pos;
}
+
+// ----------------------------------------------------------------------------
+// Keyword Matcher
+
+KeywordMatcher::FirstState KeywordMatcher::first_states_[] = {
+ { "break", KEYWORD_PREFIX, Token::BREAK },
+ { NULL, C, Token::ILLEGAL },
+ { NULL, D, Token::ILLEGAL },
+ { "else", KEYWORD_PREFIX, Token::ELSE },
+ { NULL, F, Token::ILLEGAL },
+ { NULL, UNMATCHABLE, Token::ILLEGAL },
+ { NULL, UNMATCHABLE, Token::ILLEGAL },
+ { NULL, I, Token::ILLEGAL },
+ { NULL, UNMATCHABLE, Token::ILLEGAL },
+ { NULL, UNMATCHABLE, Token::ILLEGAL },
+ { NULL, UNMATCHABLE, Token::ILLEGAL },
+ { NULL, UNMATCHABLE, Token::ILLEGAL },
+ { NULL, N, Token::ILLEGAL },
+ { NULL, UNMATCHABLE, Token::ILLEGAL },
+ { NULL, UNMATCHABLE, Token::ILLEGAL },
+ { NULL, UNMATCHABLE, Token::ILLEGAL },
+ { "return", KEYWORD_PREFIX, Token::RETURN },
+ { "switch", KEYWORD_PREFIX, Token::SWITCH },
+ { NULL, T, Token::ILLEGAL },
+ { NULL, UNMATCHABLE, Token::ILLEGAL },
+ { NULL, V, Token::ILLEGAL },
+ { NULL, W, Token::ILLEGAL }
+};
+
+
+void KeywordMatcher::Step(uc32 input) {
+ switch (state_) {
+ case INITIAL: {
+ // matching the first character is the only state with significant fanout.
+ // Match only lower-case letters in range 'b'..'w'.
+ unsigned int offset = input - kFirstCharRangeMin;
+ if (offset < kFirstCharRangeLength) {
+ state_ = first_states_[offset].state;
+ if (state_ == KEYWORD_PREFIX) {
+ keyword_ = first_states_[offset].keyword;
+ counter_ = 1;
+ keyword_token_ = first_states_[offset].token;
+ }
+ return;
+ }
+ break;
+ }
+ case KEYWORD_PREFIX:
+ if (keyword_[counter_] == input) {
+ ASSERT_NE(input, '\0');
+ counter_++;
+ if (keyword_[counter_] == '\0') {
+ state_ = KEYWORD_MATCHED;
+ token_ = keyword_token_;
+ }
+ return;
+ }
+ break;
+ case KEYWORD_MATCHED:
+ token_ = Token::IDENTIFIER;
+ break;
+ case C:
+ if (MatchState(input, 'a', CA)) return;
+ if (MatchState(input, 'o', CO)) return;
+ break;
+ case CA:
+ if (MatchKeywordStart(input, "case", 2, Token::CASE)) return;
+ if (MatchKeywordStart(input, "catch", 2, Token::CATCH)) return;
+ break;
+ case CO:
+ if (MatchState(input, 'n', CON)) return;
+ break;
+ case CON:
+ if (MatchKeywordStart(input, "const", 3, Token::CONST)) return;
+ if (MatchKeywordStart(input, "continue", 3, Token::CONTINUE)) return;
+ break;
+ case D:
+ if (MatchState(input, 'e', DE)) return;
+ if (MatchKeyword(input, 'o', KEYWORD_MATCHED, Token::DO)) return;
+ break;
+ case DE:
+ if (MatchKeywordStart(input, "debugger", 2, Token::DEBUGGER)) return;
+ if (MatchKeywordStart(input, "default", 2, Token::DEFAULT)) return;
+ if (MatchKeywordStart(input, "delete", 2, Token::DELETE)) return;
+ break;
+ case F:
+ if (MatchKeywordStart(input, "false", 1, Token::FALSE_LITERAL)) return;
+ if (MatchKeywordStart(input, "finally", 1, Token::FINALLY)) return;
+ if (MatchKeywordStart(input, "for", 1, Token::FOR)) return;
+ if (MatchKeywordStart(input, "function", 1, Token::FUNCTION)) return;
+ break;
+ case I:
+ if (MatchKeyword(input, 'f', KEYWORD_MATCHED, Token::IF)) return;
+ if (MatchKeyword(input, 'n', IN, Token::IN)) return;
+ break;
+ case IN:
+ token_ = Token::IDENTIFIER;
+ if (MatchKeywordStart(input, "instanceof", 2, Token::INSTANCEOF)) {
+ return;
+ }
+ break;
+ case N:
+ if (MatchKeywordStart(input, "native", 1, Token::NATIVE)) return;
+ if (MatchKeywordStart(input, "new", 1, Token::NEW)) return;
+ if (MatchKeywordStart(input, "null", 1, Token::NULL_LITERAL)) return;
+ break;
+ case T:
+ if (MatchState(input, 'h', TH)) return;
+ if (MatchState(input, 'r', TR)) return;
+ if (MatchKeywordStart(input, "typeof", 1, Token::TYPEOF)) return;
+ break;
+ case TH:
+ if (MatchKeywordStart(input, "this", 2, Token::THIS)) return;
+ if (MatchKeywordStart(input, "throw", 2, Token::THROW)) return;
+ break;
+ case TR:
+ if (MatchKeywordStart(input, "true", 2, Token::TRUE_LITERAL)) return;
+ if (MatchKeyword(input, 'y', KEYWORD_MATCHED, Token::TRY)) return;
+ break;
+ case V:
+ if (MatchKeywordStart(input, "var", 1, Token::VAR)) return;
+ if (MatchKeywordStart(input, "void", 1, Token::VOID)) return;
+ break;
+ case W:
+ if (MatchKeywordStart(input, "while", 1, Token::WHILE)) return;
+ if (MatchKeywordStart(input, "with", 1, Token::WITH)) return;
+ break;
+ default:
+ UNREACHABLE();
+ }
+ // On fallthrough, it's a failure.
+ state_ = UNMATCHABLE;
+}
+
+
+
// ----------------------------------------------------------------------------
// Scanner::LiteralScope
diff --git a/deps/v8/src/scanner.h b/deps/v8/src/scanner.h
index 1f49fd0e6ec..dab3d672815 100644
--- a/deps/v8/src/scanner.h
+++ b/deps/v8/src/scanner.h
@@ -30,7 +30,6 @@
#include "token.h"
#include "char-predicates-inl.h"
-#include "scanner-base.h"
namespace v8 {
namespace internal {
@@ -143,6 +142,127 @@ class ExternalStringUTF16Buffer: public UTF16Buffer {
};
+class KeywordMatcher {
+// Incrementally recognize keywords.
+//
+// Recognized keywords:
+// break case catch const* continue debugger* default delete do else
+// finally false for function if in instanceof native* new null
+// return switch this throw true try typeof var void while with
+//
+// *: Actually "future reserved keywords". These are the only ones we
+// recognized, the remaining are allowed as identifiers.
+ public:
+ KeywordMatcher()
+ : state_(INITIAL),
+ token_(Token::IDENTIFIER),
+ keyword_(NULL),
+ counter_(0),
+ keyword_token_(Token::ILLEGAL) {}
+
+ Token::Value token() { return token_; }
+
+ inline void AddChar(uc32 input) {
+ if (state_ != UNMATCHABLE) {
+ Step(input);
+ }
+ }
+
+ void Fail() {
+ token_ = Token::IDENTIFIER;
+ state_ = UNMATCHABLE;
+ }
+
+ private:
+ enum State {
+ UNMATCHABLE,
+ INITIAL,
+ KEYWORD_PREFIX,
+ KEYWORD_MATCHED,
+ C,
+ CA,
+ CO,
+ CON,
+ D,
+ DE,
+ F,
+ I,
+ IN,
+ N,
+ T,
+ TH,
+ TR,
+ V,
+ W
+ };
+
+ struct FirstState {
+ const char* keyword;
+ State state;
+ Token::Value token;
+ };
+
+ // Range of possible first characters of a keyword.
+ static const unsigned int kFirstCharRangeMin = 'b';
+ static const unsigned int kFirstCharRangeMax = 'w';
+ static const unsigned int kFirstCharRangeLength =
+ kFirstCharRangeMax - kFirstCharRangeMin + 1;
+ // State map for first keyword character range.
+ static FirstState first_states_[kFirstCharRangeLength];
+
+ // If input equals keyword's character at position, continue matching keyword
+ // from that position.
+ inline bool MatchKeywordStart(uc32 input,
+ const char* keyword,
+ int position,
+ Token::Value token_if_match) {
+ if (input == keyword[position]) {
+ state_ = KEYWORD_PREFIX;
+ this->keyword_ = keyword;
+ this->counter_ = position + 1;
+ this->keyword_token_ = token_if_match;
+ return true;
+ }
+ return false;
+ }
+
+ // If input equals match character, transition to new state and return true.
+ inline bool MatchState(uc32 input, char match, State new_state) {
+ if (input == match) {
+ state_ = new_state;
+ return true;
+ }
+ return false;
+ }
+
+ inline bool MatchKeyword(uc32 input,
+ char match,
+ State new_state,
+ Token::Value keyword_token) {
+ if (input != match) {
+ return false;
+ }
+ state_ = new_state;
+ token_ = keyword_token;
+ return true;
+ }
+
+ void Step(uc32 input);
+
+ // Current state.
+ State state_;
+ // Token for currently added characters.
+ Token::Value token_;
+
+ // Matching a specific keyword string (there is only one possible valid
+ // keyword with the current prefix).
+ const char* keyword_;
+ int counter_;
+ Token::Value keyword_token_;
+};
+
+
+enum ParserMode { PARSE, PREPARSE };
enum ParserLanguage { JAVASCRIPT, JSON };
diff --git a/deps/v8/src/spaces.cc b/deps/v8/src/spaces.cc
index 2f3e41aea49..e3fb9233129 100644
--- a/deps/v8/src/spaces.cc
+++ b/deps/v8/src/spaces.cc
@@ -270,9 +270,8 @@ void CodeRange::TearDown() {
// -----------------------------------------------------------------------------
// MemoryAllocator
//
-intptr_t MemoryAllocator::capacity_ = 0;
-intptr_t MemoryAllocator::capacity_executable_ = 0;
-intptr_t MemoryAllocator::size_ = 0;
+intptr_t MemoryAllocator::capacity_ = 0;
+intptr_t MemoryAllocator::size_ = 0;
intptr_t MemoryAllocator::size_executable_ = 0;
List<MemoryAllocator::MemoryAllocationCallbackRegistration>
@@ -303,10 +302,8 @@ int MemoryAllocator::Pop() {
}
-bool MemoryAllocator::Setup(intptr_t capacity, intptr_t capacity_executable) {
+bool MemoryAllocator::Setup(intptr_t capacity) {
capacity_ = RoundUp(capacity, Page::kPageSize);
- capacity_executable_ = RoundUp(capacity_executable, Page::kPageSize);
- ASSERT_GE(capacity_, capacity_executable_);
// Over-estimate the size of chunks_ array. It assumes the expansion of old
// space is always in the unit of a chunk (kChunkSize) except the last
@@ -349,7 +346,6 @@ void MemoryAllocator::TearDown() {
ASSERT(top_ == max_nof_chunks_); // all chunks are free
top_ = 0;
capacity_ = 0;
- capacity_executable_ = 0;
size_ = 0;
max_nof_chunks_ = 0;
}
@@ -361,31 +357,16 @@ void* MemoryAllocator::AllocateRawMemory(const size_t requested,
if (size_ + static_cast<size_t>(requested) > static_cast<size_t>(capacity_)) {
return NULL;
}
-
void* mem;
- if (executable == EXECUTABLE) {
- // Check executable memory limit.
- if (size_executable_ + requested >
- static_cast<size_t>(capacity_executable_)) {
- LOG(StringEvent("MemoryAllocator::AllocateRawMemory",
- "V8 Executable Allocation capacity exceeded"));
- return NULL;
- }
- // Allocate executable memory either from code range or from the
- // OS.
- if (CodeRange::exists()) {
- mem = CodeRange::AllocateRawMemory(requested, allocated);
- } else {
- mem = OS::Allocate(requested, allocated, true);
- }
- // Update executable memory size.
- size_executable_ += static_cast<int>(*allocated);
+ if (executable == EXECUTABLE && CodeRange::exists()) {
+ mem = CodeRange::AllocateRawMemory(requested, allocated);
} else {
- mem = OS::Allocate(requested, allocated, false);
+ mem = OS::Allocate(requested, allocated, (executable == EXECUTABLE));
}
int alloced = static_cast<int>(*allocated);
size_ += alloced;
+ if (executable == EXECUTABLE) size_executable_ += alloced;
#ifdef DEBUG
ZapBlock(reinterpret_cast<Address>(mem), alloced);
#endif
@@ -410,7 +391,6 @@ void MemoryAllocator::FreeRawMemory(void* mem,
if (executable == EXECUTABLE) size_executable_ -= static_cast<int>(length);
ASSERT(size_ >= 0);
- ASSERT(size_executable_ >= 0);
}
diff --git a/deps/v8/src/spaces.h b/deps/v8/src/spaces.h
index 0c10d2c7795..3ed2fe8b98a 100644
--- a/deps/v8/src/spaces.h
+++ b/deps/v8/src/spaces.h
@@ -491,8 +491,8 @@ class CodeRange : public AllStatic {
class MemoryAllocator : public AllStatic {
public:
// Initializes its internal bookkeeping structures.
- // Max capacity of the total space and executable memory limit.
- static bool Setup(intptr_t max_capacity, intptr_t capacity_executable);
+ // Max capacity of the total space.
+ static bool Setup(intptr_t max_capacity);
// Deletes valid chunks.
static void TearDown();
@@ -590,12 +590,6 @@ class MemoryAllocator : public AllStatic {
// Returns allocated spaces in bytes.
static intptr_t Size() { return size_; }
- // Returns the maximum available executable bytes of heaps.
- static int AvailableExecutable() {
- if (capacity_executable_ < size_executable_) return 0;
- return capacity_executable_ - size_executable_;
- }
-
// Returns allocated executable spaces in bytes.
static intptr_t SizeExecutable() { return size_executable_; }
@@ -659,8 +653,6 @@ class MemoryAllocator : public AllStatic {
private:
// Maximum space size in bytes.
static intptr_t capacity_;
- // Maximum subset of capacity_ that can be executable
- static intptr_t capacity_executable_;
// Allocated space size in bytes.
static intptr_t size_;
diff --git a/deps/v8/src/string.js b/deps/v8/src/string.js
index d82ce05237e..d97f632b88d 100644
--- a/deps/v8/src/string.js
+++ b/deps/v8/src/string.js
@@ -144,6 +144,16 @@ function StringLastIndexOf(searchString /* position */) { // length == 1
}
+function CloneDenseArray(array) {
+ if (array === null) return null;
+ var clone = new $Array(array.length);
+ for (var i = 0; i < array.length; i++) {
+ clone[i] = array[i];
+ }
+ return clone;
+}
+
+
// ECMA-262 section 15.5.4.9
//
// This function is implementation specific. For now, we do not
@@ -162,12 +172,33 @@ function StringMatch(regexp) {
var subject = TO_STRING_INLINE(this);
if (IS_REGEXP(regexp)) {
if (!regexp.global) return regexp.exec(subject);
+
+ var cache = regExpCache;
+ var saveAnswer = false;
+
+ if (%_ObjectEquals(cache.type, 'match') &&
+ %_IsRegExpEquivalent(cache.regExp, regexp) &&
+ %_ObjectEquals(cache.subject, subject)) {
+ if (cache.answerSaved) {
+ return CloneDenseArray(cache.answer);
+ } else {
+ saveAnswer = true;
+ }
+ }
%_Log('regexp', 'regexp-match,%0S,%1r', [subject, regexp]);
// lastMatchInfo is defined in regexp.js.
- return %StringMatch(subject, regexp, lastMatchInfo);
+ var result = %StringMatch(subject, regexp, lastMatchInfo);
+ cache.type = 'match';
+ cache.regExp = regexp;
+ cache.subject = subject;
+ if (saveAnswer) cache.answer = CloneDenseArray(result);
+ cache.answerSaved = saveAnswer;
+ return result;
}
// Non-regexp argument.
regexp = new $RegExp(regexp);
+ // Don't check regexp exec cache, since the regexp is new.
+ // TODO(lrn): Change this if we start caching regexps here.
return RegExpExecNoTests(regexp, subject, 0);
}
@@ -200,6 +231,7 @@ function StringReplace(search, replace) {
if (IS_REGEXP(search)) {
%_Log('regexp', 'regexp-replace,%0r,%1S', [search, subject]);
if (IS_FUNCTION(replace)) {
+ regExpCache.type = 'none';
if (search.global) {
return StringReplaceGlobalRegExpWithFunction(subject, search, replace);
} else {
@@ -241,10 +273,24 @@ function StringReplace(search, replace) {
// Helper function for regular expressions in String.prototype.replace.
function StringReplaceRegExp(subject, regexp, replace) {
- return %StringReplaceRegExpWithString(subject,
- regexp,
- TO_STRING_INLINE(replace),
- lastMatchInfo);
+ var cache = regExpCache;
+ if (%_ObjectEquals(cache.type, 'replace') &&
+ %_IsRegExpEquivalent(cache.regExp, regexp) &&
+ %_ObjectEquals(cache.replaceString, replace) &&
+ %_ObjectEquals(cache.subject, subject)) {
+ return cache.answer;
+ }
+ replace = TO_STRING_INLINE(replace);
+ var answer = %StringReplaceRegExpWithString(subject,
+ regexp,
+ replace,
+ lastMatchInfo);
+ cache.subject = subject;
+ cache.regExp = regexp;
+ cache.replaceString = replace;
+ cache.answer = answer;
+ cache.type = 'replace';
+ return answer;
}
@@ -559,12 +605,34 @@ function StringSplit(separator, limit) {
return result;
}
+ var cache = regExpCache;
+ var saveAnswer = false;
+
+ if (%_ObjectEquals(cache.type, 'split') &&
+ %_IsRegExpEquivalent(cache.regExp, separator) &&
+ %_ObjectEquals(cache.subject, subject) &&
+ %_ObjectEquals(cache.splitLimit, limit)) {
+ if (cache.answerSaved) {
+ return CloneDenseArray(cache.answer);
+ } else {
+ saveAnswer = true;
+ }
+ }
+
+ cache.type = 'split';
+ cache.regExp = separator;
+ cache.subject = subject;
+ cache.splitLimit = limit;
+
%_Log('regexp', 'regexp-split,%0S,%1r', [subject, separator]);
if (length === 0) {
- if (DoRegExpExec(separator, subject, 0, 0) != null) {
+ cache.answerSaved = true;
+ if (splitMatch(separator, subject, 0, 0) != null) {
+ cache.answer = [];
return [];
}
+ cache.answer = [subject];
return [subject];
}
@@ -612,6 +680,8 @@ function StringSplit(separator, limit) {
startIndex = currentIndex = endIndex;
}
+ if (saveAnswer) cache.answer = CloneDenseArray(result);
+ cache.answerSaved = saveAnswer;
return result;
}
diff --git a/deps/v8/src/strtod.cc b/deps/v8/src/strtod.cc
index 0523d885f97..0ed1b0d9147 100644
--- a/deps/v8/src/strtod.cc
+++ b/deps/v8/src/strtod.cc
@@ -31,7 +31,6 @@
#include "v8.h"
#include "strtod.h"
-#include "bignum.h"
#include "cached-powers.h"
#include "double.h"
@@ -84,12 +83,44 @@ static const double exact_powers_of_ten[] = {
// 10^22 = 0x21e19e0c9bab2400000 = 0x878678326eac9 * 2^22
10000000000000000000000.0
};
+
static const int kExactPowersOfTenSize = ARRAY_SIZE(exact_powers_of_ten);
-// Maximum number of significant digits in the decimal representation.
-// In fact the value is 772 (see conversions.cc), but to give us some margin
-// we round up to 780.
-static const int kMaxSignificantDecimalDigits = 780;
+
+extern "C" double gay_strtod(const char* s00, const char** se);
+
+static double old_strtod(Vector<const char> buffer, int exponent) {
+ // gay_strtod is broken on Linux,x86. For numbers with few decimal digits
+ // the computation is done using floating-point operations which (on Linux)
+ // are prone to double-rounding errors.
+ // By adding several zeroes to the buffer gay_strtod falls back to a slower
+ // (but correct) algorithm.
+ const int kInsertedZeroesCount = 20;
+ char gay_buffer[1024];
+ Vector<char> gay_buffer_vector(gay_buffer, sizeof(gay_buffer));
+ int pos = 0;
+ for (int i = 0; i < buffer.length(); ++i) {
+ gay_buffer_vector[pos++] = buffer[i];
+ }
+ for (int i = 0; i < kInsertedZeroesCount; ++i) {
+ gay_buffer_vector[pos++] = '0';
+ }
+ exponent -= kInsertedZeroesCount;
+ gay_buffer_vector[pos++] = 'e';
+ if (exponent < 0) {
+ gay_buffer_vector[pos++] = '-';
+ exponent = -exponent;
+ }
+ const int kNumberOfExponentDigits = 5;
+ for (int i = kNumberOfExponentDigits - 1; i >= 0; i--) {
+ gay_buffer_vector[pos + i] = exponent % 10 + '0';
+ exponent /= 10;
+ }
+ pos += kNumberOfExponentDigits;
+ gay_buffer_vector[pos] = '\0';
+ return gay_strtod(gay_buffer, NULL);
+}
+
static Vector<const char> TrimLeadingZeros(Vector<const char> buffer) {
for (int i = 0; i < buffer.length(); i++) {
@@ -111,23 +142,6 @@ static Vector<const char> TrimTrailingZeros(Vector<const char> buffer) {
}
-static void TrimToMaxSignificantDigits(Vector<const char> buffer,
- int exponent,
- char* significant_buffer,
- int* significant_exponent) {
- for (int i = 0; i < kMaxSignificantDecimalDigits - 1; ++i) {
- significant_buffer[i] = buffer[i];
- }
- // The input buffer has been trimmed. Therefore the last digit must be
- // different from '0'.
- ASSERT(buffer[buffer.length() - 1] != '0');
- // Set the last digit to be non-zero. This is sufficient to guarantee
- // correct rounding.
- significant_buffer[kMaxSignificantDecimalDigits - 1] = '1';
- *significant_exponent =
- exponent + (buffer.length() - kMaxSignificantDecimalDigits);
-}
-
// Reads digits from the buffer and converts them to a uint64.
// Reads in as many digits as fit into a uint64.
// When the string starts with "1844674407370955161" no further digit is read.
@@ -360,81 +374,20 @@ static bool DiyFpStrtod(Vector<const char> buffer,
}
-// Returns the correct double for the buffer*10^exponent.
-// The variable guess should be a close guess that is either the correct double
-// or its lower neighbor (the nearest double less than the correct one).
-// Preconditions:
-// buffer.length() + exponent <= kMaxDecimalPower + 1
-// buffer.length() + exponent > kMinDecimalPower
-// buffer.length() <= kMaxDecimalSignificantDigits
-static double BignumStrtod(Vector<const char> buffer,
- int exponent,
- double guess) {
- if (guess == V8_INFINITY) {
- return guess;
- }
-
- DiyFp upper_boundary = Double(guess).UpperBoundary();
-
- ASSERT(buffer.length() + exponent <= kMaxDecimalPower + 1);
- ASSERT(buffer.length() + exponent > kMinDecimalPower);
- ASSERT(buffer.length() <= kMaxSignificantDecimalDigits);
- // Make sure that the Bignum will be able to hold all our numbers.
- // Our Bignum implementation has a separate field for exponents. Shifts will
- // consume at most one bigit (< 64 bits).
- // ln(10) == 3.3219...
- ASSERT(((kMaxDecimalPower + 1) * 333 / 100) < Bignum::kMaxSignificantBits);
- Bignum input;
- Bignum boundary;
- input.AssignDecimalString(buffer);
- boundary.AssignUInt64(upper_boundary.f());
- if (exponent >= 0) {
- input.MultiplyByPowerOfTen(exponent);
- } else {
- boundary.MultiplyByPowerOfTen(-exponent);
- }
- if (upper_boundary.e() > 0) {
- boundary.ShiftLeft(upper_boundary.e());
- } else {
- input.ShiftLeft(-upper_boundary.e());
- }
- int comparison = Bignum::Compare(input, boundary);
- if (comparison < 0) {
- return guess;
- } else if (comparison > 0) {
- return Double(guess).NextDouble();
- } else if ((Double(guess).Significand() & 1) == 0) {
- // Round towards even.
- return guess;
- } else {
- return Double(guess).NextDouble();
- }
-}
-
-
double Strtod(Vector<const char> buffer, int exponent) {
Vector<const char> left_trimmed = TrimLeadingZeros(buffer);
Vector<const char> trimmed = TrimTrailingZeros(left_trimmed);
exponent += left_trimmed.length() - trimmed.length();
if (trimmed.length() == 0) return 0.0;
- if (trimmed.length() > kMaxSignificantDecimalDigits) {
- char significant_buffer[kMaxSignificantDecimalDigits];
- int significant_exponent;
- TrimToMaxSignificantDigits(trimmed, exponent,
- significant_buffer, &significant_exponent);
- trimmed =
- Vector<const char>(significant_buffer, kMaxSignificantDecimalDigits);
- exponent = significant_exponent;
- }
if (exponent + trimmed.length() - 1 >= kMaxDecimalPower) return V8_INFINITY;
if (exponent + trimmed.length() <= kMinDecimalPower) return 0.0;
- double guess;
- if (DoubleStrtod(trimmed, exponent, &guess) ||
- DiyFpStrtod(trimmed, exponent, &guess)) {
- return guess;
+ double result;
+ if (DoubleStrtod(trimmed, exponent, &result) ||
+ DiyFpStrtod(trimmed, exponent, &result)) {
+ return result;
}
- return BignumStrtod(trimmed, exponent, guess);
+ return old_strtod(trimmed, exponent);
}
} } // namespace v8::internal
diff --git a/deps/v8/src/token.h b/deps/v8/src/token.h
index 74d9539f498..ebc7fea1cd5 100644
--- a/deps/v8/src/token.h
+++ b/deps/v8/src/token.h
@@ -28,8 +28,6 @@
#ifndef V8_TOKEN_H_
#define V8_TOKEN_H_
-#include "checks.h"
-
namespace v8 {
namespace internal {
diff --git a/deps/v8/src/utils.cc b/deps/v8/src/utils.cc
index 7096ba35ab2..45a4cd60f8d 100644
--- a/deps/v8/src/utils.cc
+++ b/deps/v8/src/utils.cc
@@ -37,6 +37,34 @@ namespace v8 {
namespace internal {
+// Implementation is from "Hacker's Delight" by Henry S. Warren, Jr.,
+// figure 3-3, page 48, where the function is called clp2.
+uint32_t RoundUpToPowerOf2(uint32_t x) {
+ ASSERT(x <= 0x80000000u);
+ x = x - 1;
+ x = x | (x >> 1);
+ x = x | (x >> 2);
+ x = x | (x >> 4);
+ x = x | (x >> 8);
+ x = x | (x >> 16);
+ return x + 1;
+}
+
+
+// Thomas Wang, Integer Hash Functions.
+// http://www.concentric.net/~Ttwang/tech/inthash.htm
+uint32_t ComputeIntegerHash(uint32_t key) {
+ uint32_t hash = key;
+ hash = ~hash + (hash << 15); // hash = (hash << 15) - hash - 1;
+ hash = hash ^ (hash >> 12);
+ hash = hash + (hash << 2);
+ hash = hash ^ (hash >> 4);
+ hash = hash * 2057; // hash = (hash + (hash << 3)) + (hash << 11);
+ hash = hash ^ (hash >> 16);
+ return hash;
+}
+
+
void PrintF(const char* format, ...) {
va_list arguments;
va_start(arguments, format);
@@ -246,4 +274,12 @@ char* StringBuilder::Finalize() {
}
+int TenToThe(int exponent) {
+ ASSERT(exponent <= 9);
+ ASSERT(exponent >= 1);
+ int answer = 10;
+ for (int i = 1; i < exponent; i++) answer *= 10;
+ return answer;
+}
+
} } // namespace v8::internal
diff --git a/deps/v8/src/utils.h b/deps/v8/src/utils.h
index 86f4259ac61..05217677885 100644
--- a/deps/v8/src/utils.h
+++ b/deps/v8/src/utils.h
@@ -31,8 +31,6 @@
#include <stdlib.h>
#include <string.h>
-#include "checks.h"
-
namespace v8 {
namespace internal {
@@ -144,19 +142,7 @@ static int PointerValueCompare(const T* a, const T* b) {
// Returns the smallest power of two which is >= x. If you pass in a
// number that is already a power of two, it is returned as is.
-// Implementation is from "Hacker's Delight" by Henry S. Warren, Jr.,
-// figure 3-3, page 48, where the function is called clp2.
-static inline uint32_t RoundUpToPowerOf2(uint32_t x) {
- ASSERT(x <= 0x80000000u);
- x = x - 1;
- x = x | (x >> 1);
- x = x | (x >> 2);
- x = x | (x >> 4);
- x = x | (x >> 8);
- x = x | (x >> 16);
- return x + 1;
-}
-
+uint32_t RoundUpToPowerOf2(uint32_t x);
template <typename T>
@@ -230,18 +216,65 @@ class BitField {
// ----------------------------------------------------------------------------
// Hash function.
-// Thomas Wang, Integer Hash Functions.
-// http://www.concentric.net/~Ttwang/tech/inthash.htm
-static inline uint32_t ComputeIntegerHash(uint32_t key) {
- uint32_t hash = key;
- hash = ~hash + (hash << 15); // hash = (hash << 15) - hash - 1;
- hash = hash ^ (hash >> 12);
- hash = hash + (hash << 2);
- hash = hash ^ (hash >> 4);
- hash = hash * 2057; // hash = (hash + (hash << 3)) + (hash << 11);
- hash = hash ^ (hash >> 16);
- return hash;
-}
+uint32_t ComputeIntegerHash(uint32_t key);
+
+
+// ----------------------------------------------------------------------------
+// I/O support.
+
+#if __GNUC__ >= 4
+// On gcc we can ask the compiler to check the types of %d-style format
+// specifiers and their associated arguments. TODO(erikcorry) fix this
+// so it works on MacOSX.
+#if defined(__MACH__) && defined(__APPLE__)
+#define PRINTF_CHECKING
+#else // MacOsX.
+#define PRINTF_CHECKING __attribute__ ((format (printf, 1, 2)))
+#endif
+#else
+#define PRINTF_CHECKING
+#endif
+
+// Our version of printf().
+void PRINTF_CHECKING PrintF(const char* format, ...);
+
+// Our version of fflush.
+void Flush();
+
+
+// Read a line of characters after printing the prompt to stdout. The resulting
+// char* needs to be disposed off with DeleteArray by the caller.
+char* ReadLine(const char* prompt);
+
+
+// Read and return the raw bytes in a file. the size of the buffer is returned
+// in size.
+// The returned buffer must be freed by the caller.
+byte* ReadBytes(const char* filename, int* size, bool verbose = true);
+
+
+// Write size chars from str to the file given by filename.
+// The file is overwritten. Returns the number of chars written.
+int WriteChars(const char* filename,
+ const char* str,
+ int size,
+ bool verbose = true);
+
+
+// Write size bytes to the file given by filename.
+// The file is overwritten. Returns the number of bytes written.
+int WriteBytes(const char* filename,
+ const byte* bytes,
+ int size,
+ bool verbose = true);
+
+
+// Write the C code
+// const char* <varname> = "<str>";
+// const int <varname>_len = <len>;
+// to the file given by filename. Only the first len chars are written.
+int WriteAsCFile(const char* filename, const char* varname,
+ const char* str, int size, bool verbose = true);
// ----------------------------------------------------------------------------
@@ -383,6 +416,23 @@ class Vector {
};
+// A temporary assignment sets a (non-local) variable to a value on
+// construction and resets it the value on destruction.
+template <typename T>
+class TempAssign {
+ public:
+ TempAssign(T* var, T value): var_(var), old_value_(*var) {
+ *var = value;
+ }
+
+ ~TempAssign() { *var_ = old_value_; }
+
+ private:
+ T* var_;
+ T old_value_;
+};
+
+
template <typename T, int kSize>
class EmbeddedVector : public Vector<T> {
public:
@@ -434,6 +484,13 @@ inline Vector<char> MutableCStrVector(char* data, int max) {
return Vector<char>(data, (length < max) ? length : max);
}
+template <typename T>
+inline Vector< Handle<Object> > HandleVector(v8::internal::Handle<T>* elms,
+ int length) {
+ return Vector< Handle<Object> >(
+ reinterpret_cast<v8::internal::Handle<Object>*>(elms), length);
+}
+
/*
* A class that collects values into a backing store.
@@ -642,6 +699,156 @@ class SequenceCollector : public Collector<T, growth_factor, max_growth> {
};
+// Simple support to read a file into a 0-terminated C-string.
+// The returned buffer must be freed by the caller.
+// On return, *exits tells whether the file existed.
+Vector<const char> ReadFile(const char* filename,
+ bool* exists,
+ bool verbose = true);
+
+
+// Simple wrapper that allows an ExternalString to refer to a
+// Vector<const char>. Doesn't assume ownership of the data.
+class AsciiStringAdapter: public v8::String::ExternalAsciiStringResource {
+ public:
+ explicit AsciiStringAdapter(Vector<const char> data) : data_(data) {}
+
+ virtual const char* data() const { return data_.start(); }
+
+ virtual size_t length() const { return data_.length(); }
+
+ private:
+ Vector<const char> data_;
+};
+
+
+// Helper class for building result strings in a character buffer. The
+// purpose of the class is to use safe operations that checks the
+// buffer bounds on all operations in debug mode.
+class StringBuilder {
+ public:
+ // Create a string builder with a buffer of the given size. The
+ // buffer is allocated through NewArray<char> and must be
+ // deallocated by the caller of Finalize().
+ explicit StringBuilder(int size);
+
+ StringBuilder(char* buffer, int size)
+ : buffer_(buffer, size), position_(0) { }
+
+ ~StringBuilder() { if (!is_finalized()) Finalize(); }
+
+ int size() const { return buffer_.length(); }
+
+ // Get the current position in the builder.
+ int position() const {
+ ASSERT(!is_finalized());
+ return position_;
+ }
+
+ // Reset the position.
+ void Reset() { position_ = 0; }
+
+ // Add a single character to the builder. It is not allowed to add
+ // 0-characters; use the Finalize() method to terminate the string
+ // instead.
+ void AddCharacter(char c) {
+ ASSERT(c != '\0');
+ ASSERT(!is_finalized() && position_ < buffer_.length());
+ buffer_[position_++] = c;
+ }
+
+ // Add an entire string to the builder. Uses strlen() internally to
+ // compute the length of the input string.
+ void AddString(const char* s);
+
+ // Add the first 'n' characters of the given string 's' to the
+ // builder. The input string must have enough characters.
+ void AddSubstring(const char* s, int n);
+
+ // Add formatted contents to the builder just like printf().
+ void AddFormatted(const char* format, ...);
+
+ // Add character padding to the builder. If count is non-positive,
+ // nothing is added to the builder.
+ void AddPadding(char c, int count);
+
+ // Finalize the string by 0-terminating it and returning the buffer.
+ char* Finalize();
+
+ private:
+ Vector<char> buffer_;
+ int position_;
+
+ bool is_finalized() const { return position_ < 0; }
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder);
+};
+
+
+// Custom memcpy implementation for platforms where the standard version
+// may not be good enough.
+// TODO(lrn): Check whether some IA32 platforms should be excluded.
+#if defined(V8_TARGET_ARCH_IA32)
+
+// TODO(lrn): Extend to other platforms as needed.
+
+typedef void (*MemCopyFunction)(void* dest, const void* src, size_t size);
+
+// Implemented in codegen-<arch>.cc.
+MemCopyFunction CreateMemCopyFunction();
+
+// Copy memory area to disjoint memory area.
+static inline void MemCopy(void* dest, const void* src, size_t size) {
+ static MemCopyFunction memcopy = CreateMemCopyFunction();
+ (*memcopy)(dest, src, size);
+#ifdef DEBUG
+ CHECK_EQ(0, memcmp(dest, src, size));
+#endif
+}
+
+
+// Limit below which the extra overhead of the MemCopy function is likely
+// to outweigh the benefits of faster copying.
+// TODO(lrn): Try to find a more precise value.
+static const int kMinComplexMemCopy = 64;
+
+#else // V8_TARGET_ARCH_IA32
+
+static inline void MemCopy(void* dest, const void* src, size_t size) {
+ memcpy(dest, src, size);
+}
+
+static const int kMinComplexMemCopy = 256;
+
+#endif // V8_TARGET_ARCH_IA32
+
+
+// Copy from ASCII/16bit chars to ASCII/16bit chars.
+template <typename sourcechar, typename sinkchar>
+static inline void CopyChars(sinkchar* dest, const sourcechar* src, int chars) {
+ sinkchar* limit = dest + chars;
+#ifdef V8_HOST_CAN_READ_UNALIGNED
+ if (sizeof(*dest) == sizeof(*src)) {
+ if (chars >= static_cast<int>(kMinComplexMemCopy / sizeof(*dest))) {
+ MemCopy(dest, src, chars * sizeof(*dest));
+ return;
+ }
+ // Number of characters in a uintptr_t.
+ static const int kStepSize = sizeof(uintptr_t) / sizeof(*dest); // NOLINT
+ while (dest <= limit - kStepSize) {
+ *reinterpret_cast<uintptr_t*>(dest) =
+ *reinterpret_cast<const uintptr_t*>(src);
+ dest += kStepSize;
+ src += kStepSize;
+ }
+ }
+#endif
+ while (dest < limit) {
+ *dest++ = static_cast<sinkchar>(*src++);
+ }
+}
+
+
// Compare ASCII/16bit chars to ASCII/16bit chars.
template <typename lchar, typename rchar>
static inline int CompareChars(const lchar* lhs, const rchar* rhs, int chars) {
@@ -670,16 +877,56 @@ static inline int CompareChars(const lchar* lhs, const rchar* rhs, int chars) {
}
-// Calculate 10^exponent.
-static inline int TenToThe(int exponent) {
- ASSERT(exponent <= 9);
- ASSERT(exponent >= 1);
- int answer = 10;
- for (int i = 1; i < exponent; i++) answer *= 10;
- return answer;
+template <typename T>
+static inline void MemsetPointer(T** dest, T* value, int counter) {
+#if defined(V8_HOST_ARCH_IA32)
+#define STOS "stosl"
+#elif defined(V8_HOST_ARCH_X64)
+#define STOS "stosq"
+#endif
+
+#if defined(__GNUC__) && defined(STOS)
+ asm volatile(
+ "cld;"
+ "rep ; " STOS
+ : "+&c" (counter), "+&D" (dest)
+ : "a" (value)
+ : "memory", "cc");
+#else
+ for (int i = 0; i < counter; i++) {
+ dest[i] = value;
+ }
+#endif
+
+#undef STOS
}
+// Copies data from |src| to |dst|. The data spans MUST not overlap.
+inline void CopyWords(Object** dst, Object** src, int num_words) {
+ ASSERT(Min(dst, src) + num_words <= Max(dst, src));
+ ASSERT(num_words > 0);
+
+ // Use block copying memcpy if the segment we're copying is
+ // enough to justify the extra call/setup overhead.
+ static const int kBlockCopyLimit = 16;
+
+ if (num_words >= kBlockCopyLimit) {
+ memcpy(dst, src, num_words * kPointerSize);
+ } else {
+ int remaining = num_words;
+ do {
+ remaining--;
+ *dst++ = *src++;
+ } while (remaining > 0);
+ }
+}
+
+
+// Calculate 10^exponent.
+int TenToThe(int exponent);
+
+
// The type-based aliasing rule allows the compiler to assume that pointers of
// different types (for some definition of different) never alias each other.
// Thus the following code does not work:
diff --git a/deps/v8/src/v8.h b/deps/v8/src/v8.h
index 1cb8d2f1a66..9dbdf4c28a9 100644
--- a/deps/v8/src/v8.h
+++ b/deps/v8/src/v8.h
@@ -56,7 +56,7 @@
#include "globals.h"
#include "checks.h"
#include "allocation.h"
-#include "v8utils.h"
+#include "utils.h"
#include "flags.h"
// Objects & heap
diff --git a/deps/v8/src/v8utils.h b/deps/v8/src/v8utils.h
deleted file mode 100644
index a907c9f5563..00000000000
--- a/deps/v8/src/v8utils.h
+++ /dev/null
@@ -1,301 +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_V8UTILS_H_
-#define V8_V8UTILS_H_
-
-#include "utils.h"
-
-namespace v8 {
-namespace internal {
-
-// ----------------------------------------------------------------------------
-// I/O support.
-
-#if __GNUC__ >= 4
-// On gcc we can ask the compiler to check the types of %d-style format
-// specifiers and their associated arguments. TODO(erikcorry) fix this
-// so it works on MacOSX.
-#if defined(__MACH__) && defined(__APPLE__)
-#define PRINTF_CHECKING
-#else // MacOsX.
-#define PRINTF_CHECKING __attribute__ ((format (printf, 1, 2)))
-#endif
-#else
-#define PRINTF_CHECKING
-#endif
-
-// Our version of printf().
-void PRINTF_CHECKING PrintF(const char* format, ...);
-
-// Our version of fflush.
-void Flush();
-
-
-// Read a line of characters after printing the prompt to stdout. The resulting
-// char* needs to be disposed off with DeleteArray by the caller.
-char* ReadLine(const char* prompt);
-
-
-// Read and return the raw bytes in a file. the size of the buffer is returned
-// in size.
-// The returned buffer must be freed by the caller.
-byte* ReadBytes(const char* filename, int* size, bool verbose = true);
-
-
-// Write size chars from str to the file given by filename.
-// The file is overwritten. Returns the number of chars written.
-int WriteChars(const char* filename,
- const char* str,
- int size,
- bool verbose = true);
-
-
-// Write size bytes to the file given by filename.
-// The file is overwritten. Returns the number of bytes written.
-int WriteBytes(const char* filename,
- const byte* bytes,
- int size,
- bool verbose = true);
-
-
-// Write the C code
-// const char* <varname> = "<str>";
-// const int <varname>_len = <len>;
-// to the file given by filename. Only the first len chars are written.
-int WriteAsCFile(const char* filename, const char* varname,
- const char* str, int size, bool verbose = true);
-
-
-// Data structures
-
-template <typename T>
-inline Vector< Handle<Object> > HandleVector(v8::internal::Handle<T>* elms,
- int length) {
- return Vector< Handle<Object> >(
- reinterpret_cast<v8::internal::Handle<Object>*>(elms), length);
-}
-
-// Memory
-
-// Copies data from |src| to |dst|. The data spans MUST not overlap.
-inline void CopyWords(Object** dst, Object** src, int num_words) {
- ASSERT(Min(dst, src) + num_words <= Max(dst, src));
- ASSERT(num_words > 0);
-
- // Use block copying memcpy if the segment we're copying is
- // enough to justify the extra call/setup overhead.
- static const int kBlockCopyLimit = 16;
-
- if (num_words >= kBlockCopyLimit) {
- memcpy(dst, src, num_words * kPointerSize);
- } else {
- int remaining = num_words;
- do {
- remaining--;
- *dst++ = *src++;
- } while (remaining > 0);
- }
-}
-
-
-template <typename T>
-static inline void MemsetPointer(T** dest, T* value, int counter) {
-#if defined(V8_HOST_ARCH_IA32)
-#define STOS "stosl"
-#elif defined(V8_HOST_ARCH_X64)
-#define STOS "stosq"
-#endif
-
-#if defined(__GNUC__) && defined(STOS)
- asm volatile(
- "cld;"
- "rep ; " STOS
- : "+&c" (counter), "+&D" (dest)
- : "a" (value)
- : "memory", "cc");
-#else
- for (int i = 0; i < counter; i++) {
- dest[i] = value;
- }
-#endif
-
-#undef STOS
-}
-
-
-// Simple wrapper that allows an ExternalString to refer to a
-// Vector<const char>. Doesn't assume ownership of the data.
-class AsciiStringAdapter: public v8::String::ExternalAsciiStringResource {
- public:
- explicit AsciiStringAdapter(Vector<const char> data) : data_(data) {}
-
- virtual const char* data() const { return data_.start(); }
-
- virtual size_t length() const { return data_.length(); }
-
- private:
- Vector<const char> data_;
-};
-
-
-// Simple support to read a file into a 0-terminated C-string.
-// The returned buffer must be freed by the caller.
-// On return, *exits tells whether the file existed.
-Vector<const char> ReadFile(const char* filename,
- bool* exists,
- bool verbose = true);
-
-
-// Helper class for building result strings in a character buffer. The
-// purpose of the class is to use safe operations that checks the
-// buffer bounds on all operations in debug mode.
-class StringBuilder {
- public:
- // Create a string builder with a buffer of the given size. The
- // buffer is allocated through NewArray<char> and must be
- // deallocated by the caller of Finalize().
- explicit StringBuilder(int size);
-
- StringBuilder(char* buffer, int size)
- : buffer_(buffer, size), position_(0) { }
-
- ~StringBuilder() { if (!is_finalized()) Finalize(); }
-
- int size() const { return buffer_.length(); }
-
- // Get the current position in the builder.
- int position() const {
- ASSERT(!is_finalized());
- return position_;
- }
-
- // Reset the position.
- void Reset() { position_ = 0; }
-
- // Add a single character to the builder. It is not allowed to add
- // 0-characters; use the Finalize() method to terminate the string
- // instead.
- void AddCharacter(char c) {
- ASSERT(c != '\0');
- ASSERT(!is_finalized() && position_ < buffer_.length());
- buffer_[position_++] = c;
- }
-
- // Add an entire string to the builder. Uses strlen() internally to
- // compute the length of the input string.
- void AddString(const char* s);
-
- // Add the first 'n' characters of the given string 's' to the
- // builder. The input string must have enough characters.
- void AddSubstring(const char* s, int n);
-
- // Add formatted contents to the builder just like printf().
- void AddFormatted(const char* format, ...);
-
- // Add character padding to the builder. If count is non-positive,
- // nothing is added to the builder.
- void AddPadding(char c, int count);
-
- // Finalize the string by 0-terminating it and returning the buffer.
- char* Finalize();
-
- private:
- Vector<char> buffer_;
- int position_;
-
- bool is_finalized() const { return position_ < 0; }
-
- DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder);
-};
-
-
-// Custom memcpy implementation for platforms where the standard version
-// may not be good enough.
-#if defined(V8_TARGET_ARCH_IA32)
-
-// The default memcpy on ia32 architectures is generally not as efficient
-// as possible. (If any further ia32 platforms are introduced where the
-// memcpy function is efficient, exclude them from this branch).
-
-typedef void (*MemCopyFunction)(void* dest, const void* src, size_t size);
-
-// Implemented in codegen-<arch>.cc.
-MemCopyFunction CreateMemCopyFunction();
-
-// Copy memory area to disjoint memory area.
-static inline void MemCopy(void* dest, const void* src, size_t size) {
- static MemCopyFunction memcopy = CreateMemCopyFunction();
- (*memcopy)(dest, src, size);
-#ifdef DEBUG
- CHECK_EQ(0, memcmp(dest, src, size));
-#endif
-}
-
-// Limit below which the extra overhead of the MemCopy function is likely
-// to outweigh the benefits of faster copying.
-static const int kMinComplexMemCopy = 64;
-
-#else // V8_TARGET_ARCH_IA32
-
-static inline void MemCopy(void* dest, const void* src, size_t size) {
- memcpy(dest, src, size);
-}
-
-static const int kMinComplexMemCopy = 256;
-
-#endif // V8_TARGET_ARCH_IA32
-
-
-// Copy from ASCII/16bit chars to ASCII/16bit chars.
-template <typename sourcechar, typename sinkchar>
-static inline void CopyChars(sinkchar* dest, const sourcechar* src, int chars) {
- sinkchar* limit = dest + chars;
-#ifdef V8_HOST_CAN_READ_UNALIGNED
- if (sizeof(*dest) == sizeof(*src)) {
- if (chars >= static_cast<int>(kMinComplexMemCopy / sizeof(*dest))) {
- MemCopy(dest, src, chars * sizeof(*dest));
- return;
- }
- // Number of characters in a uintptr_t.
- static const int kStepSize = sizeof(uintptr_t) / sizeof(*dest); // NOLINT
- while (dest <= limit - kStepSize) {
- *reinterpret_cast<uintptr_t*>(dest) =
- *reinterpret_cast<const uintptr_t*>(src);
- dest += kStepSize;
- src += kStepSize;
- }
- }
-#endif
- while (dest < limit) {
- *dest++ = static_cast<sinkchar>(*src++);
- }
-}
-
-} } // namespace v8::internal
-
-#endif // V8_V8UTILS_H_
diff --git a/deps/v8/src/version.cc b/deps/v8/src/version.cc
index b45510ca1b8..e27b9153fcc 100644
--- a/deps/v8/src/version.cc
+++ b/deps/v8/src/version.cc
@@ -34,7 +34,7 @@
// cannot be changed without changing the SCons build script.
#define MAJOR_VERSION 2
#define MINOR_VERSION 5
-#define BUILD_NUMBER 6
+#define BUILD_NUMBER 3
#define PATCH_LEVEL 0
#define CANDIDATE_VERSION false
diff --git a/deps/v8/src/x64/assembler-x64.cc b/deps/v8/src/x64/assembler-x64.cc
index caed7c8aa9b..bf5ee5bbb77 100644
--- a/deps/v8/src/x64/assembler-x64.cc
+++ b/deps/v8/src/x64/assembler-x64.cc
@@ -296,7 +296,7 @@ static void InitCoverageLog();
byte* Assembler::spare_buffer_ = NULL;
Assembler::Assembler(void* buffer, int buffer_size)
- : code_targets_(100), positions_recorder_(this) {
+ : code_targets_(100) {
if (buffer == NULL) {
// Do our own buffer management.
if (buffer_size <= kMinimalBufferSize) {
@@ -337,7 +337,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
@@ -842,7 +845,7 @@ void Assembler::call(Label* L) {
void Assembler::call(Handle<Code> target, RelocInfo::Mode rmode) {
- positions_recorder()->WriteRecordedPositions();
+ WriteRecordedPositions();
EnsureSpace ensure_space(this);
last_pc_ = pc_;
// 1110 1000 #32-bit disp.
@@ -2932,14 +2935,14 @@ void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
}
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);
}
@@ -2953,6 +2956,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;
+}
+
+
const int RelocInfo::kApplyMask = RelocInfo::kCodeTargetMask |
1 << RelocInfo::INTERNAL_REFERENCE;
diff --git a/deps/v8/src/x64/assembler-x64.h b/deps/v8/src/x64/assembler-x64.h
index c7f763222e6..bbc10106276 100644
--- a/deps/v8/src/x64/assembler-x64.h
+++ b/deps/v8/src/x64/assembler-x64.h
@@ -1174,9 +1174,13 @@ class Assembler : public Malloced {
// Use --debug_code to enable.
void RecordComment(const char* msg);
- int pc_offset() const { return static_cast<int>(pc_ - buffer_); }
+ void RecordPosition(int pos);
+ void RecordStatementPosition(int pos);
+ bool WriteRecordedPositions();
- PositionsRecorder* positions_recorder() { return &positions_recorder_; }
+ int pc_offset() const { return static_cast<int>(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
@@ -1400,8 +1404,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/x64/codegen-x64.cc b/deps/v8/src/x64/codegen-x64.cc
index e0e40950e90..0faf775d51c 100644
--- a/deps/v8/src/x64/codegen-x64.cc
+++ b/deps/v8/src/x64/codegen-x64.cc
@@ -2956,7 +2956,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 {
@@ -6564,6 +6564,86 @@ void CodeGenerator::GenerateRegExpConstructResult(ZoneList<Expression*>* args) {
}
+void CodeGenerator::GenerateRegExpCloneResult(ZoneList<Expression*>* args) {
+ ASSERT_EQ(1, args->length());
+
+ Load(args->at(0));
+ Result object_result = frame_->Pop();
+ object_result.ToRegister(rax);
+ object_result.Unuse();
+ {
+ VirtualFrame::SpilledScope spilled_scope;
+
+ Label done;
+ __ JumpIfSmi(rax, &done);
+
+ // Load JSRegExpResult map into rdx.
+ // 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.
+
+ __ movq(rdx, ContextOperand(rsi, Context::GLOBAL_INDEX));
+ __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalContextOffset));
+ __ movq(rdx, ContextOperand(rdx, Context::REGEXP_RESULT_MAP_INDEX));
+ __ cmpq(rdx, FieldOperand(rax, HeapObject::kMapOffset));
+ __ j(not_equal, &done);
+
+ if (FLAG_debug_code) {
+ // Check that object really has empty properties array, as the map
+ // should guarantee.
+ __ CompareRoot(FieldOperand(rax, JSObject::kPropertiesOffset),
+ Heap::kEmptyFixedArrayRootIndex);
+ __ Check(equal, "JSRegExpResult: default map but non-empty properties.");
+ }
+
+ DeferredAllocateInNewSpace* allocate_fallback =
+ new DeferredAllocateInNewSpace(JSRegExpResult::kSize,
+ rbx,
+ rdx.bit() | rax.bit());
+
+ // All set, copy the contents to a new object.
+ __ AllocateInNewSpace(JSRegExpResult::kSize,
+ rbx,
+ no_reg,
+ no_reg,
+ allocate_fallback->entry_label(),
+ TAG_OBJECT);
+ __ bind(allocate_fallback->exit_label());
+
+ 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.
+ __ movq(rdx, FieldOperand(rax, i));
+ }
+ __ movq(rcx, FieldOperand(rax, 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;
+ __ CompareRoot(rdx, Heap::kEmptyFixedArrayRootIndex);
+ __ j(equal, &empty);
+ __ LoadRoot(kScratchRegister, Heap::kFixedCOWArrayMapRootIndex);
+ __ movq(FieldOperand(rdx, HeapObject::kMapOffset), kScratchRegister);
+ __ bind(&empty);
+ }
+ __ movq(FieldOperand(rbx, i), rdx);
+ __ movq(FieldOperand(rbx, i + kPointerSize), rcx);
+ }
+ __ movq(rax, rbx);
+
+ __ bind(&done);
+ }
+ frame_->Push(rax);
+}
+
+
class DeferredSearchCache: public DeferredCode {
public:
DeferredSearchCache(Register dst,
diff --git a/deps/v8/src/x64/codegen-x64.h b/deps/v8/src/x64/codegen-x64.h
index 1853c8327aa..795732451c3 100644
--- a/deps/v8/src/x64/codegen-x64.h
+++ b/deps/v8/src/x64/codegen-x64.h
@@ -656,6 +656,8 @@ class CodeGenerator: public AstVisitor {
void GenerateRegExpConstructResult(ZoneList<Expression*>* args);
+ void GenerateRegExpCloneResult(ZoneList<Expression*>* args);
+
// Support for fast native caches.
void GenerateGetFromCache(ZoneList<Expression*>* args);
diff --git a/deps/v8/src/x64/full-codegen-x64.cc b/deps/v8/src/x64/full-codegen-x64.cc
index 00ea684582a..4e0f6d4b624 100644
--- a/deps/v8/src/x64/full-codegen-x64.cc
+++ b/deps/v8/src/x64/full-codegen-x64.cc
@@ -1717,14 +1717,12 @@ void FullCodeGenerator::EmitCallWithIC(Call* expr,
// Code common for calls using the IC.
ZoneList<Expression*>* 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));
- }
- __ Move(rcx, name);
+ for (int i = 0; i < arg_count; i++) {
+ VisitForStackValue(args->at(i));
}
+ __ Move(rcx, 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<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count,
@@ -1742,15 +1740,13 @@ void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr,
// Code common for calls using the IC.
ZoneList<Expression*>* 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);
- __ movq(rcx, rax);
+ for (int i = 0; i < arg_count; i++) {
+ VisitForStackValue(args->at(i));
}
+ VisitForAccumulatorValue(key);
+ __ movq(rcx, rax);
// 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<Code> ic = CodeGenerator::ComputeKeyedCallInitialize(arg_count,
@@ -1766,13 +1762,11 @@ void FullCodeGenerator::EmitCallWithStub(Call* expr) {
// Code common for calls using the call stub.
ZoneList<Expression*>* 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);
@@ -1793,38 +1787,37 @@ void FullCodeGenerator::VisitCall(Call* expr) {
// resolve the function we need to call and the receiver of the
// call. The we call the resolved function using the given
// arguments.
+ VisitForStackValue(fun);
+ __ PushRoot(Heap::kUndefinedValueRootIndex); // Reserved receiver slot.
+
+ // Push the arguments.
ZoneList<Expression*>* args = expr->arguments();
int arg_count = args->length();
- { PreserveStatementPositionScope pos_scope(masm()->positions_recorder());
- VisitForStackValue(fun);
- __ PushRoot(Heap::kUndefinedValueRootIndex); // Reserved receiver slot.
-
- // Push the arguments.
- for (int i = 0; i < arg_count; i++) {
- VisitForStackValue(args->at(i));
- }
+ for (int i = 0; i < arg_count; i++) {
+ VisitForStackValue(args->at(i));
+ }
- // Push copy of the function - found below the arguments.
- __ push(Operand(rsp, (arg_count + 1) * kPointerSize));
+ // Push copy of the function - found below the arguments.
+ __ push(Operand(rsp, (arg_count + 1) * kPointerSize));
- // Push copy of the first argument or undefined if it doesn't exist.
- if (arg_count > 0) {
- __ push(Operand(rsp, arg_count * kPointerSize));
- } else {
+ // Push copy of the first argument or undefined if it doesn't exist.
+ if (arg_count > 0) {
+ __ push(Operand(rsp, arg_count * kPointerSize));
+ } else {
__ PushRoot(Heap::kUndefinedValueRootIndex);
- }
+ }
- // Push the receiver of the enclosing function and do runtime call.
- __ push(Operand(rbp, (2 + scope()->num_parameters()) * kPointerSize));
- __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 3);
+ // Push the receiver of the enclosing function and do runtime call.
+ __ push(Operand(rbp, (2 + scope()->num_parameters()) * kPointerSize));
+ __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 3);
+
+ // The runtime call returns a pair of values in rax (function) and
+ // rdx (receiver). Touch up the stack with the right values.
+ __ movq(Operand(rsp, (arg_count + 0) * kPointerSize), rdx);
+ __ movq(Operand(rsp, (arg_count + 1) * kPointerSize), rax);
- // The runtime call returns a pair of values in rax (function) and
- // rdx (receiver). Touch up the stack with the right values.
- __ movq(Operand(rsp, (arg_count + 0) * kPointerSize), rdx);
- __ movq(Operand(rsp, (arg_count + 1) * kPointerSize), rax);
- }
// 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);
@@ -1841,37 +1834,35 @@ 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);
-
- __ bind(&slow);
- // Call the runtime to find the function to call (returned in rax)
- // and the object holding it (returned in rdx).
- __ push(context_register());
- __ Push(var->name());
- __ CallRuntime(Runtime::kLoadContextSlot, 2);
- __ push(rax); // Function.
- __ push(rdx); // Receiver.
-
- // If fast case code has been generated, emit code to push the
- // function and receiver and have the slow path jump around this
- // code.
- if (done.is_linked()) {
- NearLabel call;
- __ jmp(&call);
- __ bind(&done);
- // Push function.
- __ push(rax);
- // Push global receiver.
- __ movq(rbx, CodeGenerator::GlobalObject());
- __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset));
- __ bind(&call);
- }
+ // 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 rax)
+ // and the object holding it (returned in rdx).
+ __ push(context_register());
+ __ Push(var->name());
+ __ CallRuntime(Runtime::kLoadContextSlot, 2);
+ __ push(rax); // Function.
+ __ push(rdx); // Receiver.
+
+ // If fast case code has been generated, emit code to push the
+ // function and receiver and have the slow path jump around this
+ // code.
+ if (done.is_linked()) {
+ NearLabel call;
+ __ jmp(&call);
+ __ bind(&done);
+ // Push function.
+ __ push(rax);
+ // Push global receiver.
+ __ movq(rbx, CodeGenerator::GlobalObject());
+ __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset));
+ __ bind(&call);
}
EmitCallWithStub(expr);
@@ -1882,24 +1873,18 @@ 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 KeyedCallIC.
- { PreserveStatementPositionScope scope(masm()->positions_recorder());
- VisitForStackValue(prop->obj());
- }
+ VisitForStackValue(prop->obj());
if (prop->is_synthetic()) {
- { PreserveStatementPositionScope scope(masm()->positions_recorder());
- VisitForAccumulatorValue(prop->key());
- __ movq(rdx, Operand(rsp, 0));
- }
+ VisitForAccumulatorValue(prop->key());
+ __ movq(rdx, Operand(rsp, 0));
// Record source code position for IC call.
- SetSourcePosition(prop->position(), FORCED_POSITION);
+ SetSourcePosition(prop->position());
Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
EmitCallIC(ic, RelocInfo::CODE_TARGET);
// Pop receiver.
@@ -1924,9 +1909,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.
__ movq(rbx, CodeGenerator::GlobalObject());
__ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset));
diff --git a/deps/v8/src/x64/ic-x64.cc b/deps/v8/src/x64/ic-x64.cc
index 9ec781487be..1d95b7f663d 100644
--- a/deps/v8/src/x64/ic-x64.cc
+++ b/deps/v8/src/x64/ic-x64.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/test/cctest/SConscript b/deps/v8/test/cctest/SConscript
index 620cd825cca..006653c2e8e 100644
--- a/deps/v8/test/cctest/SConscript
+++ b/deps/v8/test/cctest/SConscript
@@ -41,7 +41,6 @@ SOURCES = {
'test-alloc.cc',
'test-api.cc',
'test-ast.cc',
- 'test-bignum.cc',
'test-circular-queue.cc',
'test-compiler.cc',
'test-conversions.cc',
diff --git a/deps/v8/test/cctest/test-assembler-arm.cc b/deps/v8/test/cctest/test-assembler-arm.cc
index 0f12f985a36..4f90b613a83 100644
--- a/deps/v8/test/cctest/test-assembler-arm.cc
+++ b/deps/v8/test/cctest/test-assembler-arm.cc
@@ -397,72 +397,4 @@ TEST(6) {
}
}
-
-static void TestRoundingMode(int32_t mode, double value, int expected) {
- InitializeVM();
- v8::HandleScope scope;
-
- Assembler assm(NULL, 0);
-
- __ vmrs(r1);
- // Set custom FPSCR.
- __ bic(r2, r1, Operand(((mode ^ 3) << 22) | 0xf));
- __ orr(r2, r2, Operand(mode << 22));
- __ vmsr(r2);
-
- // Load value, convert, and move back result to r0.
- __ vmov(d1, value);
- __ vcvt_s32_f64(s0, d1, Assembler::FPSCRRounding, al);
- __ vmov(r0, s0);
-
- __ mov(pc, Operand(lr));
-
- CodeDesc desc;
- assm.GetCode(&desc);
- Object* code = Heap::CreateCode(
- desc,
- Code::ComputeFlags(Code::STUB),
- Handle<Object>(Heap::undefined_value()))->ToObjectChecked();
- CHECK(code->IsCode());
-#ifdef DEBUG
- Code::cast(code)->Print();
-#endif
- F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
- int res = reinterpret_cast<int>(
- CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0));
- ::printf("res = %d\n", res);
- CHECK_EQ(expected, res);
-}
-
-
-TEST(7) {
- // Test vfp rounding modes.
-
- // See ARM DDI 0406B Page A2-29.
- enum FPSCRRoungingMode {
- RN, // Round to Nearest.
- RP, // Round towards Plus Infinity.
- RM, // Round towards Minus Infinity.
- RZ // Round towards zero.
- };
-
- if (CpuFeatures::IsSupported(VFP3)) {
- CpuFeatures::Scope scope(VFP3);
-
- TestRoundingMode(RZ, 0.5, 0);
- TestRoundingMode(RZ, -0.5, 0);
- TestRoundingMode(RZ, 123.7, 123);
- TestRoundingMode(RZ, -123.7, -123);
- TestRoundingMode(RZ, 123456.2, 123456);
- TestRoundingMode(RZ, -123456.2, -123456);
-
- TestRoundingMode(RM, 0.5, 0);
- TestRoundingMode(RM, -0.5, -1);
- TestRoundingMode(RM, 123.7, 123);
- TestRoundingMode(RM, -123.7, -124);
- TestRoundingMode(RM, 123456.2, 123456);
- TestRoundingMode(RM, -123456.2, -123457);
- }
-}
-
#undef __
diff --git a/deps/v8/test/cctest/test-bignum.cc b/deps/v8/test/cctest/test-bignum.cc
deleted file mode 100644
index 9aa5ef30d0a..00000000000
--- a/deps/v8/test/cctest/test-bignum.cc
+++ /dev/null
@@ -1,1502 +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 <stdlib.h>
-
-#include "v8.h"
-
-#include "platform.h"
-#include "cctest.h"
-#include "bignum.h"
-
-using namespace v8::internal;
-
-
-static const int kBufferSize = 1024;
-
-static void AssignHexString(Bignum* bignum, const char* str) {
- bignum->AssignHexString(Vector<const char>(str, StrLength(str)));
-}
-
-
-static void AssignDecimalString(Bignum* bignum, const char* str) {
- bignum->AssignDecimalString(Vector<const char>(str, StrLength(str)));
-}
-
-
-TEST(Assign) {
- char buffer[kBufferSize];
- Bignum bignum;
- Bignum bignum2;
- bignum.AssignUInt16(0);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("0", buffer);
- bignum.AssignUInt16(0xA);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("A", buffer);
- bignum.AssignUInt16(0x20);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("20", buffer);
-
-
- bignum.AssignUInt64(0);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("0", buffer);
- bignum.AssignUInt64(0xA);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("A", buffer);
- bignum.AssignUInt64(0x20);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("20", buffer);
- bignum.AssignUInt64(0x100);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("100", buffer);
-
- // The first real test, since this will not fit into one bigit.
- bignum.AssignUInt64(0x12345678);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("12345678", buffer);
-
- uint64_t big = V8_2PART_UINT64_C(0xFFFFFFFF, FFFFFFFF);
- bignum.AssignUInt64(big);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("FFFFFFFFFFFFFFFF", buffer);
-
- big = V8_2PART_UINT64_C(0x12345678, 9ABCDEF0);
- bignum.AssignUInt64(big);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("123456789ABCDEF0", buffer);
-
- bignum2.AssignBignum(bignum);
- CHECK(bignum2.ToHexString(buffer, kBufferSize));
- CHECK_EQ("123456789ABCDEF0", buffer);
-
- AssignDecimalString(&bignum, "0");
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("0", buffer);
-
- AssignDecimalString(&bignum, "1");
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("1", buffer);
-
- AssignDecimalString(&bignum, "1234567890");
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("499602D2", buffer);
-
- AssignHexString(&bignum, "0");
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("0", buffer);
-
- AssignHexString(&bignum, "123456789ABCDEF0");
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("123456789ABCDEF0", buffer);
-}
-
-
-TEST(ShiftLeft) {
- char buffer[kBufferSize];
- Bignum bignum;
- AssignHexString(&bignum, "0");
- bignum.ShiftLeft(100);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("0", buffer);
-
- AssignHexString(&bignum, "1");
- bignum.ShiftLeft(1);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("2", buffer);
-
- AssignHexString(&bignum, "1");
- bignum.ShiftLeft(4);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("10", buffer);
-
- AssignHexString(&bignum, "1");
- bignum.ShiftLeft(32);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("100000000", buffer);
-
- AssignHexString(&bignum, "1");
- bignum.ShiftLeft(64);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("10000000000000000", buffer);
-
- AssignHexString(&bignum, "123456789ABCDEF");
- bignum.ShiftLeft(64);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("123456789ABCDEF0000000000000000", buffer);
- bignum.ShiftLeft(1);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("2468ACF13579BDE0000000000000000", buffer);
-}
-
-
-TEST(AddUInt64) {
- char buffer[kBufferSize];
- Bignum bignum;
- AssignHexString(&bignum, "0");
- bignum.AddUInt64(0xA);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("A", buffer);
-
- AssignHexString(&bignum, "1");
- bignum.AddUInt64(0xA);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("B", buffer);
-
- AssignHexString(&bignum, "1");
- bignum.AddUInt64(0x100);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("101", buffer);
-
- AssignHexString(&bignum, "1");
- bignum.AddUInt64(0xFFFF);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("10000", buffer);
-
- AssignHexString(&bignum, "FFFFFFF");
- bignum.AddUInt64(0x1);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("10000000", buffer);
-
- AssignHexString(&bignum, "10000000000000000000000000000000000000000000");
- bignum.AddUInt64(0xFFFF);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("1000000000000000000000000000000000000000FFFF", buffer);
-
- AssignHexString(&bignum, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
- bignum.AddUInt64(0x1);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("100000000000000000000000000000000000000000000", buffer);
-
- bignum.AssignUInt16(0x1);
- bignum.ShiftLeft(100);
- bignum.AddUInt64(1);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("10000000000000000000000001", buffer);
-
- bignum.AssignUInt16(0x1);
- bignum.ShiftLeft(100);
- bignum.AddUInt64(0xFFFF);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("1000000000000000000000FFFF", buffer);
-
- AssignHexString(&bignum, "0");
- bignum.AddUInt64(V8_2PART_UINT64_C(0xA, 00000000));
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("A00000000", buffer);
-
- AssignHexString(&bignum, "1");
- bignum.AddUInt64(V8_2PART_UINT64_C(0xA, 00000000));
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("A00000001", buffer);
-
- AssignHexString(&bignum, "1");
- bignum.AddUInt64(V8_2PART_UINT64_C(0x100, 00000000));
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("10000000001", buffer);
-
- AssignHexString(&bignum, "1");
- bignum.AddUInt64(V8_2PART_UINT64_C(0xFFFF, 00000000));
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("FFFF00000001", buffer);
-
- AssignHexString(&bignum, "FFFFFFF");
- bignum.AddUInt64(V8_2PART_UINT64_C(0x1, 00000000));
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("10FFFFFFF", buffer);
-
- AssignHexString(&bignum, "10000000000000000000000000000000000000000000");
- bignum.AddUInt64(V8_2PART_UINT64_C(0xFFFF, 00000000));
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("10000000000000000000000000000000FFFF00000000", buffer);
-
- AssignHexString(&bignum, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
- bignum.AddUInt64(V8_2PART_UINT64_C(0x1, 00000000));
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("1000000000000000000000000000000000000FFFFFFFF", buffer);
-
- bignum.AssignUInt16(0x1);
- bignum.ShiftLeft(100);
- bignum.AddUInt64(V8_2PART_UINT64_C(0x1, 00000000));
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("10000000000000000100000000", buffer);
-
- bignum.AssignUInt16(0x1);
- bignum.ShiftLeft(100);
- bignum.AddUInt64(V8_2PART_UINT64_C(0xFFFF, 00000000));
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("10000000000000FFFF00000000", buffer);
-}
-
-
-TEST(AddBignum) {
- char buffer[kBufferSize];
- Bignum bignum;
- Bignum other;
-
- AssignHexString(&other, "1");
- AssignHexString(&bignum, "0");
- bignum.AddBignum(other);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("1", buffer);
-
- AssignHexString(&bignum, "1");
- bignum.AddBignum(other);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("2", buffer);
-
- AssignHexString(&bignum, "FFFFFFF");
- bignum.AddBignum(other);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("10000000", buffer);
-
- AssignHexString(&bignum, "FFFFFFFFFFFFFF");
- bignum.AddBignum(other);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("100000000000000", buffer);
-
- AssignHexString(&bignum, "10000000000000000000000000000000000000000000");
- bignum.AddBignum(other);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("10000000000000000000000000000000000000000001", buffer);
-
- AssignHexString(&other, "1000000000000");
-
- AssignHexString(&bignum, "1");
- bignum.AddBignum(other);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("1000000000001", buffer);
-
- AssignHexString(&bignum, "FFFFFFF");
- bignum.AddBignum(other);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("100000FFFFFFF", buffer);
-
- AssignHexString(&bignum, "10000000000000000000000000000000000000000000");
- bignum.AddBignum(other);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("10000000000000000000000000000001000000000000", buffer);
-
- AssignHexString(&bignum, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
- bignum.AddBignum(other);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("1000000000000000000000000000000FFFFFFFFFFFF", buffer);
-
- bignum.AssignUInt16(0x1);
- bignum.ShiftLeft(100);
- bignum.AddBignum(other);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("10000000000001000000000000", buffer);
-
- other.ShiftLeft(64);
- // other == "10000000000000000000000000000"
-
- bignum.AssignUInt16(0x1);
- bignum.AddBignum(other);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("10000000000000000000000000001", buffer);
-
- AssignHexString(&bignum, "FFFFFFF");
- bignum.AddBignum(other);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("1000000000000000000000FFFFFFF", buffer);
-
- AssignHexString(&bignum, "10000000000000000000000000000000000000000000");
- bignum.AddBignum(other);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("10000000000000010000000000000000000000000000", buffer);
-
- AssignHexString(&bignum, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
- bignum.AddBignum(other);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("100000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFF", buffer);
-
- bignum.AssignUInt16(0x1);
- bignum.ShiftLeft(100);
- bignum.AddBignum(other);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("10010000000000000000000000000", buffer);
-}
-
-
-TEST(SubtractBignum) {
- char buffer[kBufferSize];
- Bignum bignum;
- Bignum other;
-
- AssignHexString(&bignum, "1");
- AssignHexString(&other, "0");
- bignum.SubtractBignum(other);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("1", buffer);
-
- AssignHexString(&bignum, "2");
- AssignHexString(&other, "0");
- bignum.SubtractBignum(other);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("2", buffer);
-
- AssignHexString(&bignum, "10000000");
- AssignHexString(&other, "1");
- bignum.SubtractBignum(other);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("FFFFFFF", buffer);
-
- AssignHexString(&bignum, "100000000000000");
- AssignHexString(&other, "1");
- bignum.SubtractBignum(other);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("FFFFFFFFFFFFFF", buffer);
-
- AssignHexString(&bignum, "10000000000000000000000000000000000000000001");
- AssignHexString(&other, "1");
- bignum.SubtractBignum(other);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("10000000000000000000000000000000000000000000", buffer);
-
- AssignHexString(&bignum, "1000000000001");
- AssignHexString(&other, "1000000000000");
- bignum.SubtractBignum(other);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("1", buffer);
-
- AssignHexString(&bignum, "100000FFFFFFF");
- AssignHexString(&other, "1000000000000");
- bignum.SubtractBignum(other);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("FFFFFFF", buffer);
-
- AssignHexString(&bignum, "10000000000000000000000000000001000000000000");
- AssignHexString(&other, "1000000000000");
- bignum.SubtractBignum(other);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("10000000000000000000000000000000000000000000", buffer);
-
- AssignHexString(&bignum, "1000000000000000000000000000000FFFFFFFFFFFF");
- AssignHexString(&other, "1000000000000");
- bignum.SubtractBignum(other);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", buffer);
-
- bignum.AssignUInt16(0x1);
- bignum.ShiftLeft(100);
- // "10 0000 0000 0000 0000 0000 0000"
- AssignHexString(&other, "1000000000000");
- bignum.SubtractBignum(other);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("FFFFFFFFFFFFF000000000000", buffer);
-
- AssignHexString(&other, "1000000000000");
- other.ShiftLeft(48);
- // other == "1000000000000000000000000"
-
- bignum.AssignUInt16(0x1);
- bignum.ShiftLeft(100);
- // bignum == "10000000000000000000000000"
- bignum.SubtractBignum(other);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("F000000000000000000000000", buffer);
-
- other.AssignUInt16(0x1);
- other.ShiftLeft(35);
- // other == "800000000"
- AssignHexString(&bignum, "FFFFFFF");
- bignum.ShiftLeft(60);
- // bignum = FFFFFFF000000000000000
- bignum.SubtractBignum(other);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("FFFFFFEFFFFFF800000000", buffer);
-
- AssignHexString(&bignum, "10000000000000000000000000000000000000000000");
- bignum.SubtractBignum(other);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000000", buffer);
-
- AssignHexString(&bignum, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
- bignum.SubtractBignum(other);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFF", buffer);
-}
-
-
-TEST(MultiplyUInt32) {
- char buffer[kBufferSize];
- Bignum bignum;
-
- AssignHexString(&bignum, "0");
- bignum.MultiplyByUInt32(0x25);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("0", buffer);
-
- AssignHexString(&bignum, "2");
- bignum.MultiplyByUInt32(0x5);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("A", buffer);
-
- AssignHexString(&bignum, "10000000");
- bignum.MultiplyByUInt32(0x9);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("90000000", buffer);
-
- AssignHexString(&bignum, "100000000000000");
- bignum.MultiplyByUInt32(0xFFFF);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("FFFF00000000000000", buffer);
-
- AssignHexString(&bignum, "100000000000000");
- bignum.MultiplyByUInt32(0xFFFFFFFF);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("FFFFFFFF00000000000000", buffer);
-
- AssignHexString(&bignum, "1234567ABCD");
- bignum.MultiplyByUInt32(0xFFF);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("12333335552433", buffer);
-
- AssignHexString(&bignum, "1234567ABCD");
- bignum.MultiplyByUInt32(0xFFFFFFF);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("12345679998A985433", buffer);
-
- AssignHexString(&bignum, "FFFFFFFFFFFFFFFF");
- bignum.MultiplyByUInt32(0x2);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("1FFFFFFFFFFFFFFFE", buffer);
-
- AssignHexString(&bignum, "FFFFFFFFFFFFFFFF");
- bignum.MultiplyByUInt32(0x4);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("3FFFFFFFFFFFFFFFC", buffer);
-
- AssignHexString(&bignum, "FFFFFFFFFFFFFFFF");
- bignum.MultiplyByUInt32(0xF);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("EFFFFFFFFFFFFFFF1", buffer);
-
- AssignHexString(&bignum, "FFFFFFFFFFFFFFFF");
- bignum.MultiplyByUInt32(0xFFFFFF);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("FFFFFEFFFFFFFFFF000001", buffer);
-
- bignum.AssignUInt16(0x1);
- bignum.ShiftLeft(100);
- // "10 0000 0000 0000 0000 0000 0000"
- bignum.MultiplyByUInt32(2);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("20000000000000000000000000", buffer);
-
- bignum.AssignUInt16(0x1);
- bignum.ShiftLeft(100);
- // "10 0000 0000 0000 0000 0000 0000"
- bignum.MultiplyByUInt32(0xF);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("F0000000000000000000000000", buffer);
-
- bignum.AssignUInt16(0xFFFF);
- bignum.ShiftLeft(100);
- // "FFFF0 0000 0000 0000 0000 0000 0000"
- bignum.MultiplyByUInt32(0xFFFF);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("FFFE00010000000000000000000000000", buffer);
-
- bignum.AssignUInt16(0xFFFF);
- bignum.ShiftLeft(100);
- // "FFFF0 0000 0000 0000 0000 0000 0000"
- bignum.MultiplyByUInt32(0xFFFFFFFF);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("FFFEFFFF00010000000000000000000000000", buffer);
-
- bignum.AssignUInt16(0xFFFF);
- bignum.ShiftLeft(100);
- // "FFFF0 0000 0000 0000 0000 0000 0000"
- bignum.MultiplyByUInt32(0xFFFFFFFF);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("FFFEFFFF00010000000000000000000000000", buffer);
-
- AssignDecimalString(&bignum, "15611230384529777");
- bignum.MultiplyByUInt32(10000000);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("210EDD6D4CDD2580EE80", buffer);
-}
-
-
-TEST(MultiplyUInt64) {
- char buffer[kBufferSize];
- Bignum bignum;
-
- AssignHexString(&bignum, "0");
- bignum.MultiplyByUInt64(0x25);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("0", buffer);
-
- AssignHexString(&bignum, "2");
- bignum.MultiplyByUInt64(0x5);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("A", buffer);
-
- AssignHexString(&bignum, "10000000");
- bignum.MultiplyByUInt64(0x9);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("90000000", buffer);
-
- AssignHexString(&bignum, "100000000000000");
- bignum.MultiplyByUInt64(0xFFFF);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("FFFF00000000000000", buffer);
-
- AssignHexString(&bignum, "100000000000000");
- bignum.MultiplyByUInt64(V8_2PART_UINT64_C(0xFFFFFFFF, FFFFFFFF));
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("FFFFFFFFFFFFFFFF00000000000000", buffer);
-
- AssignHexString(&bignum, "1234567ABCD");
- bignum.MultiplyByUInt64(0xFFF);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("12333335552433", buffer);
-
- AssignHexString(&bignum, "1234567ABCD");
- bignum.MultiplyByUInt64(V8_2PART_UINT64_C(0xFF, FFFFFFFF));
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("1234567ABCBDCBA985433", buffer);
-
- AssignHexString(&bignum, "FFFFFFFFFFFFFFFF");
- bignum.MultiplyByUInt64(0x2);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("1FFFFFFFFFFFFFFFE", buffer);
-
- AssignHexString(&bignum, "FFFFFFFFFFFFFFFF");
- bignum.MultiplyByUInt64(0x4);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("3FFFFFFFFFFFFFFFC", buffer);
-
- AssignHexString(&bignum, "FFFFFFFFFFFFFFFF");
- bignum.MultiplyByUInt64(0xF);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("EFFFFFFFFFFFFFFF1", buffer);
-
- AssignHexString(&bignum, "FFFFFFFFFFFFFFFF");
- bignum.MultiplyByUInt64(V8_2PART_UINT64_C(0xFFFFFFFF, FFFFFFFF));
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("FFFFFFFFFFFFFFFE0000000000000001", buffer);
-
- bignum.AssignUInt16(0x1);
- bignum.ShiftLeft(100);
- // "10 0000 0000 0000 0000 0000 0000"
- bignum.MultiplyByUInt64(2);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("20000000000000000000000000", buffer);
-
- bignum.AssignUInt16(0x1);
- bignum.ShiftLeft(100);
- // "10 0000 0000 0000 0000 0000 0000"
- bignum.MultiplyByUInt64(0xF);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("F0000000000000000000000000", buffer);
-
- bignum.AssignUInt16(0xFFFF);
- bignum.ShiftLeft(100);
- // "FFFF0 0000 0000 0000 0000 0000 0000"
- bignum.MultiplyByUInt64(0xFFFF);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("FFFE00010000000000000000000000000", buffer);
-
- bignum.AssignUInt16(0xFFFF);
- bignum.ShiftLeft(100);
- // "FFFF0 0000 0000 0000 0000 0000 0000"
- bignum.MultiplyByUInt64(0xFFFFFFFF);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("FFFEFFFF00010000000000000000000000000", buffer);
-
- bignum.AssignUInt16(0xFFFF);
- bignum.ShiftLeft(100);
- // "FFFF0 0000 0000 0000 0000 0000 0000"
- bignum.MultiplyByUInt64(V8_2PART_UINT64_C(0xFFFFFFFF, FFFFFFFF));
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("FFFEFFFFFFFFFFFF00010000000000000000000000000", buffer);
-
- AssignDecimalString(&bignum, "15611230384529777");
- bignum.MultiplyByUInt64(V8_2PART_UINT64_C(0x8ac72304, 89e80000));
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("1E10EE4B11D15A7F3DE7F3C7680000", buffer);
-}
-
-
-TEST(MultiplyPowerOfTen) {
- char buffer[kBufferSize];
- Bignum bignum;
-
- AssignDecimalString(&bignum, "1234");
- bignum.MultiplyByPowerOfTen(1);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("3034", buffer);
-
- AssignDecimalString(&bignum, "1234");
- bignum.MultiplyByPowerOfTen(2);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("1E208", buffer);
-
- AssignDecimalString(&bignum, "1234");
- bignum.MultiplyByPowerOfTen(3);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("12D450", buffer);
-
- AssignDecimalString(&bignum, "1234");
- bignum.MultiplyByPowerOfTen(4);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("BC4B20", buffer);
-
- AssignDecimalString(&bignum, "1234");
- bignum.MultiplyByPowerOfTen(5);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("75AEF40", buffer);
-
- AssignDecimalString(&bignum, "1234");
- bignum.MultiplyByPowerOfTen(6);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("498D5880", buffer);
-
- AssignDecimalString(&bignum, "1234");
- bignum.MultiplyByPowerOfTen(7);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("2DF857500", buffer);
-
- AssignDecimalString(&bignum, "1234");
- bignum.MultiplyByPowerOfTen(8);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("1CBB369200", buffer);
-
- AssignDecimalString(&bignum, "1234");
- bignum.MultiplyByPowerOfTen(9);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("11F5021B400", buffer);
-
- AssignDecimalString(&bignum, "1234");
- bignum.MultiplyByPowerOfTen(10);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("B3921510800", buffer);
-
- AssignDecimalString(&bignum, "1234");
- bignum.MultiplyByPowerOfTen(11);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("703B4D2A5000", buffer);
-
- AssignDecimalString(&bignum, "1234");
- bignum.MultiplyByPowerOfTen(12);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("4625103A72000", buffer);
-
- AssignDecimalString(&bignum, "1234");
- bignum.MultiplyByPowerOfTen(13);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("2BD72A24874000", buffer);
-
- AssignDecimalString(&bignum, "1234");
- bignum.MultiplyByPowerOfTen(14);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("1B667A56D488000", buffer);
-
- AssignDecimalString(&bignum, "1234");
- bignum.MultiplyByPowerOfTen(15);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("11200C7644D50000", buffer);
-
- AssignDecimalString(&bignum, "1234");
- bignum.MultiplyByPowerOfTen(16);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("AB407C9EB0520000", buffer);
-
- AssignDecimalString(&bignum, "1234");
- bignum.MultiplyByPowerOfTen(17);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("6B084DE32E3340000", buffer);
-
- AssignDecimalString(&bignum, "1234");
- bignum.MultiplyByPowerOfTen(18);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("42E530ADFCE0080000", buffer);
-
- AssignDecimalString(&bignum, "1234");
- bignum.MultiplyByPowerOfTen(19);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("29CF3E6CBE0C0500000", buffer);
-
- AssignDecimalString(&bignum, "1234");
- bignum.MultiplyByPowerOfTen(20);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("1A218703F6C783200000", buffer);
-
- AssignDecimalString(&bignum, "1234");
- bignum.MultiplyByPowerOfTen(21);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("1054F4627A3CB1F400000", buffer);
-
- AssignDecimalString(&bignum, "1234");
- bignum.MultiplyByPowerOfTen(22);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("A3518BD8C65EF38800000", buffer);
-
- AssignDecimalString(&bignum, "1234");
- bignum.MultiplyByPowerOfTen(23);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("6612F7677BFB5835000000", buffer);
-
- AssignDecimalString(&bignum, "1234");
- bignum.MultiplyByPowerOfTen(24);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("3FCBDAA0AD7D17212000000", buffer);
-
- AssignDecimalString(&bignum, "1234");
- bignum.MultiplyByPowerOfTen(25);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("27DF68A46C6E2E74B4000000", buffer);
-
- AssignDecimalString(&bignum, "1234");
- bignum.MultiplyByPowerOfTen(26);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("18EBA166C3C4DD08F08000000", buffer);
-
- AssignDecimalString(&bignum, "1234");
- bignum.MultiplyByPowerOfTen(27);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("F9344E03A5B0A259650000000", buffer);
-
- AssignDecimalString(&bignum, "1234");
- bignum.MultiplyByPowerOfTen(28);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("9BC0B0C2478E6577DF20000000", buffer);
-
- AssignDecimalString(&bignum, "1234");
- bignum.MultiplyByPowerOfTen(29);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("61586E796CB8FF6AEB740000000", buffer);
-
- AssignDecimalString(&bignum, "1234");
- bignum.MultiplyByPowerOfTen(30);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("3CD7450BE3F39FA2D32880000000", buffer);
-
- AssignDecimalString(&bignum, "1234");
- bignum.MultiplyByPowerOfTen(31);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("26068B276E7843C5C3F9500000000", buffer);
-
- AssignDecimalString(&bignum, "1234");
- bignum.MultiplyByPowerOfTen(50);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("149D1B4CFED03B23AB5F4E1196EF45C08000000000000", buffer);
-
- AssignDecimalString(&bignum, "1234");
- bignum.MultiplyByPowerOfTen(100);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("5827249F27165024FBC47DFCA9359BF316332D1B91ACEECF471FBAB06D9B2"
- "0000000000000000000000000", buffer);
-
- AssignDecimalString(&bignum, "1234");
- bignum.MultiplyByPowerOfTen(200);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("64C1F5C06C3816AFBF8DAFD5A3D756365BB0FD020E6F084E759C1F7C99E4F"
- "55B9ACC667CEC477EB958C2AEEB3C6C19BA35A1AD30B35C51EB72040920000"
- "0000000000000000000000000000000000000000000000", buffer);
-
- AssignDecimalString(&bignum, "1234");
- bignum.MultiplyByPowerOfTen(500);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("96741A625EB5D7C91039FEB5C5ACD6D9831EDA5B083D800E6019442C8C8223"
- "3EAFB3501FE2058062221E15121334928880827DEE1EC337A8B26489F3A40A"
- "CB440A2423734472D10BFCE886F41B3AF9F9503013D86D088929CA86EEB4D8"
- "B9C831D0BD53327B994A0326227CFD0ECBF2EB48B02387AAE2D4CCCDF1F1A1"
- "B8CC4F1FA2C56AD40D0E4DAA9C28CDBF0A549098EA13200000000000000000"
- "00000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000", buffer);
-
- AssignDecimalString(&bignum, "1234");
- bignum.MultiplyByPowerOfTen(1000);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("1258040F99B1CD1CC9819C676D413EA50E4A6A8F114BB0C65418C62D399B81"
- "6361466CA8E095193E1EE97173553597C96673AF67FAFE27A66E7EF2E5EF2E"
- "E3F5F5070CC17FE83BA53D40A66A666A02F9E00B0E11328D2224B8694C7372"
- "F3D536A0AD1985911BD361496F268E8B23112500EAF9B88A9BC67B2AB04D38"
- "7FEFACD00F5AF4F764F9ABC3ABCDE54612DE38CD90CB6647CA389EA0E86B16"
- "BF7A1F34086E05ADBE00BD1673BE00FAC4B34AF1091E8AD50BA675E0381440"
- "EA8E9D93E75D816BAB37C9844B1441C38FC65CF30ABB71B36433AF26DD97BD"
- "ABBA96C03B4919B8F3515B92826B85462833380DC193D79F69D20DD6038C99"
- "6114EF6C446F0BA28CC772ACBA58B81C04F8FFDE7B18C4E5A3ABC51E637FDF"
- "6E37FDFF04C940919390F4FF92000000000000000000000000000000000000"
- "00000000000000000000000000000000000000000000000000000000000000"
- "00000000000000000000000000000000000000000000000000000000000000"
- "00000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000", buffer);
-
- Bignum bignum2;
- AssignHexString(&bignum2, "3DA774C07FB5DF54284D09C675A492165B830D5DAAEB2A7501"
- "DA17CF9DFA1CA2282269F92A25A97314296B717E3DCBB9FE17"
- "41A842FE2913F540F40796F2381155763502C58B15AF7A7F88"
- "6F744C9164FF409A28F7FA0C41F89ED79C1BE9F322C8578B97"
- "841F1CBAA17D901BE1230E3C00E1C643AF32638B5674E01FEA"
- "96FC90864E621B856A9E1CE56E6EB545B9C2F8F0CC10DDA88D"
- "CC6D282605F8DB67044F2DFD3695E7BA63877AE16701536AE6"
- "567C794D0BFE338DFBB42D92D4215AF3BB22BF0A8B283FDDC2"
- "C667A10958EA6D2");
- CHECK(bignum2.ToHexString(buffer, kBufferSize));
- CHECK_EQ("3DA774C07FB5DF54284D09C675A492165B830D5DAAEB2A7501"
- "DA17CF9DFA1CA2282269F92A25A97314296B717E3DCBB9FE17"
- "41A842FE2913F540F40796F2381155763502C58B15AF7A7F88"
- "6F744C9164FF409A28F7FA0C41F89ED79C1BE9F322C8578B97"
- "841F1CBAA17D901BE1230E3C00E1C643AF32638B5674E01FEA"
- "96FC90864E621B856A9E1CE56E6EB545B9C2F8F0CC10DDA88D"
- "CC6D282605F8DB67044F2DFD3695E7BA63877AE16701536AE6"
- "567C794D0BFE338DFBB42D92D4215AF3BB22BF0A8B283FDDC2"
- "C667A10958EA6D2", buffer);
-
- bignum.AssignBignum(bignum2);
- bignum.MultiplyByPowerOfTen(1);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("2688A8F84FD1AB949930261C0986DB4DF931E85A8AD2FA8921284EE1C2BC51"
- "E55915823BBA5789E7EC99E326EEE69F543ECE890929DED9AC79489884BE57"
- "630AD569E121BB76ED8DAC8FB545A8AFDADF1F8860599AFC47A93B6346C191"
- "7237F5BD36B73EB29371F4A4EE7A116CB5E8E5808D1BEA4D7F7E3716090C13"
- "F29E5DDA53F0FD513362A2D20F6505314B9419DB967F8A8A89589FC43917C3"
- "BB892062B17CBE421DB0D47E34ACCCE060D422CFF60DCBD0277EE038BD509C"
- "7BC494D8D854F5B76696F927EA99BC00C4A5D7928434", buffer);
-
- bignum.AssignBignum(bignum2);
- bignum.MultiplyByPowerOfTen(2);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("1815699B31E30B3CDFBE17D185F44910BBBF313896C3DC95B4B9314D19B5B32"
- "F57AD71655476B630F3E02DF855502394A74115A5BA2B480BCBCD5F52F6F69D"
- "E6C5622CB5152A54788BD9D14B896DE8CB73B53C3800DDACC9C51E0C38FAE76"
- "2F9964232872F9C2738E7150C4AE3F1B18F70583172706FAEE26DC5A78C77A2"
- "FAA874769E52C01DA5C3499F233ECF3C90293E0FB69695D763DAA3AEDA5535B"
- "43DAEEDF6E9528E84CEE0EC000C3C8495C1F9C89F6218AF4C23765261CD5ADD"
- "0787351992A01E5BB8F2A015807AE7A6BB92A08", buffer);
-
- bignum.AssignBignum(bignum2);
- bignum.MultiplyByPowerOfTen(5);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("5E13A4863ADEE3E5C9FE8D0A73423D695D62D8450CED15A8C9F368952C6DC3"
- "F0EE7D82F3D1EFB7AF38A3B3920D410AFCAD563C8F5F39116E141A3C5C14B3"
- "58CD73077EA35AAD59F6E24AD98F10D5555ABBFBF33AC361EAF429FD5FBE94"
- "17DA9EF2F2956011F9F93646AA38048A681D984ED88127073443247CCC167C"
- "B354A32206EF5A733E73CF82D795A1AD598493211A6D613C39515E0E0F6304"
- "DCD9C810F3518C7F6A7CB6C81E99E02FCC65E8FDB7B7AE97306CC16A8631CE"
- "0A2AEF6568276BE4C176964A73C153FDE018E34CB4C2F40", buffer);
-
- bignum.AssignBignum(bignum2);
- bignum.MultiplyByPowerOfTen(10);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("8F8CB8EB51945A7E815809F6121EF2F4E61EF3405CD9432CAD2709749EEAFD"
- "1B81E843F14A3667A7BDCCC9E0BB795F63CDFDB62844AC7438976C885A0116"
- "29607DA54F9C023CC366570B7637ED0F855D931752038A614922D0923E382C"
- "B8E5F6C975672DB76E0DE471937BB9EDB11E28874F1C122D5E1EF38CECE9D0"
- "0723056BCBD4F964192B76830634B1D322B7EB0062F3267E84F5C824343A77"
- "4B7DCEE6DD464F01EBDC8C671BB18BB4EF4300A42474A6C77243F2A12B03BF"
- "0443C38A1C0D2701EDB393135AE0DEC94211F9D4EB51F990800", buffer);
-
- bignum.AssignBignum(bignum2);
- bignum.MultiplyByPowerOfTen(50);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("107A8BE345E24407372FC1DE442CBA696BC23C4FFD5B4BDFD9E5C39559815"
- "86628CF8472D2D589F2FC2BAD6E0816EC72CBF85CCA663D8A1EC6C51076D8"
- "2D247E6C26811B7EC4D4300FB1F91028DCB7B2C4E7A60C151161AA7E65E79"
- "B40917B12B2B5FBE7745984D4E8EFA31F9AE6062427B068B144A9CB155873"
- "E7C0C9F0115E5AC72DC5A73C4796DB970BF9205AB8C77A6996EB1B417F9D1"
- "6232431E6313C392203601B9C22CC10DDA88DCC6D282605F8DB67044F2DFD"
- "3695E7BA63877AE16701536AE6567C794D0BFE338DFBB42D924CF964BD2C0"
- "F586E03A2FCD35A408000000000000", buffer);
-
- bignum.AssignBignum(bignum2);
- bignum.MultiplyByPowerOfTen(100);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("46784A90ACD0ED3E7759CC585FB32D36EB6034A6F78D92604E3BAA5ED3D8B"
- "6E60E854439BE448897FB4B7EA5A3D873AA0FCB3CFFD80D0530880E45F511"
- "722A50CE7E058B5A6F5464DB7500E34984EE3202A9441F44FA1554C0CEA96"
- "B438A36F25E7C9D56D71AE2CD313EC37534DA299AC0854FC48591A7CF3171"
- "31265AA4AE62DE32344CE7BEEEF894AE686A2DAAFE5D6D9A10971FFD9C064"
- "5079B209E1048F58B5192D41D84336AC4C8C489EEF00939CFC9D55C122036"
- "01B9C22CC10DDA88DCC6D282605F8DB67044F2DFD3695E7BA3F67B96D3A32"
- "E11FB5561B68744C4035B0800DC166D49D98E3FD1D5BB2000000000000000"
- "0000000000", buffer);
-
- bignum.AssignBignum(bignum2);
- bignum.MultiplyByPowerOfTen(200);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("508BD351221DF139D72D88CDC0416845A53EE2D0E6B98352509A9AC312F8C"
- "6CB1A144889416201E0B6CE66EA3EBE259B5FD79ECFC1FD77963CE516CC7E"
- "2FE73D4B5B710C19F6BCB092C7A2FD76286543B8DBD2C596DFF2C896720BA"
- "DFF7BC9C366ACEA3A880AEC287C5E6207DF2739B5326FC19D773BD830B109"
- "ED36C7086544BF8FDB9D4B73719C2B5BC2F571A5937EC46876CD428281F6B"
- "F287E1E07F25C1B1D46BC37324FF657A8B2E0071DB83B86123CA34004F406"
- "001082D7945E90C6E8C9A9FEC2B44BE0DDA46E9F52B152E4D1336D2FCFBC9"
- "96E30CA0082256737365158FE36482AA7EB9DAF2AB128F10E7551A3CD5BE6"
- "0A922F3A7D5EED38B634A7EC95BCF7021BA6820A292000000000000000000"
- "00000000000000000000000000000000", buffer);
-
- bignum.AssignBignum(bignum2);
- bignum.MultiplyByPowerOfTen(500);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("7845F900E475B5086885BAAAE67C8E85185ACFE4633727F82A4B06B5582AC"
- "BE933C53357DA0C98C20C5AC900C4D76A97247DF52B79F48F9E35840FB715"
- "D392CE303E22622B0CF82D9471B398457DD3196F639CEE8BBD2C146873841"
- "F0699E6C41F04FC7A54B48CEB995BEB6F50FE81DE9D87A8D7F849CC523553"
- "7B7BBBC1C7CAAFF6E9650BE03B308C6D31012AEF9580F70D3EE2083ADE126"
- "8940FA7D6308E239775DFD2F8C97FF7EBD525DAFA6512216F7047A62A93DC"
- "38A0165BDC67E250DCC96A0181DE935A70B38704DC71819F02FC5261FF7E1"
- "E5F11907678B0A3E519FF4C10A867B0C26CE02BE6960BA8621A87303C101C"
- "3F88798BB9F7739655946F8B5744E6B1EAF10B0C5621330F0079209033C69"
- "20DE2E2C8D324F0624463735D482BF291926C22A910F5B80FA25170B6B57D"
- "8D5928C7BCA3FE87461275F69BD5A1B83181DAAF43E05FC3C72C4E93111B6"
- "6205EBF49B28FEDFB7E7526CBDA658A332000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000", buffer);
-}
-
-
-TEST(DivideModuloIntBignum) {
- char buffer[kBufferSize];
- Bignum bignum;
- Bignum other;
- Bignum third;
-
- bignum.AssignUInt16(10);
- other.AssignUInt16(2);
- CHECK_EQ(5, bignum.DivideModuloIntBignum(other));
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("0", buffer);
-
- bignum.AssignUInt16(10);
- bignum.ShiftLeft(500);
- other.AssignUInt16(2);
- other.ShiftLeft(500);
- CHECK_EQ(5, bignum.DivideModuloIntBignum(other));
- CHECK_EQ("0", buffer);
-
- bignum.AssignUInt16(11);
- other.AssignUInt16(2);
- CHECK_EQ(5, bignum.DivideModuloIntBignum(other));
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("1", buffer);
-
- bignum.AssignUInt16(10);
- bignum.ShiftLeft(500);
- other.AssignUInt16(1);
- bignum.AddBignum(other);
- other.AssignUInt16(2);
- other.ShiftLeft(500);
- CHECK_EQ(5, bignum.DivideModuloIntBignum(other));
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("1", buffer);
-
- bignum.AssignUInt16(10);
- bignum.ShiftLeft(500);
- other.AssignBignum(bignum);
- bignum.MultiplyByUInt32(0x1234);
- third.AssignUInt16(0xFFF);
- bignum.AddBignum(third);
- CHECK_EQ(0x1234, bignum.DivideModuloIntBignum(other));
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("FFF", buffer);
-
- bignum.AssignUInt16(10);
- AssignHexString(&other, "1234567890");
- CHECK_EQ(0, bignum.DivideModuloIntBignum(other));
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("A", buffer);
-
- AssignHexString(&bignum, "12345678");
- AssignHexString(&other, "3789012");
- CHECK_EQ(5, bignum.DivideModuloIntBignum(other));
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("D9861E", buffer);
-
- AssignHexString(&bignum, "70000001");
- AssignHexString(&other, "1FFFFFFF");
- CHECK_EQ(3, bignum.DivideModuloIntBignum(other));
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("10000004", buffer);
-
- AssignHexString(&bignum, "28000000");
- AssignHexString(&other, "12A05F20");
- CHECK_EQ(2, bignum.DivideModuloIntBignum(other));
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("2BF41C0", buffer);
-
- bignum.AssignUInt16(10);
- bignum.ShiftLeft(500);
- other.AssignBignum(bignum);
- bignum.MultiplyByUInt32(0x1234);
- third.AssignUInt16(0xFFF);
- other.SubtractBignum(third);
- CHECK_EQ(0x1234, bignum.DivideModuloIntBignum(other));
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("1232DCC", buffer);
- CHECK_EQ(0, bignum.DivideModuloIntBignum(other));
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("1232DCC", buffer);
-}
-
-
-TEST(Compare) {
- Bignum bignum1;
- Bignum bignum2;
- bignum1.AssignUInt16(1);
- bignum2.AssignUInt16(1);
- CHECK_EQ(0, Bignum::Compare(bignum1, bignum2));
- CHECK(Bignum::Equal(bignum1, bignum2));
- CHECK(Bignum::LessEqual(bignum1, bignum2));
- CHECK(!Bignum::Less(bignum1, bignum2));
-
- bignum1.AssignUInt16(0);
- bignum2.AssignUInt16(1);
- CHECK_EQ(-1, Bignum::Compare(bignum1, bignum2));
- CHECK_EQ(+1, Bignum::Compare(bignum2, bignum1));
- CHECK(!Bignum::Equal(bignum1, bignum2));
- CHECK(!Bignum::Equal(bignum2, bignum1));
- CHECK(Bignum::LessEqual(bignum1, bignum2));
- CHECK(!Bignum::LessEqual(bignum2, bignum1));
- CHECK(Bignum::Less(bignum1, bignum2));
- CHECK(!Bignum::Less(bignum2, bignum1));
-
- AssignHexString(&bignum1, "1234567890ABCDEF12345");
- AssignHexString(&bignum2, "1234567890ABCDEF12345");
- CHECK_EQ(0, Bignum::Compare(bignum1, bignum2));
-
- AssignHexString(&bignum1, "1234567890ABCDEF12345");
- AssignHexString(&bignum2, "1234567890ABCDEF12346");
- CHECK_EQ(-1, Bignum::Compare(bignum1, bignum2));
- CHECK_EQ(+1, Bignum::Compare(bignum2, bignum1));
-
- AssignHexString(&bignum1, "1234567890ABCDEF12345");
- bignum1.ShiftLeft(500);
- AssignHexString(&bignum2, "1234567890ABCDEF12345");
- bignum2.ShiftLeft(500);
- CHECK_EQ(0, Bignum::Compare(bignum1, bignum2));
-
- AssignHexString(&bignum1, "1234567890ABCDEF12345");
- bignum1.ShiftLeft(500);
- AssignHexString(&bignum2, "1234567890ABCDEF12346");
- bignum2.ShiftLeft(500);
- CHECK_EQ(-1, Bignum::Compare(bignum1, bignum2));
- CHECK_EQ(+1, Bignum::Compare(bignum2, bignum1));
-
- bignum1.AssignUInt16(1);
- bignum1.ShiftLeft(64);
- AssignHexString(&bignum2, "10000000000000000");
- CHECK_EQ(0, Bignum::Compare(bignum1, bignum2));
- CHECK_EQ(0, Bignum::Compare(bignum2, bignum1));
-
- bignum1.AssignUInt16(1);
- bignum1.ShiftLeft(64);
- AssignHexString(&bignum2, "10000000000000001");
- CHECK_EQ(-1, Bignum::Compare(bignum1, bignum2));
- CHECK_EQ(+1, Bignum::Compare(bignum2, bignum1));
-
- bignum1.AssignUInt16(1);
- bignum1.ShiftLeft(96);
- AssignHexString(&bignum2, "10000000000000001");
- bignum2.ShiftLeft(32);
- CHECK_EQ(-1, Bignum::Compare(bignum1, bignum2));
- CHECK_EQ(+1, Bignum::Compare(bignum2, bignum1));
-
- AssignHexString(&bignum1, "FFFFFFFFFFFFFFFF");
- bignum2.AssignUInt16(1);
- bignum2.ShiftLeft(64);
- CHECK_EQ(-1, Bignum::Compare(bignum1, bignum2));
- CHECK_EQ(+1, Bignum::Compare(bignum2, bignum1));
-
- AssignHexString(&bignum1, "FFFFFFFFFFFFFFFF");
- bignum1.ShiftLeft(32);
- bignum2.AssignUInt16(1);
- bignum2.ShiftLeft(96);
- CHECK_EQ(-1, Bignum::Compare(bignum1, bignum2));
- CHECK_EQ(+1, Bignum::Compare(bignum2, bignum1));
-
- AssignHexString(&bignum1, "FFFFFFFFFFFFFFFF");
- bignum1.ShiftLeft(32);
- bignum2.AssignUInt16(1);
- bignum2.ShiftLeft(95);
- CHECK_EQ(+1, Bignum::Compare(bignum1, bignum2));
- CHECK_EQ(-1, Bignum::Compare(bignum2, bignum1));
-
- AssignHexString(&bignum1, "FFFFFFFFFFFFFFFF");
- bignum1.ShiftLeft(32);
- bignum2.AssignUInt16(1);
- bignum2.ShiftLeft(100);
- CHECK_EQ(-1, Bignum::Compare(bignum1, bignum2));
- CHECK_EQ(+1, Bignum::Compare(bignum2, bignum1));
-
- AssignHexString(&bignum1, "100000000000000");
- bignum2.AssignUInt16(1);
- bignum2.ShiftLeft(14*4);
- CHECK_EQ(0, Bignum::Compare(bignum1, bignum2));
- CHECK_EQ(0, Bignum::Compare(bignum2, bignum1));
-
- AssignHexString(&bignum1, "100000000000001");
- bignum2.AssignUInt16(1);
- bignum2.ShiftLeft(14*4);
- CHECK_EQ(+1, Bignum::Compare(bignum1, bignum2));
- CHECK_EQ(-1, Bignum::Compare(bignum2, bignum1));
-
- AssignHexString(&bignum1, "200000000000000");
- bignum2.AssignUInt16(3);
- bignum2.ShiftLeft(14*4);
- CHECK_EQ(-1, Bignum::Compare(bignum1, bignum2));
- CHECK_EQ(+1, Bignum::Compare(bignum2, bignum1));
-}
-
-
-TEST(PlusCompare) {
- Bignum a;
- Bignum b;
- Bignum c;
- a.AssignUInt16(1);
- b.AssignUInt16(0);
- c.AssignUInt16(1);
- CHECK_EQ(0, Bignum::PlusCompare(a, b, c));
- CHECK(Bignum::PlusEqual(a, b, c));
- CHECK(Bignum::PlusLessEqual(a, b, c));
- CHECK(!Bignum::PlusLess(a, b, c));
-
- a.AssignUInt16(0);
- b.AssignUInt16(0);
- c.AssignUInt16(1);
- CHECK_EQ(-1, Bignum::PlusCompare(a, b, c));
- CHECK_EQ(+1, Bignum::PlusCompare(c, b, a));
- CHECK(!Bignum::PlusEqual(a, b, c));
- CHECK(!Bignum::PlusEqual(c, b, a));
- CHECK(Bignum::PlusLessEqual(a, b, c));
- CHECK(!Bignum::PlusLessEqual(c, b, a));
- CHECK(Bignum::PlusLess(a, b, c));
- CHECK(!Bignum::PlusLess(c, b, a));
-
- AssignHexString(&a, "1234567890ABCDEF12345");
- b.AssignUInt16(1);
- AssignHexString(&c, "1234567890ABCDEF12345");
- CHECK_EQ(+1, Bignum::PlusCompare(a, b, c));
-
- AssignHexString(&a, "1234567890ABCDEF12344");
- b.AssignUInt16(1);
- AssignHexString(&c, "1234567890ABCDEF12345");
- CHECK_EQ(0, Bignum::PlusCompare(a, b, c));
-
- AssignHexString(&a, "1234567890");
- a.ShiftLeft(11*4);
- AssignHexString(&b, "ABCDEF12345");
- AssignHexString(&c, "1234567890ABCDEF12345");
- CHECK_EQ(0, Bignum::PlusCompare(a, b, c));
-
- AssignHexString(&a, "1234567890");
- a.ShiftLeft(11*4);
- AssignHexString(&b, "ABCDEF12344");
- AssignHexString(&c, "1234567890ABCDEF12345");
- CHECK_EQ(-1, Bignum::PlusCompare(a, b, c));
-
- AssignHexString(&a, "1234567890");
- a.ShiftLeft(11*4);
- AssignHexString(&b, "ABCDEF12346");
- AssignHexString(&c, "1234567890ABCDEF12345");
- CHECK_EQ(1, Bignum::PlusCompare(a, b, c));
-
- AssignHexString(&a, "1234567891");
- a.ShiftLeft(11*4);
- AssignHexString(&b, "ABCDEF12345");
- AssignHexString(&c, "1234567890ABCDEF12345");
- CHECK_EQ(1, Bignum::PlusCompare(a, b, c));
-
- AssignHexString(&a, "1234567889");
- a.ShiftLeft(11*4);
- AssignHexString(&b, "ABCDEF12345");
- AssignHexString(&c, "1234567890ABCDEF12345");
- CHECK_EQ(-1, Bignum::PlusCompare(a, b, c));
-
- AssignHexString(&a, "1234567890");
- a.ShiftLeft(11*4 + 32);
- AssignHexString(&b, "ABCDEF12345");
- b.ShiftLeft(32);
- AssignHexString(&c, "1234567890ABCDEF12345");
- c.ShiftLeft(32);
- CHECK_EQ(0, Bignum::PlusCompare(a, b, c));
-
- AssignHexString(&a, "1234567890");
- a.ShiftLeft(11*4 + 32);
- AssignHexString(&b, "ABCDEF12344");
- b.ShiftLeft(32);
- AssignHexString(&c, "1234567890ABCDEF12345");
- c.ShiftLeft(32);
- CHECK_EQ(-1, Bignum::PlusCompare(a, b, c));
-
- AssignHexString(&a, "1234567890");
- a.ShiftLeft(11*4 + 32);
- AssignHexString(&b, "ABCDEF12346");
- b.ShiftLeft(32);
- AssignHexString(&c, "1234567890ABCDEF12345");
- c.ShiftLeft(32);
- CHECK_EQ(1, Bignum::PlusCompare(a, b, c));
-
- AssignHexString(&a, "1234567891");
- a.ShiftLeft(11*4 + 32);
- AssignHexString(&b, "ABCDEF12345");
- b.ShiftLeft(32);
- AssignHexString(&c, "1234567890ABCDEF12345");
- c.ShiftLeft(32);
- CHECK_EQ(1, Bignum::PlusCompare(a, b, c));
-
- AssignHexString(&a, "1234567889");
- a.ShiftLeft(11*4 + 32);
- AssignHexString(&b, "ABCDEF12345");
- b.ShiftLeft(32);
- AssignHexString(&c, "1234567890ABCDEF12345");
- c.ShiftLeft(32);
- CHECK_EQ(-1, Bignum::PlusCompare(a, b, c));
-
- AssignHexString(&a, "1234567890");
- a.ShiftLeft(11*4 + 32);
- AssignHexString(&b, "ABCDEF12345");
- b.ShiftLeft(32);
- AssignHexString(&c, "1234567890ABCDEF1234500000000");
- CHECK_EQ(0, Bignum::PlusCompare(a, b, c));
-
- AssignHexString(&a, "1234567890");
- a.ShiftLeft(11*4 + 32);
- AssignHexString(&b, "ABCDEF12344");
- b.ShiftLeft(32);
- AssignHexString(&c, "1234567890ABCDEF1234500000000");
- CHECK_EQ(-1, Bignum::PlusCompare(a, b, c));
-
- AssignHexString(&a, "1234567890");
- a.ShiftLeft(11*4 + 32);
- AssignHexString(&b, "ABCDEF12346");
- b.ShiftLeft(32);
- AssignHexString(&c, "1234567890ABCDEF1234500000000");
- CHECK_EQ(1, Bignum::PlusCompare(a, b, c));
-
- AssignHexString(&a, "1234567891");
- a.ShiftLeft(11*4 + 32);
- AssignHexString(&b, "ABCDEF12345");
- b.ShiftLeft(32);
- AssignHexString(&c, "1234567890ABCDEF1234500000000");
- CHECK_EQ(1, Bignum::PlusCompare(a, b, c));
-
- AssignHexString(&a, "1234567889");
- a.ShiftLeft(11*4 + 32);
- AssignHexString(&b, "ABCDEF12345");
- b.ShiftLeft(32);
- AssignHexString(&c, "1234567890ABCDEF1234500000000");
- CHECK_EQ(-1, Bignum::PlusCompare(a, b, c));
-
- AssignHexString(&a, "1234567890");
- a.ShiftLeft(11*4 + 32);
- AssignHexString(&b, "ABCDEF12345");
- AssignHexString(&c, "123456789000000000ABCDEF12345");
- CHECK_EQ(0, Bignum::PlusCompare(a, b, c));
-
- AssignHexString(&a, "1234567890");
- a.ShiftLeft(11*4 + 32);
- AssignHexString(&b, "ABCDEF12346");
- AssignHexString(&c, "123456789000000000ABCDEF12345");
- CHECK_EQ(1, Bignum::PlusCompare(a, b, c));
-
- AssignHexString(&a, "1234567890");
- a.ShiftLeft(11*4 + 32);
- AssignHexString(&b, "ABCDEF12344");
- AssignHexString(&c, "123456789000000000ABCDEF12345");
- CHECK_EQ(-1, Bignum::PlusCompare(a, b, c));
-
- AssignHexString(&a, "1234567890");
- a.ShiftLeft(11*4 + 32);
- AssignHexString(&b, "ABCDEF12345");
- b.ShiftLeft(16);
- AssignHexString(&c, "12345678900000ABCDEF123450000");
- CHECK_EQ(0, Bignum::PlusCompare(a, b, c));
-
- AssignHexString(&a, "1234567890");
- a.ShiftLeft(11*4 + 32);
- AssignHexString(&b, "ABCDEF12344");
- b.ShiftLeft(16);
- AssignHexString(&c, "12345678900000ABCDEF123450000");
- CHECK_EQ(-1, Bignum::PlusCompare(a, b, c));
-
- AssignHexString(&a, "1234567890");
- a.ShiftLeft(11*4 + 32);
- AssignHexString(&b, "ABCDEF12345");
- b.ShiftLeft(16);
- AssignHexString(&c, "12345678900000ABCDEF123450001");
- CHECK_EQ(-1, Bignum::PlusCompare(a, b, c));
-
- AssignHexString(&a, "1234567890");
- a.ShiftLeft(11*4 + 32);
- AssignHexString(&b, "ABCDEF12346");
- b.ShiftLeft(16);
- AssignHexString(&c, "12345678900000ABCDEF123450000");
- CHECK_EQ(+1, Bignum::PlusCompare(a, b, c));
-}
-
-
-TEST(Square) {
- Bignum bignum;
- char buffer[kBufferSize];
-
- bignum.AssignUInt16(1);
- bignum.Square();
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("1", buffer);
-
- bignum.AssignUInt16(2);
- bignum.Square();
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("4", buffer);
-
- bignum.AssignUInt16(10);
- bignum.Square();
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("64", buffer);
-
- AssignHexString(&bignum, "FFFFFFF");
- bignum.Square();
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("FFFFFFE0000001", buffer);
-
- AssignHexString(&bignum, "FFFFFFFFFFFFFF");
- bignum.Square();
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("FFFFFFFFFFFFFE00000000000001", buffer);
-}
-
-
-TEST(AssignPowerUInt16) {
- Bignum bignum;
- char buffer[kBufferSize];
-
- bignum.AssignPowerUInt16(1, 0);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("1", buffer);
-
- bignum.AssignPowerUInt16(1, 1);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("1", buffer);
-
- bignum.AssignPowerUInt16(1, 2);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("1", buffer);
-
- bignum.AssignPowerUInt16(2, 0);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("1", buffer);
-
- bignum.AssignPowerUInt16(2, 1);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("2", buffer);
-
- bignum.AssignPowerUInt16(2, 2);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("4", buffer);
-
- bignum.AssignPowerUInt16(16, 1);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("10", buffer);
-
- bignum.AssignPowerUInt16(16, 2);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("100", buffer);
-
- bignum.AssignPowerUInt16(16, 5);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("100000", buffer);
-
- bignum.AssignPowerUInt16(16, 8);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("100000000", buffer);
-
- bignum.AssignPowerUInt16(16, 16);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("10000000000000000", buffer);
-
- bignum.AssignPowerUInt16(16, 30);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("1000000000000000000000000000000", buffer);
-
- bignum.AssignPowerUInt16(10, 0);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("1", buffer);
-
- bignum.AssignPowerUInt16(10, 1);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("A", buffer);
-
- bignum.AssignPowerUInt16(10, 2);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("64", buffer);
-
- bignum.AssignPowerUInt16(10, 5);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("186A0", buffer);
-
- bignum.AssignPowerUInt16(10, 8);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("5F5E100", buffer);
-
- bignum.AssignPowerUInt16(10, 16);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("2386F26FC10000", buffer);
-
- bignum.AssignPowerUInt16(10, 30);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("C9F2C9CD04674EDEA40000000", buffer);
-
- bignum.AssignPowerUInt16(10, 31);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("7E37BE2022C0914B2680000000", buffer);
-
- bignum.AssignPowerUInt16(2, 0);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("1", buffer);
-
- bignum.AssignPowerUInt16(2, 100);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("10000000000000000000000000", buffer);
-
- bignum.AssignPowerUInt16(17, 0);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("1", buffer);
-
- bignum.AssignPowerUInt16(17, 99);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("1942BB9853FAD924A3D4DD92B89B940E0207BEF05DB9C26BC1B757"
- "80BE0C5A2C2990E02A681224F34ED68558CE4C6E33760931",
- buffer);
-
- bignum.AssignPowerUInt16(0xFFFF, 99);
- CHECK(bignum.ToHexString(buffer, kBufferSize));
- CHECK_EQ("FF9D12F09B886C54E77E7439C7D2DED2D34F669654C0C2B6B8C288250"
- "5A2211D0E3DC9A61831349EAE674B11D56E3049D7BD79DAAD6C9FA2BA"
- "528E3A794299F2EE9146A324DAFE3E88967A0358233B543E233E575B9"
- "DD4E3AA7942146426C328FF55BFD5C45E0901B1629260AF9AE2F310C5"
- "50959FAF305C30116D537D80CF6EBDBC15C5694062AF1AC3D956D0A41"
- "B7E1B79FF11E21D83387A1CE1F5882B31E4B5D8DE415BDBE6854466DF"
- "343362267A7E8833119D31D02E18DB5B0E8F6A64B0ED0D0062FFFF",
- buffer);
-}
diff --git a/deps/v8/test/cctest/test-debug.cc b/deps/v8/test/cctest/test-debug.cc
index 748e3e8d91e..d59e2f5ad11 100644
--- a/deps/v8/test/cctest/test-debug.cc
+++ b/deps/v8/test/cctest/test-debug.cc
@@ -902,7 +902,6 @@ static void DebugEventBreak(v8::DebugEvent event,
// Debug event handler which re-issues a debug break until a limit has been
// reached.
int max_break_point_hit_count = 0;
-bool terminate_after_max_break_point_hit = false;
static void DebugEventBreakMax(v8::DebugEvent event,
v8::Handle<v8::Object> exec_state,
v8::Handle<v8::Object> event_data,
@@ -910,17 +909,12 @@ static void DebugEventBreakMax(v8::DebugEvent event,
// When hitting a debug event listener there must be a break set.
CHECK_NE(v8::internal::Debug::break_id(), 0);
- if (event == v8::Break) {
- if (break_point_hit_count < max_break_point_hit_count) {
- // Count the number of breaks.
- break_point_hit_count++;
+ if (event == v8::Break && break_point_hit_count < max_break_point_hit_count) {
+ // Count the number of breaks.
+ break_point_hit_count++;
- // Set the break flag again to come back here as soon as possible.
- v8::Debug::DebugBreak();
- } else if (terminate_after_max_break_point_hit) {
- // Terminate execution after the last break if requested.
- v8::V8::TerminateExecution();
- }
+ // Set the break flag again to come back here as soon as possible.
+ v8::Debug::DebugBreak();
}
}
@@ -6898,33 +6892,4 @@ TEST(DebugEventBreakData) {
CheckDebuggerUnloaded();
}
-
-// Test that setting the terminate execution flag during debug break processing.
-TEST(DebugBreakLoop) {
- v8::HandleScope scope;
- DebugLocalContext env;
-
- // Receive 100 breaks and terminate.
- max_break_point_hit_count = 100;
- terminate_after_max_break_point_hit = true;
-
- // Register a debug event listener which sets the break flag and counts.
- v8::Debug::SetDebugEventListener(DebugEventBreakMax);
-
- // Function with infinite loop.
- CompileRun("function f() { while (true) { } }");
-
- // Set the debug break to enter the debugger as soon as possible.
- v8::Debug::DebugBreak();
-
- // Call function with infinite loop.
- CompileRun("f();");
- CHECK_EQ(100, break_point_hit_count);
-
- // Get rid of the debug event listener.
- v8::Debug::SetDebugEventListener(NULL);
- CheckDebuggerUnloaded();
-}
-
-
#endif // ENABLE_DEBUGGER_SUPPORT
diff --git a/deps/v8/test/cctest/test-double.cc b/deps/v8/test/cctest/test-double.cc
index 3594a4fe32a..a7a604ea433 100644
--- a/deps/v8/test/cctest/test-double.cc
+++ b/deps/v8/test/cctest/test-double.cc
@@ -202,19 +202,3 @@ TEST(NormalizedBoundaries) {
CHECK(diy_fp.f() - boundary_minus.f() == boundary_plus.f() - diy_fp.f());
CHECK((1 << 10) == diy_fp.f() - boundary_minus.f()); // NOLINT
}
-
-
-TEST(NextDouble) {
- CHECK_EQ(4e-324, Double(0.0).NextDouble());
- CHECK_EQ(0.0, Double(-0.0).NextDouble());
- CHECK_EQ(-0.0, Double(-4e-324).NextDouble());
- Double d0(-4e-324);
- Double d1(d0.NextDouble());
- Double d2(d1.NextDouble());
- CHECK_EQ(-0.0, d1.value());
- CHECK_EQ(0.0, d2.value());
- CHECK_EQ(4e-324, d2.NextDouble());
- CHECK_EQ(-1.7976931348623157e308, Double(-V8_INFINITY).NextDouble());
- CHECK_EQ(V8_INFINITY,
- Double(V8_2PART_UINT64_C(0x7fefffff, ffffffff)).NextDouble());
-}
diff --git a/deps/v8/test/cctest/test-heap-profiler.cc b/deps/v8/test/cctest/test-heap-profiler.cc
index b165190b0a9..b86a3361605 100644
--- a/deps/v8/test/cctest/test-heap-profiler.cc
+++ b/deps/v8/test/cctest/test-heap-profiler.cc
@@ -388,10 +388,14 @@ namespace {
class NamedEntriesDetector {
public:
NamedEntriesDetector()
- : has_A2(false), has_B2(false), has_C2(false) {
+ : has_A1(false), has_B1(false), has_C1(false),
+ has_A2(false), has_B2(false), has_C2(false) {
}
void Apply(i::HeapEntry** entry_ptr) {
+ if (IsReachableNodeWithName(*entry_ptr, "A1")) has_A1 = true;
+ if (IsReachableNodeWithName(*entry_ptr, "B1")) has_B1 = true;
+ if (IsReachableNodeWithName(*entry_ptr, "C1")) has_C1 = true;
if (IsReachableNodeWithName(*entry_ptr, "A2")) has_A2 = true;
if (IsReachableNodeWithName(*entry_ptr, "B2")) has_B2 = true;
if (IsReachableNodeWithName(*entry_ptr, "C2")) has_C2 = true;
@@ -401,6 +405,9 @@ class NamedEntriesDetector {
return strcmp(name, entry->name()) == 0 && entry->painted_reachable();
}
+ bool has_A1;
+ bool has_B1;
+ bool has_C1;
bool has_A2;
bool has_B2;
bool has_C2;
@@ -457,7 +464,21 @@ static bool HasString(const v8::HeapGraphNode* node, const char* contents) {
TEST(HeapSnapshot) {
v8::HandleScope scope;
+ v8::Handle<v8::String> token1 = v8::String::New("token1");
+ LocalContext env1;
+ env1->SetSecurityToken(token1);
+
+ CompileRun(
+ "function A1() {}\n"
+ "function B1(x) { this.x = x; }\n"
+ "function C1(x) { this.x1 = x; this.x2 = x; }\n"
+ "var a1 = new A1();\n"
+ "var b1_1 = new B1(a1), b1_2 = new B1(a1);\n"
+ "var c1 = new C1(a1);");
+
+ v8::Handle<v8::String> token2 = v8::String::New("token2");
LocalContext env2;
+ env2->SetSecurityToken(token2);
CompileRun(
"function A2() {}\n"
@@ -477,7 +498,14 @@ TEST(HeapSnapshot) {
const_cast<i::HeapEntry*>(
reinterpret_cast<const i::HeapEntry*>(global_env2))->PaintAllReachable();
- // Verify, that JS global object of env2 has '..2' properties.
+ // Verify, that JS global object of env2 doesn't have '..1'
+ // properties, but has '..2' properties.
+ CHECK_EQ(NULL, GetProperty(global_env2, v8::HeapGraphEdge::kProperty, "a1"));
+ CHECK_EQ(
+ NULL, GetProperty(global_env2, v8::HeapGraphEdge::kProperty, "b1_1"));
+ CHECK_EQ(
+ NULL, GetProperty(global_env2, v8::HeapGraphEdge::kProperty, "b1_2"));
+ CHECK_EQ(NULL, GetProperty(global_env2, v8::HeapGraphEdge::kProperty, "c1"));
const v8::HeapGraphNode* a2_node =
GetProperty(global_env2, v8::HeapGraphEdge::kProperty, "a2");
CHECK_NE(NULL, a2_node);
@@ -490,6 +518,9 @@ TEST(HeapSnapshot) {
// Verify that anything related to '[ABC]1' is not reachable.
NamedEntriesDetector det;
i_snapshot_env2->IterateEntries(&det);
+ CHECK(!det.has_A1);
+ CHECK(!det.has_B1);
+ CHECK(!det.has_C1);
CHECK(det.has_A2);
CHECK(det.has_B2);
CHECK(det.has_C2);
diff --git a/deps/v8/test/cctest/test-mark-compact.cc b/deps/v8/test/cctest/test-mark-compact.cc
index 994256712f0..ea5afecc1e3 100644
--- a/deps/v8/test/cctest/test-mark-compact.cc
+++ b/deps/v8/test/cctest/test-mark-compact.cc
@@ -75,7 +75,7 @@ TEST(Promotion) {
// from new space.
FLAG_gc_global = true;
FLAG_always_compact = true;
- Heap::ConfigureHeap(2*256*KB, 4*MB, 4*MB);
+ Heap::ConfigureHeap(2*256*KB, 4*MB);
InitializeVM();
@@ -101,7 +101,7 @@ TEST(Promotion) {
TEST(NoPromotion) {
- Heap::ConfigureHeap(2*256*KB, 4*MB, 4*MB);
+ Heap::ConfigureHeap(2*256*KB, 4*MB);
// Test the situation that some objects in new space are promoted to
// the old space
diff --git a/deps/v8/test/cctest/test-parsing.cc b/deps/v8/test/cctest/test-parsing.cc
index 7ae8dcfa386..02503f225ca 100755
--- a/deps/v8/test/cctest/test-parsing.cc
+++ b/deps/v8/test/cctest/test-parsing.cc
@@ -26,7 +26,6 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <stdlib.h>
-#include <stdio.h>
#include "v8.h"
@@ -35,8 +34,7 @@
#include "parser.h"
#include "utils.h"
#include "execution.h"
-#include "scanner.h"
-#include "preparser.h"
+
#include "cctest.h"
namespace i = ::v8::internal;
@@ -241,32 +239,3 @@ TEST(Preparsing) {
i::Vector<const char*> args = pre_impl->BuildArgs();
CHECK_GT(strlen(message), 0);
}
-
-
-TEST(StandAlonePreParser) {
- int marker;
- i::StackGuard::SetStackLimit(
- reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
-
- const char* programs[] = {
- "{label: 42}",
- "var x = 42;",
- "function foo(x, y) { return x + y; }",
- "native function foo(); return %ArgleBargle(glop);",
- "var x = new new Function('this.x = 42');",
- NULL
- };
-
- for (int i = 0; programs[i]; i++) {
- const char* program = programs[i];
- unibrow::Utf8InputBuffer<256> stream(program, strlen(program));
- i::CompleteParserRecorder log;
- i::Scanner scanner;
- scanner.Initialize(i::Handle<i::String>::null(), &stream, i::JAVASCRIPT);
- v8::preparser::PreParser<i::Scanner, i::CompleteParserRecorder> preparser;
- bool result = preparser.PreParseProgram(&scanner, &log, true);
- CHECK(result);
- i::ScriptDataImpl data(log.ExtractData());
- CHECK(!data.has_error());
- }
-}
diff --git a/deps/v8/test/cctest/test-spaces.cc b/deps/v8/test/cctest/test-spaces.cc
index b399a4ef182..06f1bfaca29 100644
--- a/deps/v8/test/cctest/test-spaces.cc
+++ b/deps/v8/test/cctest/test-spaces.cc
@@ -91,7 +91,7 @@ TEST(Page) {
TEST(MemoryAllocator) {
CHECK(Heap::ConfigureHeapDefault());
- CHECK(MemoryAllocator::Setup(Heap::MaxReserved(), Heap::MaxExecutableSize()));
+ CHECK(MemoryAllocator::Setup(Heap::MaxReserved()));
OldSpace faked_space(Heap::MaxReserved(), OLD_POINTER_SPACE, NOT_EXECUTABLE);
int total_pages = 0;
@@ -147,7 +147,7 @@ TEST(MemoryAllocator) {
TEST(NewSpace) {
CHECK(Heap::ConfigureHeapDefault());
- CHECK(MemoryAllocator::Setup(Heap::MaxReserved(), Heap::MaxExecutableSize()));
+ CHECK(MemoryAllocator::Setup(Heap::MaxReserved()));
NewSpace new_space;
@@ -172,7 +172,7 @@ TEST(NewSpace) {
TEST(OldSpace) {
CHECK(Heap::ConfigureHeapDefault());
- CHECK(MemoryAllocator::Setup(Heap::MaxReserved(), Heap::MaxExecutableSize()));
+ CHECK(MemoryAllocator::Setup(Heap::MaxReserved()));
OldSpace* s = new OldSpace(Heap::MaxOldGenerationSize(),
OLD_POINTER_SPACE,
diff --git a/deps/v8/test/cctest/test-strtod.cc b/deps/v8/test/cctest/test-strtod.cc
index d71d126b48d..56b26ea1eb9 100644
--- a/deps/v8/test/cctest/test-strtod.cc
+++ b/deps/v8/test/cctest/test-strtod.cc
@@ -4,10 +4,7 @@
#include "v8.h"
-#include "bignum.h"
#include "cctest.h"
-#include "diy-fp.h"
-#include "double.h"
#include "strtod.h"
using namespace v8::internal;
@@ -205,14 +202,11 @@ TEST(Strtod) {
CHECK_EQ(1.7976931348623158E+308, StrtodChar("17976931348623158", 292));
CHECK_EQ(V8_INFINITY, StrtodChar("17976931348623159", 292));
- // The following number is the result of 89255.0/1e22. Both floating-point
+ // The following number is the result of 89255.0/1e-22. Both floating-point
// numbers can be accurately represented with doubles. However on Linux,x86
// the floating-point stack is set to 80bits and the double-rounding
// introduces an error.
CHECK_EQ(89255e-22, StrtodChar("89255", -22));
-
- // Some random values.
- CHECK_EQ(358416272e-33, StrtodChar("358416272", -33));
CHECK_EQ(104110013277974872254e-225,
StrtodChar("104110013277974872254", -225));
@@ -258,160 +252,4 @@ TEST(Strtod) {
StrtodChar("1234567890123456789052345", 114));
CHECK_EQ(1234567890123456789052345e115,
StrtodChar("1234567890123456789052345", 115));
-
- // Boundary cases. Boundaries themselves should round to even.
- //
- // 0x1FFFFFFFFFFFF * 2^3 = 72057594037927928
- // next: 72057594037927936
- // boundary: 72057594037927932 should round up.
- CHECK_EQ(72057594037927928.0, StrtodChar("72057594037927928", 0));
- CHECK_EQ(72057594037927936.0, StrtodChar("72057594037927936", 0));
- CHECK_EQ(72057594037927936.0, StrtodChar("72057594037927932", 0));
- CHECK_EQ(72057594037927928.0, StrtodChar("7205759403792793199999", -5));
- CHECK_EQ(72057594037927936.0, StrtodChar("7205759403792793200001", -5));
-
- // 0x1FFFFFFFFFFFF * 2^10 = 9223372036854774784
- // next: 9223372036854775808
- // boundary: 9223372036854775296 should round up.
- CHECK_EQ(9223372036854774784.0, StrtodChar("9223372036854774784", 0));
- CHECK_EQ(9223372036854775808.0, StrtodChar("9223372036854775808", 0));
- CHECK_EQ(9223372036854775808.0, StrtodChar("9223372036854775296", 0));
- CHECK_EQ(9223372036854774784.0, StrtodChar("922337203685477529599999", -5));
- CHECK_EQ(9223372036854775808.0, StrtodChar("922337203685477529600001", -5));
-
- // 0x1FFFFFFFFFFFF * 2^50 = 10141204801825834086073718800384
- // next: 10141204801825835211973625643008
- // boundary: 10141204801825834649023672221696 should round up.
- CHECK_EQ(10141204801825834086073718800384.0,
- StrtodChar("10141204801825834086073718800384", 0));
- CHECK_EQ(10141204801825835211973625643008.0,
- StrtodChar("10141204801825835211973625643008", 0));
- CHECK_EQ(10141204801825835211973625643008.0,
- StrtodChar("10141204801825834649023672221696", 0));
- CHECK_EQ(10141204801825834086073718800384.0,
- StrtodChar("1014120480182583464902367222169599999", -5));
- CHECK_EQ(10141204801825835211973625643008.0,
- StrtodChar("1014120480182583464902367222169600001", -5));
-
- // 0x1FFFFFFFFFFFF * 2^99 = 5708990770823838890407843763683279797179383808
- // next: 5708990770823839524233143877797980545530986496
- // boundary: 5708990770823839207320493820740630171355185152
- // The boundary should round up.
- CHECK_EQ(5708990770823838890407843763683279797179383808.0,
- StrtodChar("5708990770823838890407843763683279797179383808", 0));
- CHECK_EQ(5708990770823839524233143877797980545530986496.0,
- StrtodChar("5708990770823839524233143877797980545530986496", 0));
- CHECK_EQ(5708990770823839524233143877797980545530986496.0,
- StrtodChar("5708990770823839207320493820740630171355185152", 0));
- CHECK_EQ(5708990770823838890407843763683279797179383808.0,
- StrtodChar("5708990770823839207320493820740630171355185151999", -3));
- CHECK_EQ(5708990770823839524233143877797980545530986496.0,
- StrtodChar("5708990770823839207320493820740630171355185152001", -3));
-}
-
-
-static int CompareBignumToDiyFp(const Bignum& bignum_digits,
- int bignum_exponent,
- DiyFp diy_fp) {
- Bignum bignum;
- bignum.AssignBignum(bignum_digits);
- Bignum other;
- other.AssignUInt64(diy_fp.f());
- if (bignum_exponent >= 0) {
- bignum.MultiplyByPowerOfTen(bignum_exponent);
- } else {
- other.MultiplyByPowerOfTen(-bignum_exponent);
- }
- if (diy_fp.e() >= 0) {
- other.ShiftLeft(diy_fp.e());
- } else {
- bignum.ShiftLeft(-diy_fp.e());
- }
- return Bignum::Compare(bignum, other);
-}
-
-
-static bool CheckDouble(Vector<const char> buffer,
- int exponent,
- double to_check) {
- DiyFp lower_boundary;
- DiyFp upper_boundary;
- Bignum input_digits;
- input_digits.AssignDecimalString(buffer);
- if (to_check == 0.0) {
- const double kMinDouble = 4e-324;
- // Check that the buffer*10^exponent < (0 + kMinDouble)/2.
- Double d(kMinDouble);
- d.NormalizedBoundaries(&lower_boundary, &upper_boundary);
- return CompareBignumToDiyFp(input_digits, exponent, lower_boundary) <= 0;
- }
- if (to_check == V8_INFINITY) {
- const double kMaxDouble = 1.7976931348623157e308;
- // Check that the buffer*10^exponent >= boundary between kMaxDouble and inf.
- Double d(kMaxDouble);
- d.NormalizedBoundaries(&lower_boundary, &upper_boundary);
- return CompareBignumToDiyFp(input_digits, exponent, upper_boundary) >= 0;
- }
- Double d(to_check);
- d.NormalizedBoundaries(&lower_boundary, &upper_boundary);
- if ((d.Significand() & 1) == 0) {
- return CompareBignumToDiyFp(input_digits, exponent, lower_boundary) >= 0 &&
- CompareBignumToDiyFp(input_digits, exponent, upper_boundary) <= 0;
- } else {
- return CompareBignumToDiyFp(input_digits, exponent, lower_boundary) > 0 &&
- CompareBignumToDiyFp(input_digits, exponent, upper_boundary) < 0;
- }
-}
-
-
-// Copied from v8.cc and adapted to make the function deterministic.
-static uint32_t DeterministicRandom() {
- // Random number generator using George Marsaglia's MWC algorithm.
- static uint32_t hi = 0;
- static uint32_t lo = 0;
-
- // Initialization values don't have any special meaning. (They are the result
- // of two calls to random().)
- if (hi == 0) hi = 0xbfe166e7;
- if (lo == 0) lo = 0x64d1c3c9;
-
- // Mix the bits.
- hi = 36969 * (hi & 0xFFFF) + (hi >> 16);
- lo = 18273 * (lo & 0xFFFF) + (lo >> 16);
- return (hi << 16) + (lo & 0xFFFF);
-}
-
-
-static const int kBufferSize = 1024;
-static const int kShortStrtodRandomCount = 2;
-static const int kLargeStrtodRandomCount = 2;
-
-TEST(RandomStrtod) {
- char buffer[kBufferSize];
- for (int length = 1; length < 15; length++) {
- for (int i = 0; i < kShortStrtodRandomCount; ++i) {
- int pos = 0;
- for (int j = 0; j < length; ++j) {
- buffer[pos++] = random() % 10 + '0';
- }
- int exponent = DeterministicRandom() % (25*2 + 1) - 25 - length;
- buffer[pos] = '\0';
- Vector<const char> vector(buffer, pos);
- double strtod_result = Strtod(vector, exponent);
- CHECK(CheckDouble(vector, exponent, strtod_result));
- }
- }
- for (int length = 15; length < 800; length += 2) {
- for (int i = 0; i < kLargeStrtodRandomCount; ++i) {
- int pos = 0;
- for (int j = 0; j < length; ++j) {
- buffer[pos++] = random() % 10 + '0';
- }
- int exponent = DeterministicRandom() % (308*2 + 1) - 308 - length;
- buffer[pos] = '\0';
- Vector<const char> vector(buffer, pos);
- double strtod_result = Strtod(vector, exponent);
- CHECK(CheckDouble(vector, exponent, strtod_result));
- }
- }
}
diff --git a/deps/v8/test/mjsunit/regress/regress-927.js b/deps/v8/test/mjsunit/regress/regress-927.js
deleted file mode 100644
index c671f7d480c..00000000000
--- a/deps/v8/test/mjsunit/regress/regress-927.js
+++ /dev/null
@@ -1,33 +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.
-
-function a1() {
- var a2 = -1756315459;
- return ((((a2 & a2) ^ 1) * a2) << -10);
-}
-
-assertEquals(a1(), -2147483648);
diff --git a/deps/v8/test/mjsunit/regress/regress-conditional-position.js b/deps/v8/test/mjsunit/regress/regress-conditional-position.js
deleted file mode 100644
index cd8f7bd7457..00000000000
--- a/deps/v8/test/mjsunit/regress/regress-conditional-position.js
+++ /dev/null
@@ -1,95 +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.
-
-// Flags: --always-full-compiler
-
-var functionToCatch;
-var lineNumber;
-
-function catchLineNumber () {
- var x = {};
-
- Error.prepareStackTrace = function (error, stackTrace) {
- stackTrace.some(function (frame) {
- if (frame.getFunction() == functionToCatch) {
- lineNumber = frame.getLineNumber();
- return true;
- }
- return false;
- });
- return lineNumber;
- };
-
- Error.captureStackTrace(x);
- return x.stack;
-}
-
-function log() {
- catchLineNumber();
-}
-
-function foo() {}
-
-function test1() {
- log(foo() == foo()
- ? 'a'
- : 'b');
-}
-
-function test2() {
- var o = { foo: function () {}}
- log(o.foo() == o.foo()
- ? 'a'
- : 'b');
-}
-
-function test3() {
- var o = { log: log, foo: function() { } };
- o.log(o.foo() == o.foo()
- ? 'a'
- : 'b');
-
-}
-
-function test(f, expectedLineNumber) {
- functionToCatch = f;
- f();
-
- assertEquals(expectedLineNumber, lineNumber);
-}
-
-test(test1, 58);
-test(test2, 65);
-test(test3, 72);
-
-eval(test1.toString() + "//@ sourceUrl=foo");
-eval(test2.toString() + "//@ sourceUrl=foo");
-eval(test3.toString() + "//@ sourceUrl=foo");
-
-test(test1, 2);
-test(test2, 3);
-test(test3, 3);
diff --git a/deps/v8/test/mjsunit/string-split.js b/deps/v8/test/mjsunit/string-split.js
index c741f6a3e59..59d3ad3ee38 100644
--- a/deps/v8/test/mjsunit/string-split.js
+++ b/deps/v8/test/mjsunit/string-split.js
@@ -27,45 +27,76 @@
expected = ["A", undefined, "B", "bold", "/", "B", "and", undefined, "CODE", "coded", "/", "CODE", ""];
result = "A<B>bold</B>and<CODE>coded</CODE>".split(/<(\/)?([^<>]+)>/);
-assertArrayEquals(expected, result);
+assertArrayEquals(expected, result, 1);
+expected = ["a", "b"];
+result = "ab".split(/a*?/);
+assertArrayEquals(expected, result, 2);
-assertArrayEquals(["a", "b"], "ab".split(/a*?/));
+expected = ["", "b"];
+result = "ab".split(/a*/);
+assertArrayEquals(expected, result, 3);
-assertArrayEquals(["", "b"], "ab".split(/a*/));
+expected = ["a"];
+result = "ab".split(/a*?/, 1);
+assertArrayEquals(expected, result, 4);
-assertArrayEquals(["a"], "ab".split(/a*?/, 1));
+expected = [""];
+result = "ab".split(/a*/, 1);
+assertArrayEquals(expected, result, 5);
-assertArrayEquals([""], "ab".split(/a*/, 1));
+expected = ["as","fas","fas","f"];
+result = "asdfasdfasdf".split("d");
+assertArrayEquals(expected, result, 6);
-assertArrayEquals(["as","fas","fas","f"], "asdfasdfasdf".split("d"));
+expected = ["as","fas","fas","f"];
+result = "asdfasdfasdf".split("d", -1);
+assertArrayEquals(expected, result, 7);
-assertArrayEquals(["as","fas","fas","f"], "asdfasdfasdf".split("d", -1));
+expected = ["as", "fas"];
+result = "asdfasdfasdf".split("d", 2);
+assertArrayEquals(expected, result, 8);
-assertArrayEquals(["as", "fas"], "asdfasdfasdf".split("d", 2));
+expected = [];
+result = "asdfasdfasdf".split("d", 0);
+assertArrayEquals(expected, result, 9);
-assertArrayEquals([], "asdfasdfasdf".split("d", 0));
+expected = ["as","fas","fas",""];
+result = "asdfasdfasd".split("d");
+assertArrayEquals(expected, result, 10);
-assertArrayEquals(["as","fas","fas",""], "asdfasdfasd".split("d"));
+expected = [];
+result = "".split("");
+assertArrayEquals(expected, result, 11);
-assertArrayEquals([], "".split(""));
+expected = [""]
+result = "".split("a");
+assertArrayEquals(expected, result, 12);
-assertArrayEquals([""], "".split("a"));
+expected = ["a","b"]
+result = "axxb".split(/x*/);
+assertArrayEquals(expected, result, 13);
-assertArrayEquals(["a","b"], "axxb".split(/x*/));
+expected = ["a","b"]
+result = "axxb".split(/x+/);
+assertArrayEquals(expected, result, 14);
-assertArrayEquals(["a","b"], "axxb".split(/x+/));
-
-assertArrayEquals(["a","","b"], "axxb".split(/x/));
+expected = ["a","","b"]
+result = "axxb".split(/x/);
+assertArrayEquals(expected, result, 15);
// This was http://b/issue?id=1151354
-assertArrayEquals(["div", "#id", ".class"], "div#id.class".split(/(?=[#.])/));
-
+expected = ["div", "#id", ".class"]
+result = "div#id.class".split(/(?=[#.])/);
+assertArrayEquals(expected, result, 16);
-assertArrayEquals(["div", "#i", "d", ".class"], "div#id.class".split(/(?=[d#.])/));
-
-assertArrayEquals(["a", "b", "c"], "abc".split(/(?=.)/));
+expected = ["div", "#i", "d", ".class"]
+result = "div#id.class".split(/(?=[d#.])/);
+assertArrayEquals(expected, result, 17);
+expected = ["a", "b", "c"]
+result = "abc".split(/(?=.)/);
+assertArrayEquals(expected, result, 18);
/* "ab".split(/((?=.))/)
*
@@ -77,23 +108,19 @@ assertArrayEquals(["a", "b", "c"], "abc".split(/(?=.)/));
*
* Opera seems to have this right. The others make no sense.
*/
-assertArrayEquals(["a", "", "b"], "ab".split(/((?=.))/));
+expected = ["a", "", "b"]
+result = "ab".split(/((?=.))/);
+assertArrayEquals(expected, result, 19);
/* "ab".split(/(?=)/)
*
* KJS: a,b
* SM: ab
* IE: a,b
- * Opera: a,bb
+ * Opera: a,b
* V8: a,b
*/
-assertArrayEquals(["a", "b"], "ab".split(/(?=)/));
-
+expected = ["a", "b"]
+result = "ab".split(/(?=)/);
+assertArrayEquals(expected, result, 20);
-// For issue http://code.google.com/p/v8/issues/detail?id=924
-// Splitting the empty string is a special case.
-assertEquals([""], ''.split());
-assertEquals([""], ''.split(/./));
-assertEquals([], ''.split(/.?/));
-assertEquals([], ''.split(/.??/));
-assertEquals([], ''.split(/()()/));
diff --git a/deps/v8/tools/gyp/v8.gyp b/deps/v8/tools/gyp/v8.gyp
index 65b86203222..17d556f1cf7 100644
--- a/deps/v8/tools/gyp/v8.gyp
+++ b/deps/v8/tools/gyp/v8.gyp
@@ -280,8 +280,6 @@
'../../src/ast.cc',
'../../src/ast-inl.h',
'../../src/ast.h',
- '../../src/bignum.cc',
- '../../src/bignum.h',
'../../src/bootstrapper.cc',
'../../src/bootstrapper.h',
'../../src/builtins.cc',
@@ -428,8 +426,6 @@
'../../src/rewriter.h',
'../../src/runtime.cc',
'../../src/runtime.h',
- '../../src/scanner-base.cc',
- '../../src/scanner-base.h',
'../../src/scanner.cc',
'../../src/scanner.h',
'../../src/scopeinfo.cc',
diff --git a/deps/v8/tools/presubmit.py b/deps/v8/tools/presubmit.py
index ebf8bd89396..e69c9a85ac8 100755
--- a/deps/v8/tools/presubmit.py
+++ b/deps/v8/tools/presubmit.py
@@ -195,7 +195,7 @@ class CppLintProcessor(SourceFileProcessor):
or (name in CppLintProcessor.IGNORE_LINT))
def GetPathsToSearch(self):
- return ['src', 'include', 'samples', join('test', 'cctest')]
+ return ['src', 'public', 'samples', join('test', 'cctest')]
def ProcessFiles(self, files, path):
good_files_cache = FileContentsCache('.cpplint-cache')
diff --git a/deps/v8/tools/v8.xcodeproj/project.pbxproj b/deps/v8/tools/v8.xcodeproj/project.pbxproj
index 5f93c78a8e3..08558cc5b0e 100644
--- a/deps/v8/tools/v8.xcodeproj/project.pbxproj
+++ b/deps/v8/tools/v8.xcodeproj/project.pbxproj
@@ -115,7 +115,6 @@
89A88E180E71A6960043BA31 /* property.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF16D0E719B8F00D62E90 /* property.cc */; };
89A88E190E71A6970043BA31 /* rewriter.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF16F0E719B8F00D62E90 /* rewriter.cc */; };
89A88E1A0E71A69B0043BA31 /* runtime.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1710E719B8F00D62E90 /* runtime.cc */; };
- 89A88E1B0E71A69D0043BA31 /* scanner-base.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1730E719B8F00D62E90 /* scanner-base.cc */; };
89A88E1B0E71A69D0043BA31 /* scanner.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1730E719B8F00D62E90 /* scanner.cc */; };
89A88E1C0E71A69E0043BA31 /* scopeinfo.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1760E719B8F00D62E90 /* scopeinfo.cc */; };
89A88E1D0E71A6A00043BA31 /* scopes.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1780E719B8F00D62E90 /* scopes.cc */; };
@@ -178,7 +177,6 @@
89F23C6C0E78D5B2006B2466 /* property.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF16D0E719B8F00D62E90 /* property.cc */; };
89F23C6D0E78D5B2006B2466 /* rewriter.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF16F0E719B8F00D62E90 /* rewriter.cc */; };
89F23C6E0E78D5B2006B2466 /* runtime.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1710E719B8F00D62E90 /* runtime.cc */; };
- 89F23C6F0E78D5B2006B2466 /* scanner-base.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1730E719B8F00D62E90 /* scanner-base.cc */; };
89F23C6F0E78D5B2006B2466 /* scanner.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1730E719B8F00D62E90 /* scanner.cc */; };
89F23C700E78D5B2006B2466 /* scopeinfo.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1760E719B8F00D62E90 /* scopeinfo.cc */; };
89F23C710E78D5B2006B2466 /* scopes.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1780E719B8F00D62E90 /* scopes.cc */; };
@@ -483,8 +481,6 @@
897FF1700E719B8F00D62E90 /* rewriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rewriter.h; sourceTree = "<group>"; };
897FF1710E719B8F00D62E90 /* runtime.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = runtime.cc; sourceTree = "<group>"; };
897FF1720E719B8F00D62E90 /* runtime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = runtime.h; sourceTree = "<group>"; };
- 897FF1730E719B8F00D62E90 /* scanner-base.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = scanner-base.cc; sourceTree = "<group>"; };
- 897FF1740E719B8F00D62E90 /* scanner-base.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scanner-base.h; sourceTree = "<group>"; };
897FF1730E719B8F00D62E90 /* scanner.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = scanner.cc; sourceTree = "<group>"; };
897FF1740E719B8F00D62E90 /* scanner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scanner.h; sourceTree = "<group>"; };
897FF1750E719B8F00D62E90 /* SConscript */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = SConscript; sourceTree = "<group>"; };
@@ -947,8 +943,6 @@
897FF1700E719B8F00D62E90 /* rewriter.h */,
897FF1710E719B8F00D62E90 /* runtime.cc */,
897FF1720E719B8F00D62E90 /* runtime.h */,
- 897FF1730E719B8F00D62E90 /* scanner-base.cc */,
- 897FF1740E719B8F00D62E90 /* scanner-base.h */,
897FF1730E719B8F00D62E90 /* scanner.cc */,
897FF1740E719B8F00D62E90 /* scanner.h */,
897FF1760E719B8F00D62E90 /* scopeinfo.cc */,
@@ -1354,7 +1348,6 @@
58950D630F5551AF00F3E8BA /* register-allocator.cc in Sources */,
89A88E190E71A6970043BA31 /* rewriter.cc in Sources */,
89A88E1A0E71A69B0043BA31 /* runtime.cc in Sources */,
- 89A88E1B0E71A69D0043BA31 /* scanner-base.cc in Sources */,
89A88E1B0E71A69D0043BA31 /* scanner.cc in Sources */,
89A88E1C0E71A69E0043BA31 /* scopeinfo.cc in Sources */,
89A88E1D0E71A6A00043BA31 /* scopes.cc in Sources */,
@@ -1479,7 +1472,6 @@
58950D640F5551B500F3E8BA /* register-allocator.cc in Sources */,
89F23C6D0E78D5B2006B2466 /* rewriter.cc in Sources */,
89F23C6E0E78D5B2006B2466 /* runtime.cc in Sources */,
- 89F23C6F0E78D5B2006B2466 /* scanner-base.cc in Sources */,
89F23C6F0E78D5B2006B2466 /* scanner.cc in Sources */,
89F23C700E78D5B2006B2466 /* scopeinfo.cc in Sources */,
89F23C710E78D5B2006B2466 /* scopes.cc in Sources */,
diff --git a/deps/v8/tools/visual_studio/v8_base.vcproj b/deps/v8/tools/visual_studio/v8_base.vcproj
index d1ee48d6da7..62d450152f8 100644
--- a/deps/v8/tools/visual_studio/v8_base.vcproj
+++ b/deps/v8/tools/visual_studio/v8_base.vcproj
@@ -145,22 +145,6 @@
</FileConfiguration>
</File>
<File
- RelativePath="..\..\src\bignum.cc"
- >
- </File>
- <File
- RelativePath="..\..\src\bignum.h"
- >
- </File>
- <File
- RelativePath="..\..\src\bignum-dtoa.cc"
- >
- </File>
- <File
- RelativePath="..\..\src\bignum-dtoa.h"
- >
- </File>
- <File
RelativePath="..\..\src\dtoa.cc"
>
</File>
@@ -257,22 +241,6 @@
>
</File>
<File
- RelativePath="..\..\src\bignum.cc"
- >
- </File>
- <File
- RelativePath="..\..\src\bignum.h"
- >
- </File>
- <File
- RelativePath="..\..\src\bignum-dtoa.cc"
- >
- </File>
- <File
- RelativePath="..\..\src\bignum-dtoa.h"
- >
- </File>
- <File
RelativePath="..\..\src\bootstrapper.cc"
>
</File>
@@ -914,14 +882,6 @@
>
</File>
<File
- RelativePath="..\..\src\scanner-base.cc"
- >
- </File>
- <File
- RelativePath="..\..\src\scanner-base.h"
- >
- </File>
- <File
RelativePath="..\..\src\scanner.cc"
>
</File>