summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2011-05-12 15:51:54 +0100
committerSteve Block <steveblock@google.com>2011-05-12 16:12:25 +0100
commit9fac840a46e8b7e26894f4792ba26dde14c56b04 (patch)
tree0b8b71befb5175abac552daa0d084fc51c1090b8
parentb0fe1620dcb4135ac3ab2d66ff93072373911299 (diff)
downloadandroid_external_v8-9fac840a46e8b7e26894f4792ba26dde14c56b04.tar.gz
android_external_v8-9fac840a46e8b7e26894f4792ba26dde14c56b04.tar.bz2
android_external_v8-9fac840a46e8b7e26894f4792ba26dde14c56b04.zip
Update V8 to r6190 as required by WebKit r75315
Change-Id: I0b2f598e4d8748df417ad350fc47a1c465ad1fef
-rw-r--r--ChangeLog25
-rw-r--r--V8_MERGE_REVISION6
-rw-r--r--include/v8.h26
-rwxr-xr-xsrc/SConscript5
-rw-r--r--src/arm/assembler-arm.h5
-rw-r--r--src/arm/code-stubs-arm.cc44
-rw-r--r--src/arm/code-stubs-arm.h43
-rw-r--r--src/arm/codegen-arm.cc10
-rw-r--r--src/arm/full-codegen-arm.cc2
-rw-r--r--src/arm/lithium-arm.cc68
-rw-r--r--src/arm/lithium-arm.h88
-rw-r--r--src/arm/lithium-codegen-arm.cc325
-rw-r--r--src/arm/lithium-codegen-arm.h2
-rw-r--r--src/ast.cc3
-rw-r--r--src/ast.h6
-rw-r--r--src/builtins.cc62
-rw-r--r--src/cpu-profiler.cc3
-rw-r--r--src/d8-debug.cc19
-rw-r--r--src/d8-debug.h6
-rw-r--r--src/d8.cc3
-rw-r--r--src/data-flow.h7
-rw-r--r--src/date.js2
-rw-r--r--src/debug-agent.h6
-rw-r--r--src/debug.cc3
-rw-r--r--src/deoptimizer.cc6
-rw-r--r--src/deoptimizer.h6
-rw-r--r--src/factory.cc8
-rw-r--r--src/factory.h2
-rw-r--r--src/flag-definitions.h1
-rw-r--r--src/globals.h13
-rw-r--r--src/heap-inl.h82
-rw-r--r--src/heap.cc65
-rw-r--r--src/heap.h16
-rw-r--r--src/hydrogen-instructions.h85
-rw-r--r--src/hydrogen.cc150
-rw-r--r--src/hydrogen.h109
-rw-r--r--src/ia32/builtins-ia32.cc8
-rw-r--r--src/ia32/code-stubs-ia32.cc10
-rw-r--r--src/ia32/debug-ia32.cc2
-rw-r--r--src/ia32/full-codegen-ia32.cc2
-rw-r--r--src/ia32/ic-ia32.cc15
-rw-r--r--src/ia32/lithium-codegen-ia32.cc73
-rw-r--r--src/ia32/lithium-ia32.cc49
-rw-r--r--src/ia32/lithium-ia32.h44
-rw-r--r--src/ia32/regexp-macro-assembler-ia32.cc6
-rw-r--r--src/ia32/stub-cache-ia32.cc1
-rw-r--r--src/json.js15
-rw-r--r--src/lithium-allocator.cc44
-rw-r--r--src/lithium-allocator.h41
-rw-r--r--src/liveedit-debugger.js4
-rw-r--r--src/log.cc3
-rw-r--r--src/macros.py1
-rw-r--r--src/mirror-debugger.js2
-rw-r--r--src/objects-debug.cc847
-rw-r--r--src/objects-printer.cc778
-rw-r--r--src/objects-visiting.h4
-rw-r--r--src/objects.cc157
-rw-r--r--src/objects.h51
-rw-r--r--src/parser.cc95
-rw-r--r--src/parser.h26
-rw-r--r--src/platform-freebsd.cc12
-rw-r--r--src/platform-linux.cc16
-rw-r--r--src/platform-macos.cc33
-rw-r--r--src/platform-nullos.cc13
-rw-r--r--src/platform-openbsd.cc12
-rw-r--r--src/platform-solaris.cc12
-rw-r--r--src/platform-win32.cc13
-rw-r--r--src/platform.h13
-rw-r--r--src/preparse-data.cc21
-rw-r--r--src/preparse-data.h48
-rw-r--r--src/preparser-api.cc1
-rw-r--r--src/preparser.cc35
-rw-r--r--src/preparser.h5
-rw-r--r--src/scanner-base.cc34
-rw-r--r--src/scanner-base.h216
-rwxr-xr-xsrc/scanner.cc11
-rw-r--r--src/scanner.h3
-rw-r--r--src/string-search.h7
-rw-r--r--src/string.js2
-rw-r--r--src/top.cc4
-rw-r--r--src/unicode.cc328
-rw-r--r--src/utils.h18
-rw-r--r--src/v8threads.cc3
-rw-r--r--src/v8utils.h5
-rw-r--r--src/version.cc4
-rw-r--r--src/x64/assembler-x64.cc2
-rw-r--r--src/x64/assembler-x64.h2
-rw-r--r--src/x64/builtins-x64.cc10
-rw-r--r--src/x64/code-stubs-x64.cc8
-rw-r--r--src/x64/code-stubs-x64.h40
-rw-r--r--src/x64/codegen-x64.cc13
-rw-r--r--src/x64/debug-x64.cc148
-rw-r--r--src/x64/full-codegen-x64.cc2
-rw-r--r--src/x64/ic-x64.cc464
-rw-r--r--src/x64/macro-assembler-x64.cc4
-rw-r--r--src/x64/macro-assembler-x64.h2
-rw-r--r--src/x64/regexp-macro-assembler-x64.cc6
-rw-r--r--src/x64/stub-cache-x64.cc2259
-rw-r--r--test/cctest/test-assembler-ia32.cc10
-rw-r--r--test/cctest/test-disasm-ia32.cc2
-rwxr-xr-xtest/cctest/test-parsing.cc2
-rw-r--r--test/mjsunit/bugs/bug-1015.js66
-rw-r--r--test/mjsunit/indexed-accessors.js13
-rw-r--r--test/mjsunit/regress/regress-1017.js36
-rw-r--r--test/mjsunit/regress/regress-900.js46
-rw-r--r--test/mozilla/mozilla.status2
-rw-r--r--tools/gyp/v8.gyp1469
-rw-r--r--tools/v8.xcodeproj/project.pbxproj38
-rw-r--r--tools/visual_studio/v8_base.vcproj4
-rw-r--r--tools/visual_studio/v8_base_arm.vcproj4
-rw-r--r--tools/visual_studio/v8_base_x64.vcproj4
111 files changed, 5040 insertions, 4075 deletions
diff --git a/ChangeLog b/ChangeLog
index c81d7a73..c89ec311 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,28 @@
+2010-01-05: Version 3.0.6
+
+ Allowed getters and setters on JSArray elements (Issue 900).
+
+ Stopped JSON objects from hitting inherited setters (part of
+ Issue 1015).
+
+ Allowed numbers and strings as names of getters/setters in object
+ initializer (Issue 820).
+
+ Added use_system_v8 option to gyp (off by default), to make it easier
+ for Linux distributions to ship with system-provided V8 library.
+
+ Exported external array data accessors (Issue 1016).
+
+ Added labelled thread names to help with debugging (on Linux).
+
+
+2011-01-03: Version 3.0.5
+
+ Fixed a couple of cast errors for gcc-3.4.3.
+
+ Performance improvements in GC and IA32 code generator.
+
+
2010-12-21: Version 3.0.4
Added Date::ResetCache() to the API so that the cached values in the
diff --git a/V8_MERGE_REVISION b/V8_MERGE_REVISION
index afd88f3d..e9ea6594 100644
--- a/V8_MERGE_REVISION
+++ b/V8_MERGE_REVISION
@@ -1,5 +1,7 @@
We use a V8 revision that has been used for a Chromium release.
-http://src.chromium.org/svn/releases/10.0.621.0/DEPS
-http://v8.googlecode.com/svn/trunk@6101 (+ 1 cherry pick from r6346 in src/v8utils.h to fix compile on Android)
+http://src.chromium.org/svn/releases/10.0.634.0/DEPS
+http://v8.googlecode.com/svn/trunk@6190 plus two partial cherry-picks to fix Android build ...
+- r6346 - include platform.h in src/v8utils.h
+- r7077 - CreateThread() in src/platform-linux.cc
diff --git a/include/v8.h b/include/v8.h
index 2c0f3508..883bfad9 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -1651,9 +1651,9 @@ class Object : public Value {
* the backing store is preserved while V8 has a reference.
*/
V8EXPORT void SetIndexedPropertiesToPixelData(uint8_t* data, int length);
- bool HasIndexedPropertiesInPixelData();
- uint8_t* GetIndexedPropertiesPixelData();
- int GetIndexedPropertiesPixelDataLength();
+ V8EXPORT bool HasIndexedPropertiesInPixelData();
+ V8EXPORT uint8_t* GetIndexedPropertiesPixelData();
+ V8EXPORT int GetIndexedPropertiesPixelDataLength();
/**
* Set the backing store of the indexed properties to be managed by the
@@ -1666,10 +1666,10 @@ class Object : public Value {
void* data,
ExternalArrayType array_type,
int number_of_elements);
- bool HasIndexedPropertiesInExternalArrayData();
- void* GetIndexedPropertiesExternalArrayData();
- ExternalArrayType GetIndexedPropertiesExternalArrayDataType();
- int GetIndexedPropertiesExternalArrayDataLength();
+ V8EXPORT bool HasIndexedPropertiesInExternalArrayData();
+ V8EXPORT void* GetIndexedPropertiesExternalArrayData();
+ V8EXPORT ExternalArrayType GetIndexedPropertiesExternalArrayDataType();
+ V8EXPORT int GetIndexedPropertiesExternalArrayDataLength();
V8EXPORT static Local<Object> New();
static inline Object* Cast(Value* obj);
@@ -3076,6 +3076,18 @@ class V8EXPORT Context {
* Returns a persistent handle to the newly allocated context. This
* persistent handle has to be disposed when the context is no
* longer used so the context can be garbage collected.
+ *
+ * \param extensions An optional extension configuration containing
+ * the extensions to be installed in the newly created context.
+ *
+ * \param global_template An optional object template from which the
+ * global object for the newly created context will be created.
+ *
+ * \param global_object An optional global object to be reused for
+ * the newly created context. This global object must have been
+ * created by a previous call to Context::New with the same global
+ * template. The state of the global object will be completely reset
+ * and only object identify will remain.
*/
static Persistent<Context> New(
ExtensionConfiguration* extensions = NULL,
diff --git a/src/SConscript b/src/SConscript
index dfa099cb..b1f9bb61 100755
--- a/src/SConscript
+++ b/src/SConscript
@@ -229,9 +229,10 @@ SOURCES = {
'os:win32': ['platform-win32.cc'],
'mode:release': [],
'mode:debug': [
- 'objects-debug.cc', 'prettyprinter.cc', 'regexp-macro-assembler-tracer.cc'
+ 'objects-debug.cc', 'objects-printer.cc', 'prettyprinter.cc',
+ 'regexp-macro-assembler-tracer.cc'
],
- 'objectprint:on': ['objects-debug.cc']
+ 'objectprint:on': ['objects-printer.cc']
}
diff --git a/src/arm/assembler-arm.h b/src/arm/assembler-arm.h
index 36f7507f..cd7f07f0 100644
--- a/src/arm/assembler-arm.h
+++ b/src/arm/assembler-arm.h
@@ -66,13 +66,14 @@ namespace internal {
// such that we use an enum in optimized mode, and the struct in debug
// mode. This way we get the compile-time error checking in debug mode
// and best performance in optimized code.
-//
+
// Core register
struct Register {
static const int kNumRegisters = 16;
static const int kNumAllocatableRegisters = 8;
static int ToAllocationIndex(Register reg) {
+ ASSERT(reg.code() < kNumAllocatableRegisters);
return reg.code();
}
@@ -132,7 +133,7 @@ const Register r5 = { 5 };
const Register r6 = { 6 };
const Register r7 = { 7 };
const Register r8 = { 8 }; // Used as context register.
-const Register r9 = { 9 };
+const Register r9 = { 9 }; // Used as lithium codegen scratch register.
const Register r10 = { 10 }; // Used as roots register.
const Register fp = { 11 };
const Register ip = { 12 };
diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc
index 5ec8584f..577ac633 100644
--- a/src/arm/code-stubs-arm.cc
+++ b/src/arm/code-stubs-arm.cc
@@ -917,13 +917,6 @@ void NumberToStringStub::Generate(MacroAssembler* masm) {
}
-void RecordWriteStub::Generate(MacroAssembler* masm) {
- __ add(offset_, object_, Operand(offset_));
- __ RecordWriteHelper(object_, offset_, scratch_);
- __ Ret();
-}
-
-
// On entry lhs_ and rhs_ are the values to be compared.
// On exit r0 is 0, positive or negative to indicate the result of
// the comparison.
@@ -1229,16 +1222,22 @@ void GenericBinaryOpStub::HandleBinaryOpSlowCases(
bool generate_code_to_calculate_answer = true;
if (ShouldGenerateFPCode()) {
+ // DIV has neither SmiSmi fast code nor specialized slow code.
+ // So don't try to patch a DIV Stub.
if (runtime_operands_type_ == BinaryOpIC::DEFAULT) {
switch (op_) {
case Token::ADD:
case Token::SUB:
case Token::MUL:
- case Token::DIV:
GenerateTypeTransition(masm); // Tail call.
generate_code_to_calculate_answer = false;
break;
+ case Token::DIV:
+ // DIV has neither SmiSmi fast code nor specialized slow code.
+ // So don't try to patch a DIV Stub.
+ break;
+
default:
break;
}
@@ -1299,7 +1298,8 @@ void GenericBinaryOpStub::HandleBinaryOpSlowCases(
// HEAP_NUMBERS stub is slower than GENERIC on a pair of smis.
// r0 is known to be a smi. If r1 is also a smi then switch to GENERIC.
Label r1_is_not_smi;
- if (runtime_operands_type_ == BinaryOpIC::HEAP_NUMBERS) {
+ if ((runtime_operands_type_ == BinaryOpIC::HEAP_NUMBERS) &&
+ HasSmiSmiFastPath()) {
__ tst(r1, Operand(kSmiTagMask));
__ b(ne, &r1_is_not_smi);
GenerateTypeTransition(masm); // Tail call.
@@ -2894,45 +2894,45 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
// Uses registers r0 to r4. Expected input is
-// function in r0 (or at sp+1*ptrsz) and object in
+// object in r0 (or at sp+1*kPointerSize) and function in
// r1 (or at sp), depending on whether or not
// args_in_registers() is true.
void InstanceofStub::Generate(MacroAssembler* masm) {
// Fixed register usage throughout the stub:
- const Register object = r1; // Object (lhs).
+ const Register object = r0; // Object (lhs).
const Register map = r3; // Map of the object.
- const Register function = r0; // Function (rhs).
+ const Register function = r1; // Function (rhs).
const Register prototype = r4; // Prototype of the function.
const Register scratch = r2;
Label slow, loop, is_instance, is_not_instance, not_js_object;
if (!args_in_registers()) {
- __ ldr(function, MemOperand(sp, 1 * kPointerSize));
- __ ldr(object, MemOperand(sp, 0));
+ __ ldr(object, MemOperand(sp, 1 * kPointerSize));
+ __ ldr(function, MemOperand(sp, 0));
}
// Check that the left hand is a JS object and load map.
- __ BranchOnSmi(object, &slow);
- __ IsObjectJSObjectType(object, map, scratch, &slow);
+ __ BranchOnSmi(object, &not_js_object);
+ __ IsObjectJSObjectType(object, map, scratch, &not_js_object);
// Look up the function and the map in the instanceof cache.
Label miss;
__ LoadRoot(ip, Heap::kInstanceofCacheFunctionRootIndex);
- __ cmp(object, ip);
+ __ cmp(function, ip);
__ b(ne, &miss);
__ LoadRoot(ip, Heap::kInstanceofCacheMapRootIndex);
__ cmp(map, ip);
__ b(ne, &miss);
- __ LoadRoot(function, Heap::kInstanceofCacheAnswerRootIndex);
+ __ LoadRoot(r0, Heap::kInstanceofCacheAnswerRootIndex);
__ Ret(args_in_registers() ? 0 : 2);
__ bind(&miss);
- __ TryGetFunctionPrototype(object, prototype, scratch, &slow);
+ __ TryGetFunctionPrototype(function, prototype, scratch, &slow);
// Check that the function prototype is a JS object.
__ BranchOnSmi(prototype, &slow);
__ IsObjectJSObjectType(prototype, scratch, scratch, &slow);
- __ StoreRoot(object, Heap::kInstanceofCacheFunctionRootIndex);
+ __ StoreRoot(function, Heap::kInstanceofCacheFunctionRootIndex);
__ StoreRoot(map, Heap::kInstanceofCacheMapRootIndex);
// Register mapping: r3 is object map and r4 is function prototype.
@@ -2957,6 +2957,7 @@ void InstanceofStub::Generate(MacroAssembler* masm) {
__ bind(&is_not_instance);
__ mov(r0, Operand(Smi::FromInt(1)));
+ __ StoreRoot(r0, Heap::kInstanceofCacheAnswerRootIndex);
__ Ret(args_in_registers() ? 0 : 2);
Label object_not_null, object_not_null_or_smi;
@@ -2986,6 +2987,9 @@ void InstanceofStub::Generate(MacroAssembler* masm) {
__ Ret(args_in_registers() ? 0 : 2);
// Slow-case. Tail call builtin.
+ if (args_in_registers()) {
+ __ Push(r0, r1);
+ }
__ bind(&slow);
__ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_JS);
}
diff --git a/src/arm/code-stubs-arm.h b/src/arm/code-stubs-arm.h
index 8ffca773..9fa86879 100644
--- a/src/arm/code-stubs-arm.h
+++ b/src/arm/code-stubs-arm.h
@@ -77,7 +77,7 @@ class GenericBinaryOpStub : public CodeStub {
rhs_(rhs),
constant_rhs_(constant_rhs),
specialized_on_rhs_(RhsIsOneWeWantToOptimizeFor(op, constant_rhs)),
- runtime_operands_type_(BinaryOpIC::DEFAULT),
+ runtime_operands_type_(BinaryOpIC::UNINIT_OR_SMI),
name_(NULL) { }
GenericBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info)
@@ -178,6 +178,10 @@ class GenericBinaryOpStub : public CodeStub {
return lhs_is_r0 ? r1 : r0;
}
+ bool HasSmiSmiFastPath() {
+ return op_ != Token::DIV;
+ }
+
bool ShouldGenerateSmiCode() {
return ((op_ != Token::DIV && op_ != Token::MOD) || specialized_on_rhs_) &&
runtime_operands_type_ != BinaryOpIC::HEAP_NUMBERS &&
@@ -437,43 +441,6 @@ class NumberToStringStub: public CodeStub {
};
-class RecordWriteStub : public CodeStub {
- public:
- RecordWriteStub(Register object, Register offset, Register scratch)
- : object_(object), offset_(offset), scratch_(scratch) { }
-
- void Generate(MacroAssembler* masm);
-
- private:
- Register object_;
- Register offset_;
- Register scratch_;
-
- // Minor key encoding in 12 bits. 4 bits for each of the three
- // registers (object, offset and scratch) OOOOAAAASSSS.
- class ScratchBits: public BitField<uint32_t, 0, 4> {};
- class OffsetBits: public BitField<uint32_t, 4, 4> {};
- class ObjectBits: public BitField<uint32_t, 8, 4> {};
-
- Major MajorKey() { return RecordWrite; }
-
- int MinorKey() {
- // Encode the registers.
- return ObjectBits::encode(object_.code()) |
- OffsetBits::encode(offset_.code()) |
- ScratchBits::encode(scratch_.code());
- }
-
-#ifdef DEBUG
- void Print() {
- PrintF("RecordWriteStub (object reg %d), (offset reg %d),"
- " (scratch reg %d)\n",
- object_.code(), offset_.code(), scratch_.code());
- }
-#endif
-};
-
-
// Enter C code from generated RegExp code in a way that allows
// the C code to fix the return address in case of a GC.
// Currently only needed on ARM.
diff --git a/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc
index 59bc14e7..4d061d23 100644
--- a/src/arm/codegen-arm.cc
+++ b/src/arm/codegen-arm.cc
@@ -5618,12 +5618,10 @@ void CodeGenerator::GenerateSwapElements(ZoneList<Expression*>* args) {
// (or them and test against Smi mask.)
__ mov(tmp2, tmp1);
- RecordWriteStub recordWrite1(tmp1, index1, tmp3);
- __ CallStub(&recordWrite1);
-
- RecordWriteStub recordWrite2(tmp2, index2, tmp3);
- __ CallStub(&recordWrite2);
-
+ __ add(index1, index1, tmp1);
+ __ add(index2, index2, tmp1);
+ __ RecordWriteHelper(tmp1, index1, tmp3);
+ __ RecordWriteHelper(tmp2, index2, tmp3);
__ bind(&done);
deferred->BindExit();
diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc
index d2549183..0275730a 100644
--- a/src/arm/full-codegen-arm.cc
+++ b/src/arm/full-codegen-arm.cc
@@ -38,6 +38,8 @@
#include "scopes.h"
#include "stub-cache.h"
+#include "arm/code-stubs-arm.h"
+
namespace v8 {
namespace internal {
diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc
index e31d2e1d..87efc92c 100644
--- a/src/arm/lithium-arm.cc
+++ b/src/arm/lithium-arm.cc
@@ -767,11 +767,6 @@ LInstruction* LChunkBuilder::DefineAsSpilled(LInstruction* instr, int index) {
}
-LInstruction* LChunkBuilder::DefineSameAsAny(LInstruction* instr) {
- return Define(instr, new LUnallocated(LUnallocated::SAME_AS_ANY_INPUT));
-}
-
-
LInstruction* LChunkBuilder::DefineSameAsFirst(LInstruction* instr) {
return Define(instr, new LUnallocated(LUnallocated::SAME_AS_FIRST_INPUT));
}
@@ -1016,9 +1011,6 @@ void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) {
HInstruction* current = block->first();
int start = chunk_->instructions()->length();
while (current != NULL && !is_aborted()) {
- if (FLAG_trace_environment) {
- PrintF("Process instruction %d\n", current->id());
- }
// Code for constants in registers is generated lazily.
if (!current->EmitAtUses()) {
VisitInstruction(current);
@@ -1125,7 +1117,7 @@ LEnvironment* LChunkBuilder::CreateEnvironment(HEnvironment* hydrogen_env) {
LEnvironment* outer = CreateEnvironment(hydrogen_env->outer());
int ast_id = hydrogen_env->ast_id();
ASSERT(ast_id != AstNode::kNoNumber);
- int value_count = hydrogen_env->values()->length();
+ int value_count = hydrogen_env->length();
LEnvironment* result = new LEnvironment(hydrogen_env->closure(),
ast_id,
hydrogen_env->parameter_count(),
@@ -1225,7 +1217,6 @@ LInstruction* LChunkBuilder::DoBranch(HBranch* instr) {
ASSERT(compare->value()->representation().IsTagged());
return new LHasInstanceTypeAndBranch(UseRegisterAtStart(compare->value()),
- TempRegister(),
first_id,
second_id);
} else if (v->IsHasCachedArrayIndex()) {
@@ -1238,11 +1229,8 @@ LInstruction* LChunkBuilder::DoBranch(HBranch* instr) {
HIsNull* compare = HIsNull::cast(v);
ASSERT(compare->value()->representation().IsTagged());
- // We only need a temp register for non-strict compare.
- LOperand* temp = compare->is_strict() ? NULL : TempRegister();
return new LIsNullAndBranch(UseRegisterAtStart(compare->value()),
compare->is_strict(),
- temp,
first_id,
second_id);
} else if (v->IsIsObject()) {
@@ -1295,12 +1283,8 @@ LInstruction* LChunkBuilder::DoCompareMapAndBranch(
HCompareMapAndBranch* instr) {
ASSERT(instr->value()->representation().IsTagged());
LOperand* value = UseRegisterAtStart(instr->value());
- HBasicBlock* first = instr->FirstSuccessor();
- HBasicBlock* second = instr->SecondSuccessor();
- return new LCmpMapAndBranch(value,
- instr->map(),
- first->block_id(),
- second->block_id());
+ LOperand* temp = TempRegister();
+ return new LCmpMapAndBranch(value, temp);
}
@@ -1316,8 +1300,8 @@ LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) {
LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
LInstruction* result =
- new LInstanceOf(UseFixed(instr->left(), r1),
- UseFixed(instr->right(), r0));
+ new LInstanceOf(UseFixed(instr->left(), r0),
+ UseFixed(instr->right(), r1));
return MarkAsCall(DefineFixed(result, r0), instr);
}
@@ -1370,6 +1354,9 @@ LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
return AssignEnvironment(DefineAsRegister(result));
case kMathSqrt:
return DefineSameAsFirst(result);
+ case kMathRound:
+ Abort("MathRound LUnaryMathOperation not implemented");
+ return NULL;
case kMathPowHalf:
Abort("MathPowHalf LUnaryMathOperation not implemented");
return NULL;
@@ -1666,19 +1653,15 @@ LInstruction* LChunkBuilder::DoClassOfTest(HClassOfTest* instr) {
}
-LInstruction* LChunkBuilder::DoArrayLength(HArrayLength* instr) {
- LOperand* array = NULL;
- LOperand* temporary = NULL;
+LInstruction* LChunkBuilder::DoJSArrayLength(HJSArrayLength* instr) {
+ LOperand* array = UseRegisterAtStart(instr->value());
+ return DefineAsRegister(new LJSArrayLength(array));
+}
- if (instr->value()->IsLoadElements()) {
- array = UseRegisterAtStart(instr->value());
- } else {
- array = UseRegister(instr->value());
- temporary = TempRegister();
- }
- LInstruction* result = new LArrayLength(array, temporary);
- return AssignEnvironment(DefineAsRegister(result));
+LInstruction* LChunkBuilder::DoFixedArrayLength(HFixedArrayLength* instr) {
+ LOperand* array = UseRegisterAtStart(instr->value());
+ return DefineAsRegister(new LFixedArrayLength(array));
}
@@ -1778,9 +1761,11 @@ LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
LInstruction* LChunkBuilder::DoCheckPrototypeMaps(HCheckPrototypeMaps* instr) {
- LOperand* temp = TempRegister();
+ LOperand* temp1 = TempRegister();
+ LOperand* temp2 = TempRegister();
LInstruction* result =
- new LCheckPrototypeMaps(temp,
+ new LCheckPrototypeMaps(temp1,
+ temp2,
instr->holder(),
instr->receiver_map());
return AssignEnvironment(result);
@@ -1854,6 +1839,13 @@ LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
}
+LInstruction* LChunkBuilder::DoLoadFunctionPrototype(
+ HLoadFunctionPrototype* instr) {
+ return AssignEnvironment(DefineAsRegister(
+ new LLoadFunctionPrototype(UseRegister(instr->function()))));
+}
+
+
LInstruction* LChunkBuilder::DoLoadElements(HLoadElements* instr) {
LOperand* input = UseRegisterAtStart(instr->value());
return DefineSameAsFirst(new LLoadElements(input));
@@ -2054,13 +2046,7 @@ LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
}
}
- if (FLAG_trace_environment) {
- PrintF("Reconstructed environment ast_id=%d, instr_id=%d\n",
- instr->ast_id(),
- instr->id());
- env->PrintToStd();
- }
- ASSERT(env->values()->length() == instr->environment_height());
+ ASSERT(env->length() == instr->environment_length());
// If there is an instruction pending deoptimization environment create a
// lazy bailout instruction to capture the environment.
diff --git a/src/arm/lithium-arm.h b/src/arm/lithium-arm.h
index 41209c67..2f8cc1c7 100644
--- a/src/arm/lithium-arm.h
+++ b/src/arm/lithium-arm.h
@@ -101,7 +101,8 @@ class Translation;
// LStoreNamedField
// LStoreNamedGeneric
// LUnaryOperation
-// LArrayLength
+// LJSArrayLength
+// LFixedArrayLength
// LBitNotI
// LBranch
// LCallNew
@@ -127,6 +128,7 @@ class Translation;
// LIsSmiAndBranch
// LLoadNamedField
// LLoadNamedGeneric
+// LLoadFunctionPrototype
// LNumberTagD
// LNumberTagI
// LPushArgument
@@ -161,7 +163,6 @@ class Translation;
V(ArgumentsLength) \
V(ArithmeticD) \
V(ArithmeticT) \
- V(ArrayLength) \
V(ArrayLiteral) \
V(BitI) \
V(BitNotI) \
@@ -195,6 +196,7 @@ class Translation;
V(Deoptimize) \
V(DivI) \
V(DoubleToI) \
+ V(FixedArrayLength) \
V(FunctionLiteral) \
V(Gap) \
V(GlobalObject) \
@@ -209,6 +211,7 @@ class Translation;
V(IsObjectAndBranch) \
V(IsSmi) \
V(IsSmiAndBranch) \
+ V(JSArrayLength) \
V(HasInstanceType) \
V(HasInstanceTypeAndBranch) \
V(HasCachedArrayIndex) \
@@ -223,6 +226,7 @@ class Translation;
V(LoadKeyedGeneric) \
V(LoadNamedField) \
V(LoadNamedGeneric) \
+ V(LoadFunctionPrototype) \
V(ModI) \
V(MulI) \
V(NumberTagD) \
@@ -722,11 +726,9 @@ class LIsNullAndBranch: public LIsNull {
public:
LIsNullAndBranch(LOperand* value,
bool is_strict,
- LOperand* temp,
int true_block_id,
int false_block_id)
: LIsNull(value, is_strict),
- temp_(temp),
true_block_id_(true_block_id),
false_block_id_(false_block_id) { }
@@ -737,10 +739,7 @@ class LIsNullAndBranch: public LIsNull {
int true_block_id() const { return true_block_id_; }
int false_block_id() const { return false_block_id_; }
- LOperand* temp() const { return temp_; }
-
private:
- LOperand* temp_;
int true_block_id_;
int false_block_id_;
};
@@ -835,11 +834,9 @@ class LHasInstanceType: public LUnaryOperation {
class LHasInstanceTypeAndBranch: public LHasInstanceType {
public:
LHasInstanceTypeAndBranch(LOperand* value,
- LOperand* temporary,
int true_block_id,
int false_block_id)
: LHasInstanceType(value),
- temp_(temporary),
true_block_id_(true_block_id),
false_block_id_(false_block_id) { }
@@ -851,10 +848,7 @@ class LHasInstanceTypeAndBranch: public LHasInstanceType {
int true_block_id() const { return true_block_id_; }
int false_block_id() const { return false_block_id_; }
- LOperand* temp() { return temp_; }
-
private:
- LOperand* temp_;
int true_block_id_;
int false_block_id_;
};
@@ -1117,42 +1111,43 @@ class LBranch: public LUnaryOperation {
class LCmpMapAndBranch: public LUnaryOperation {
public:
- LCmpMapAndBranch(LOperand* value,
- Handle<Map> map,
- int true_block_id,
- int false_block_id)
- : LUnaryOperation(value),
- map_(map),
- true_block_id_(true_block_id),
- false_block_id_(false_block_id) { }
+ LCmpMapAndBranch(LOperand* value, LOperand* temp)
+ : LUnaryOperation(value), temp_(temp) { }
DECLARE_CONCRETE_INSTRUCTION(CmpMapAndBranch, "cmp-map-and-branch")
+ DECLARE_HYDROGEN_ACCESSOR(CompareMapAndBranch)
virtual bool IsControl() const { return true; }
- Handle<Map> map() const { return map_; }
- int true_block_id() const { return true_block_id_; }
- int false_block_id() const { return false_block_id_; }
+ LOperand* temp() const { return temp_; }
+ Handle<Map> map() const { return hydrogen()->map(); }
+ int true_block_id() const {
+ return hydrogen()->true_destination()->block_id();
+ }
+ int false_block_id() const {
+ return hydrogen()->false_destination()->block_id();
+ }
private:
- Handle<Map> map_;
- int true_block_id_;
- int false_block_id_;
+ LOperand* temp_;
};
-class LArrayLength: public LUnaryOperation {
+class LJSArrayLength: public LUnaryOperation {
public:
- LArrayLength(LOperand* input, LOperand* temporary)
- : LUnaryOperation(input), temporary_(temporary) { }
+ explicit LJSArrayLength(LOperand* input) : LUnaryOperation(input) { }
- LOperand* temporary() const { return temporary_; }
+ DECLARE_CONCRETE_INSTRUCTION(JSArrayLength, "js-array-length")
+ DECLARE_HYDROGEN_ACCESSOR(JSArrayLength)
+};
- DECLARE_CONCRETE_INSTRUCTION(ArrayLength, "array-length")
- DECLARE_HYDROGEN_ACCESSOR(ArrayLength)
- private:
- LOperand* temporary_;
+class LFixedArrayLength: public LUnaryOperation {
+ public:
+ explicit LFixedArrayLength(LOperand* input) : LUnaryOperation(input) { }
+
+ DECLARE_CONCRETE_INSTRUCTION(FixedArrayLength, "fixed-array-length")
+ DECLARE_HYDROGEN_ACCESSOR(FixedArrayLength)
};
@@ -1256,6 +1251,18 @@ class LLoadNamedGeneric: public LUnaryOperation {
};
+class LLoadFunctionPrototype: public LUnaryOperation {
+ public:
+ explicit LLoadFunctionPrototype(LOperand* function)
+ : LUnaryOperation(function) { }
+
+ DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype, "load-function-prototype")
+ DECLARE_HYDROGEN_ACCESSOR(LoadFunctionPrototype)
+
+ LOperand* function() const { return input(); }
+};
+
+
class LLoadElements: public LUnaryOperation {
public:
explicit LLoadElements(LOperand* obj) : LUnaryOperation(obj) { }
@@ -1655,21 +1662,25 @@ class LCheckMap: public LUnaryOperation {
class LCheckPrototypeMaps: public LInstruction {
public:
- LCheckPrototypeMaps(LOperand* temp,
+ LCheckPrototypeMaps(LOperand* temp1,
+ LOperand* temp2,
Handle<JSObject> holder,
Handle<Map> receiver_map)
- : temp_(temp),
+ : temp1_(temp1),
+ temp2_(temp2),
holder_(holder),
receiver_map_(receiver_map) { }
DECLARE_CONCRETE_INSTRUCTION(CheckPrototypeMaps, "check-prototype-maps")
- LOperand* temp() const { return temp_; }
+ LOperand* temp1() const { return temp1_; }
+ LOperand* temp2() const { return temp2_; }
Handle<JSObject> holder() const { return holder_; }
Handle<Map> receiver_map() const { return receiver_map_; }
private:
- LOperand* temp_;
+ LOperand* temp1_;
+ LOperand* temp2_;
Handle<JSObject> holder_;
Handle<Map> receiver_map_;
};
@@ -2051,7 +2062,6 @@ class LChunkBuilder BASE_EMBEDDED {
LInstruction* Define(LInstruction* instr);
LInstruction* DefineAsRegister(LInstruction* instr);
LInstruction* DefineAsSpilled(LInstruction* instr, int index);
- LInstruction* DefineSameAsAny(LInstruction* instr);
LInstruction* DefineSameAsFirst(LInstruction* instr);
LInstruction* DefineFixed(LInstruction* instr, Register reg);
LInstruction* DefineFixedDouble(LInstruction* instr, DoubleRegister reg);
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
index dfc48917..bb2461ce 100644
--- a/src/arm/lithium-codegen-arm.cc
+++ b/src/arm/lithium-codegen-arm.cc
@@ -598,7 +598,7 @@ void LCodeGen::DoParallelMove(LParallelMove* move) {
DoubleRegister dbl_scratch = d0;
LUnallocated marker_operand(LUnallocated::NONE);
- Register core_scratch = r9;
+ Register core_scratch = scratch0();
bool destroys_core_scratch = false;
LGapResolver resolver(move->move_operands(), &marker_operand);
@@ -730,7 +730,53 @@ void LCodeGen::DoParameter(LParameter* instr) {
void LCodeGen::DoCallStub(LCallStub* instr) {
- Abort("DoCallStub unimplemented.");
+ ASSERT(ToRegister(instr->result()).is(r0));
+ switch (instr->hydrogen()->major_key()) {
+ case CodeStub::RegExpConstructResult: {
+ RegExpConstructResultStub stub;
+ CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+ break;
+ }
+ case CodeStub::RegExpExec: {
+ RegExpExecStub stub;
+ CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+ break;
+ }
+ case CodeStub::SubString: {
+ SubStringStub stub;
+ CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+ break;
+ }
+ case CodeStub::StringCharAt: {
+ Abort("StringCharAtStub unimplemented.");
+ break;
+ }
+ case CodeStub::MathPow: {
+ Abort("MathPowStub unimplemented.");
+ break;
+ }
+ case CodeStub::NumberToString: {
+ NumberToStringStub stub;
+ CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+ break;
+ }
+ case CodeStub::StringAdd: {
+ StringAddStub stub(NO_STRING_ADD_FLAGS);
+ CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+ break;
+ }
+ case CodeStub::StringCompare: {
+ StringCompareStub stub;
+ CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+ break;
+ }
+ case CodeStub::TranscendentalCache: {
+ Abort("TranscendentalCache unimplemented.");
+ break;
+ }
+ default:
+ UNREACHABLE();
+ }
}
@@ -750,8 +796,8 @@ void LCodeGen::DoDivI(LDivI* instr) {
void LCodeGen::DoMulI(LMulI* instr) {
+ Register scratch = scratch0();
Register left = ToRegister(instr->left());
- Register scratch = r9;
Register right = EmitLoadRegister(instr->right(), scratch);
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero) &&
@@ -813,6 +859,7 @@ void LCodeGen::DoBitI(LBitI* instr) {
void LCodeGen::DoShiftI(LShiftI* instr) {
+ Register scratch = scratch0();
LOperand* left = instr->left();
LOperand* right = instr->right();
ASSERT(left->Equals(instr->result()));
@@ -820,21 +867,21 @@ void LCodeGen::DoShiftI(LShiftI* instr) {
Register result = ToRegister(left);
if (right->IsRegister()) {
// Mask the right operand.
- __ and_(r9, ToRegister(right), Operand(0x1F));
+ __ and_(scratch, ToRegister(right), Operand(0x1F));
switch (instr->op()) {
case Token::SAR:
- __ mov(result, Operand(result, ASR, r9));
+ __ mov(result, Operand(result, ASR, scratch));
break;
case Token::SHR:
if (instr->can_deopt()) {
- __ mov(result, Operand(result, LSR, r9), SetCC);
+ __ mov(result, Operand(result, LSR, scratch), SetCC);
DeoptimizeIf(mi, instr->environment());
} else {
- __ mov(result, Operand(result, LSR, r9));
+ __ mov(result, Operand(result, LSR, scratch));
}
break;
case Token::SHL:
- __ mov(result, Operand(result, LSL, r9));
+ __ mov(result, Operand(result, LSL, scratch));
break;
default:
UNREACHABLE();
@@ -898,24 +945,18 @@ void LCodeGen::DoConstantT(LConstantT* instr) {
}
-void LCodeGen::DoArrayLength(LArrayLength* instr) {
+void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) {
Register result = ToRegister(instr->result());
+ Register array = ToRegister(instr->input());
+ __ ldr(result, FieldMemOperand(array, JSArray::kLengthOffset));
+}
- if (instr->hydrogen()->value()->IsLoadElements()) {
- // We load the length directly from the elements array.
- Register elements = ToRegister(instr->input());
- __ ldr(result, FieldMemOperand(elements, FixedArray::kLengthOffset));
- } else {
- // Check that the receiver really is an array.
- Register array = ToRegister(instr->input());
- Register temporary = ToRegister(instr->temporary());
- __ CompareObjectType(array, temporary, temporary, JS_ARRAY_TYPE);
- DeoptimizeIf(ne, instr->environment());
- // Load length directly from the array.
- __ ldr(result, FieldMemOperand(array, JSArray::kLengthOffset));
- }
- Abort("DoArrayLength untested.");
+void LCodeGen::DoFixedArrayLength(LFixedArrayLength* instr) {
+ Register result = ToRegister(instr->result());
+ Register array = ToRegister(instr->input());
+ __ ldr(result, FieldMemOperand(array, FixedArray::kLengthOffset));
+ Abort("DoFixedArrayLength untested.");
}
@@ -1065,11 +1106,10 @@ void LCodeGen::DoBranch(LBranch* instr) {
// Test for double values. Zero is false.
Label call_stub;
DoubleRegister dbl_scratch = d0;
- Register core_scratch = r9;
- ASSERT(!reg.is(core_scratch));
- __ ldr(core_scratch, FieldMemOperand(reg, HeapObject::kMapOffset));
+ Register scratch = scratch0();
+ __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset));
__ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
- __ cmp(core_scratch, Operand(ip));
+ __ cmp(scratch, Operand(ip));
__ b(ne, &call_stub);
__ sub(ip, reg, Operand(kHeapObjectTag));
__ vldr(dbl_scratch, ip, HeapNumber::kValueOffset);
@@ -1176,11 +1216,41 @@ void LCodeGen::DoCmpJSObjectEqAndBranch(LCmpJSObjectEqAndBranch* instr) {
void LCodeGen::DoIsNull(LIsNull* instr) {
- Abort("DoIsNull unimplemented.");
+ Register reg = ToRegister(instr->input());
+ Register result = ToRegister(instr->result());
+
+ __ LoadRoot(ip, Heap::kNullValueRootIndex);
+ __ cmp(reg, ip);
+ if (instr->is_strict()) {
+ __ LoadRoot(result, Heap::kTrueValueRootIndex, eq);
+ __ LoadRoot(result, Heap::kFalseValueRootIndex, ne);
+ } else {
+ Label true_value, false_value, done;
+ __ b(eq, &true_value);
+ __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
+ __ cmp(ip, reg);
+ __ b(eq, &true_value);
+ __ tst(reg, Operand(kSmiTagMask));
+ __ b(eq, &false_value);
+ // Check for undetectable objects by looking in the bit field in
+ // the map. The object has already been smi checked.
+ Register scratch = result;
+ __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset));
+ __ ldrb(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset));
+ __ tst(scratch, Operand(1 << Map::kIsUndetectable));
+ __ b(ne, &true_value);
+ __ bind(&false_value);
+ __ LoadRoot(result, Heap::kFalseValueRootIndex);
+ __ jmp(&done);
+ __ bind(&true_value);
+ __ LoadRoot(result, Heap::kTrueValueRootIndex);
+ __ bind(&done);
+ }
}
void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) {
+ Register scratch = scratch0();
Register reg = ToRegister(instr->input());
// TODO(fsc): If the expression is known to be a smi, then it's
@@ -1204,7 +1274,6 @@ void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) {
__ b(eq, false_label);
// Check for undetectable objects by looking in the bit field in
// the map. The object has already been smi checked.
- Register scratch = ToRegister(instr->temp());
__ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset));
__ ldrb(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset));
__ tst(scratch, Operand(1 << Map::kIsUndetectable));
@@ -1282,8 +1351,8 @@ void LCodeGen::DoHasInstanceType(LHasInstanceType* instr) {
void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) {
+ Register scratch = scratch0();
Register input = ToRegister(instr->input());
- Register temp = ToRegister(instr->temp());
int true_block = chunk_->LookupDestination(instr->true_block_id());
int false_block = chunk_->LookupDestination(instr->false_block_id());
@@ -1293,7 +1362,7 @@ void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) {
__ tst(input, Operand(kSmiTagMask));
__ b(eq, false_label);
- __ CompareObjectType(input, temp, temp, instr->TestType());
+ __ CompareObjectType(input, scratch, scratch, instr->TestType());
EmitBranch(true_block, false_block, instr->BranchCondition());
}
@@ -1332,19 +1401,28 @@ void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) {
void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) {
- Abort("DoCmpMapAndBranch unimplemented.");
+ Register reg = ToRegister(instr->input());
+ Register temp = ToRegister(instr->temp());
+ int true_block = instr->true_block_id();
+ int false_block = instr->false_block_id();
+
+ __ ldr(temp, FieldMemOperand(reg, HeapObject::kMapOffset));
+ __ cmp(temp, Operand(instr->map()));
+ EmitBranch(true_block, false_block, eq);
}
void LCodeGen::DoInstanceOf(LInstanceOf* instr) {
- // We expect object and function in registers r1 and r0.
+ ASSERT(ToRegister(instr->left()).is(r0)); // Object is in r0.
+ ASSERT(ToRegister(instr->right()).is(r1)); // Function is in r1.
+
InstanceofStub stub(InstanceofStub::kArgsInRegisters);
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
Label true_value, done;
__ tst(r0, r0);
- __ mov(r0, Operand(Factory::false_value()), LeaveCC, eq);
- __ mov(r0, Operand(Factory::true_value()), LeaveCC, ne);
+ __ mov(r0, Operand(Factory::false_value()), LeaveCC, ne);
+ __ mov(r0, Operand(Factory::true_value()), LeaveCC, eq);
}
@@ -1432,7 +1510,14 @@ void LCodeGen::DoStoreGlobal(LStoreGlobal* instr) {
void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
- Abort("DoLoadNamedField unimplemented.");
+ Register object = ToRegister(instr->input());
+ Register result = ToRegister(instr->result());
+ if (instr->hydrogen()->is_in_object()) {
+ __ ldr(result, FieldMemOperand(object, instr->hydrogen()->offset()));
+ } else {
+ __ ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset));
+ __ ldr(result, FieldMemOperand(result, instr->hydrogen()->offset()));
+ }
}
@@ -1447,6 +1532,50 @@ void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
}
+void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) {
+ Register scratch = scratch0();
+ Register function = ToRegister(instr->function());
+ Register result = ToRegister(instr->result());
+
+ // Check that the function really is a function. Load map into the
+ // result register.
+ __ CompareObjectType(function, result, scratch, JS_FUNCTION_TYPE);
+ DeoptimizeIf(ne, instr->environment());
+
+ // Make sure that the function has an instance prototype.
+ Label non_instance;
+ __ ldrb(scratch, FieldMemOperand(result, Map::kBitFieldOffset));
+ __ tst(scratch, Operand(1 << Map::kHasNonInstancePrototype));
+ __ b(ne, &non_instance);
+
+ // Get the prototype or initial map from the function.
+ __ ldr(result,
+ FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
+
+ // Check that the function has a prototype or an initial map.
+ __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
+ __ cmp(result, ip);
+ DeoptimizeIf(eq, instr->environment());
+
+ // If the function does not have an initial map, we're done.
+ Label done;
+ __ CompareObjectType(result, scratch, scratch, MAP_TYPE);
+ __ b(ne, &done);
+
+ // Get the prototype from the initial map.
+ __ ldr(result, FieldMemOperand(result, Map::kPrototypeOffset));
+ __ jmp(&done);
+
+ // Non-instance prototype: Fetch prototype from constructor field
+ // in initial map.
+ __ bind(&non_instance);
+ __ ldr(result, FieldMemOperand(result, Map::kConstructorOffset));
+
+ // All done.
+ __ bind(&done);
+}
+
+
void LCodeGen::DoLoadElements(LLoadElements* instr) {
Abort("DoLoadElements unimplemented.");
}
@@ -1544,7 +1673,9 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) {
- Abort("DoCallConstantFunction unimplemented.");
+ ASSERT(ToRegister(instr->result()).is(r0));
+ __ mov(r1, Operand(instr->function()));
+ CallKnownFunction(instr->function(), instr->arity(), instr);
}
@@ -1604,7 +1735,13 @@ void LCodeGen::DoCallNamed(LCallNamed* instr) {
void LCodeGen::DoCallFunction(LCallFunction* instr) {
- Abort("DoCallFunction unimplemented.");
+ ASSERT(ToRegister(instr->result()).is(r0));
+
+ int arity = instr->arity();
+ CallFunctionStub stub(arity, NOT_IN_LOOP, RECEIVER_MIGHT_BE_VALUE);
+ CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+ __ Drop(1);
+ __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
}
@@ -1652,7 +1789,8 @@ void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
- Abort("DoBoundsCheck unimplemented.");
+ __ cmp(ToRegister(instr->index()), ToOperand(instr->length()));
+ DeoptimizeIf(hs, instr->environment());
}
@@ -1757,10 +1895,10 @@ void LCodeGen::DoNumberTagD(LNumberTagD* instr) {
};
DoubleRegister input_reg = ToDoubleRegister(instr->input());
+ Register scratch = scratch0();
Register reg = ToRegister(instr->result());
Register temp1 = ToRegister(instr->temp1());
Register temp2 = ToRegister(instr->temp2());
- Register scratch = r9;
DeferredNumberTagD* deferred = new DeferredNumberTagD(this, instr);
if (FLAG_inline_new) {
@@ -1808,8 +1946,7 @@ void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
void LCodeGen::EmitNumberUntagD(Register input_reg,
DoubleRegister result_reg,
LEnvironment* env) {
- Register core_scratch = r9;
- ASSERT(!input_reg.is(core_scratch));
+ Register scratch = scratch0();
SwVfpRegister flt_scratch = s0;
ASSERT(!result_reg.is(d0));
@@ -1820,9 +1957,9 @@ void LCodeGen::EmitNumberUntagD(Register input_reg,
__ b(eq, &load_smi);
// Heap number map check.
- __ ldr(core_scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
+ __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
__ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
- __ cmp(core_scratch, Operand(ip));
+ __ cmp(scratch, Operand(ip));
__ b(eq, &heap_number);
__ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
@@ -1864,16 +2001,15 @@ class DeferredTaggedToI: public LDeferredCode {
void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
Label done;
Register input_reg = ToRegister(instr->input());
- Register core_scratch = r9;
- ASSERT(!input_reg.is(core_scratch));
+ Register scratch = scratch0();
DoubleRegister dbl_scratch = d0;
SwVfpRegister flt_scratch = s0;
DoubleRegister dbl_tmp = ToDoubleRegister(instr->temp());
// Heap number map check.
- __ ldr(core_scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
+ __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
__ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
- __ cmp(core_scratch, Operand(ip));
+ __ cmp(scratch, Operand(ip));
if (instr->truncating()) {
Label heap_number;
@@ -1985,33 +2121,99 @@ void LCodeGen::DoCheckFunction(LCheckFunction* instr) {
void LCodeGen::DoCheckMap(LCheckMap* instr) {
+ Register scratch = scratch0();
LOperand* input = instr->input();
ASSERT(input->IsRegister());
Register reg = ToRegister(input);
- __ ldr(r9, FieldMemOperand(reg, HeapObject::kMapOffset));
- __ cmp(r9, Operand(instr->hydrogen()->map()));
+ __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset));
+ __ cmp(scratch, Operand(instr->hydrogen()->map()));
DeoptimizeIf(ne, instr->environment());
}
void LCodeGen::LoadPrototype(Register result,
Handle<JSObject> prototype) {
- Abort("LoadPrototype unimplemented.");
+ if (Heap::InNewSpace(*prototype)) {
+ Handle<JSGlobalPropertyCell> cell =
+ Factory::NewJSGlobalPropertyCell(prototype);
+ __ mov(result, Operand(cell));
+ } else {
+ __ mov(result, Operand(prototype));
+ }
}
void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) {
- Abort("DoCheckPrototypeMaps unimplemented.");
+ Register temp1 = ToRegister(instr->temp1());
+ Register temp2 = ToRegister(instr->temp2());
+
+ Handle<JSObject> holder = instr->holder();
+ Handle<Map> receiver_map = instr->receiver_map();
+ Handle<JSObject> current_prototype(JSObject::cast(receiver_map->prototype()));
+
+ // Load prototype object.
+ LoadPrototype(temp1, current_prototype);
+
+ // Check prototype maps up to the holder.
+ while (!current_prototype.is_identical_to(holder)) {
+ __ ldr(temp2, FieldMemOperand(temp1, HeapObject::kMapOffset));
+ __ cmp(temp2, Operand(Handle<Map>(current_prototype->map())));
+ DeoptimizeIf(ne, instr->environment());
+ current_prototype =
+ Handle<JSObject>(JSObject::cast(current_prototype->GetPrototype()));
+ // Load next prototype object.
+ LoadPrototype(temp1, current_prototype);
+ }
+
+ // Check the holder map.
+ __ ldr(temp2, FieldMemOperand(temp1, HeapObject::kMapOffset));
+ __ cmp(temp2, Operand(Handle<Map>(current_prototype->map())));
+ DeoptimizeIf(ne, instr->environment());
}
void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) {
- Abort("DoArrayLiteral unimplemented.");
+ __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
+ __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset));
+ __ mov(r2, Operand(Smi::FromInt(instr->hydrogen()->literal_index())));
+ __ mov(r1, Operand(instr->hydrogen()->constant_elements()));
+ __ Push(r3, r2, r1);
+
+ // Pick the right runtime function or stub to call.
+ int length = instr->hydrogen()->length();
+ if (instr->hydrogen()->IsCopyOnWrite()) {
+ ASSERT(instr->hydrogen()->depth() == 1);
+ FastCloneShallowArrayStub::Mode mode =
+ FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS;
+ FastCloneShallowArrayStub stub(mode, length);
+ CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+ } else if (instr->hydrogen()->depth() > 1) {
+ CallRuntime(Runtime::kCreateArrayLiteral, 3, instr);
+ } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) {
+ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3, instr);
+ } else {
+ FastCloneShallowArrayStub::Mode mode =
+ FastCloneShallowArrayStub::CLONE_ELEMENTS;
+ FastCloneShallowArrayStub stub(mode, length);
+ CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+ }
}
void LCodeGen::DoObjectLiteral(LObjectLiteral* instr) {
- Abort("DoObjectLiteral unimplemented.");
+ __ ldr(r4, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
+ __ ldr(r4, FieldMemOperand(r4, JSFunction::kLiteralsOffset));
+ __ mov(r3, Operand(Smi::FromInt(instr->hydrogen()->literal_index())));
+ __ mov(r2, Operand(instr->hydrogen()->constant_properties()));
+ __ mov(r1, Operand(Smi::FromInt(instr->hydrogen()->fast_elements() ? 1 : 0)));
+ __ Push(r4, r3, r2, r1);
+
+ // Pick the right runtime function to call.
+ if (instr->hydrogen()->depth() > 1) {
+ CallRuntime(Runtime::kCreateObjectLiteral, 4, instr);
+ } else {
+ CallRuntime(Runtime::kCreateObjectLiteralShallow, 4, instr);
+ }
}
@@ -2056,8 +2258,7 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
Register input,
Handle<String> type_name) {
Condition final_branch_condition = no_condition;
- Register core_scratch = r9;
- ASSERT(!input.is(core_scratch));
+ Register scratch = scratch0();
if (type_name->Equals(Heap::number_symbol())) {
__ tst(input, Operand(kSmiTagMask));
__ b(eq, true_label);
@@ -2073,7 +2274,7 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
__ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset));
__ tst(ip, Operand(1 << Map::kIsUndetectable));
__ b(ne, false_label);
- __ CompareInstanceType(input, core_scratch, FIRST_NONSTRING_TYPE);
+ __ CompareInstanceType(input, scratch, FIRST_NONSTRING_TYPE);
final_branch_condition = lo;
} else if (type_name->Equals(Heap::boolean_symbol())) {
@@ -2099,10 +2300,10 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
} else if (type_name->Equals(Heap::function_symbol())) {
__ tst(input, Operand(kSmiTagMask));
__ b(eq, false_label);
- __ CompareObjectType(input, input, core_scratch, JS_FUNCTION_TYPE);
+ __ CompareObjectType(input, input, scratch, JS_FUNCTION_TYPE);
__ b(eq, true_label);
// Regular expressions => 'function' (they are callable).
- __ CompareInstanceType(input, core_scratch, JS_REGEXP_TYPE);
+ __ CompareInstanceType(input, scratch, JS_REGEXP_TYPE);
final_branch_condition = eq;
} else if (type_name->Equals(Heap::object_symbol())) {
@@ -2112,16 +2313,16 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
__ cmp(input, ip);
__ b(eq, true_label);
// Regular expressions => 'function', not 'object'.
- __ CompareObjectType(input, input, core_scratch, JS_REGEXP_TYPE);
+ __ CompareObjectType(input, input, scratch, JS_REGEXP_TYPE);
__ b(eq, false_label);
// Check for undetectable objects => false.
__ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset));
__ tst(ip, Operand(1 << Map::kIsUndetectable));
__ b(ne, false_label);
// Check for JS objects => true.
- __ CompareInstanceType(input, core_scratch, FIRST_JS_OBJECT_TYPE);
+ __ CompareInstanceType(input, scratch, FIRST_JS_OBJECT_TYPE);
__ b(lo, false_label);
- __ CompareInstanceType(input, core_scratch, LAST_JS_OBJECT_TYPE);
+ __ CompareInstanceType(input, scratch, LAST_JS_OBJECT_TYPE);
final_branch_condition = ls;
} else {
diff --git a/src/arm/lithium-codegen-arm.h b/src/arm/lithium-codegen-arm.h
index 541a6996..608efa9e 100644
--- a/src/arm/lithium-codegen-arm.h
+++ b/src/arm/lithium-codegen-arm.h
@@ -103,6 +103,8 @@ class LCodeGen BASE_EMBEDDED {
HGraph* graph() const { return chunk_->graph(); }
MacroAssembler* masm() const { return masm_; }
+ Register scratch0() { return r9; }
+
int GetNextEmittedBlock(int block);
LInstruction* GetNextInstruction();
diff --git a/src/ast.cc b/src/ast.cc
index 895ab677..1a6e7681 100644
--- a/src/ast.cc
+++ b/src/ast.cc
@@ -517,6 +517,9 @@ void Property::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
if (key()->IsPropertyName()) {
if (oracle->LoadIsBuiltin(this, Builtins::LoadIC_ArrayLength)) {
is_array_length_ = true;
+ } else if (oracle->LoadIsBuiltin(this,
+ Builtins::LoadIC_FunctionPrototype)) {
+ is_function_prototype_ = true;
} else {
Literal* lit_key = key()->AsLiteral();
ASSERT(lit_key != NULL && lit_key->handle()->IsString());
diff --git a/src/ast.h b/src/ast.h
index ed447e34..ba422fda 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -1208,6 +1208,7 @@ class Property: public Expression {
is_monomorphic_(false),
receiver_types_(NULL),
is_array_length_(false),
+ is_function_prototype_(false),
is_arguments_access_(false) { }
DECLARE_NODE_TYPE(Property)
@@ -1220,6 +1221,8 @@ class Property: public Expression {
int position() const { return pos_; }
bool is_synthetic() const { return type_ == SYNTHETIC; }
+ bool IsFunctionPrototype() const { return is_function_prototype_; }
+
// Marks that this is actually an argument rewritten to a keyed property
// accessing the argument through the arguments shadow object.
void set_is_arguments_access(bool is_arguments_access) {
@@ -1249,6 +1252,7 @@ class Property: public Expression {
bool is_monomorphic_;
ZoneMapList* receiver_types_;
bool is_array_length_;
+ bool is_function_prototype_;
bool is_arguments_access_;
Handle<Map> monomorphic_receiver_type_;
@@ -1391,7 +1395,7 @@ class BinaryOperation: public Expression {
: op_(op), left_(left), right_(right), pos_(pos), is_smi_only_(false) {
ASSERT(Token::IsBinaryOp(op));
right_id_ = (op == Token::AND || op == Token::OR)
- ? GetNextId()
+ ? static_cast<int>(GetNextId())
: AstNode::kNoNumber;
}
diff --git a/src/builtins.cc b/src/builtins.cc
index 21381f15..0c76f694 100644
--- a/src/builtins.cc
+++ b/src/builtins.cc
@@ -380,7 +380,7 @@ static inline MaybeObject* EnsureJSArrayWithWritableFastElements(
Object* receiver) {
if (!receiver->IsJSArray()) return NULL;
JSArray* array = JSArray::cast(receiver);
- HeapObject* elms = HeapObject::cast(array->elements());
+ HeapObject* elms = array->elements();
if (elms->map() == Heap::fixed_array_map()) return elms;
if (elms->map() == Heap::fixed_cow_array_map()) {
return array->EnsureWritableFastElements();
@@ -613,42 +613,38 @@ BUILTIN(ArraySlice) {
Object* receiver = *args.receiver();
FixedArray* elms;
int len = -1;
- { MaybeObject* maybe_elms_obj =
- EnsureJSArrayWithWritableFastElements(receiver);
- Object* elms_obj;
- if (maybe_elms_obj != NULL && maybe_elms_obj->ToObject(&elms_obj)) {
- if (!IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) {
- return CallJsBuiltin("ArraySlice", args);
- }
- elms = FixedArray::cast(elms_obj);
- JSArray* array = JSArray::cast(receiver);
- ASSERT(array->HasFastElements());
+ if (receiver->IsJSArray()) {
+ JSArray* array = JSArray::cast(receiver);
+ if (!array->HasFastElements() ||
+ !IsJSArrayFastElementMovingAllowed(array)) {
+ return CallJsBuiltin("ArraySlice", args);
+ }
- len = Smi::cast(array->length())->value();
- } else {
- // Array.slice(arguments, ...) is quite a common idiom (notably more
- // than 50% of invocations in Web apps). Treat it in C++ as well.
- Map* arguments_map =
- Top::context()->global_context()->arguments_boilerplate()->map();
-
- bool is_arguments_object_with_fast_elements =
- receiver->IsJSObject()
- && JSObject::cast(receiver)->map() == arguments_map
- && JSObject::cast(receiver)->HasFastElements();
- if (!is_arguments_object_with_fast_elements) {
- return CallJsBuiltin("ArraySlice", args);
- }
- elms = FixedArray::cast(JSObject::cast(receiver)->elements());
- len = elms->length();
+ elms = FixedArray::cast(array->elements());
+ len = Smi::cast(array->length())->value();
+ } else {
+ // Array.slice(arguments, ...) is quite a common idiom (notably more
+ // than 50% of invocations in Web apps). Treat it in C++ as well.
+ Map* arguments_map =
+ Top::context()->global_context()->arguments_boilerplate()->map();
+
+ bool is_arguments_object_with_fast_elements =
+ receiver->IsJSObject()
+ && JSObject::cast(receiver)->map() == arguments_map
+ && JSObject::cast(receiver)->HasFastElements();
+ if (!is_arguments_object_with_fast_elements) {
+ return CallJsBuiltin("ArraySlice", args);
+ }
+ elms = FixedArray::cast(JSObject::cast(receiver)->elements());
+ len = elms->length();
#ifdef DEBUG
- // Arguments object by construction should have no holes, check it.
- if (FLAG_enable_slow_asserts) {
- for (int i = 0; i < len; i++) {
- ASSERT(elms->get(i) != Heap::the_hole_value());
- }
+ // Arguments object by construction should have no holes, check it.
+ if (FLAG_enable_slow_asserts) {
+ for (int i = 0; i < len; i++) {
+ ASSERT(elms->get(i) != Heap::the_hole_value());
}
-#endif
}
+#endif
}
ASSERT(len >= 0);
int n_arguments = args.length() - 1;
diff --git a/src/cpu-profiler.cc b/src/cpu-profiler.cc
index f13c0eef..fcf539f3 100644
--- a/src/cpu-profiler.cc
+++ b/src/cpu-profiler.cc
@@ -47,7 +47,8 @@ static const int kTickSamplesBufferChunksCount = 16;
ProfilerEventsProcessor::ProfilerEventsProcessor(ProfileGenerator* generator)
- : generator_(generator),
+ : Thread("v8:ProfEvntProc"),
+ generator_(generator),
running_(true),
ticks_buffer_(sizeof(TickSampleEventRecord),
kTickSamplesBufferChunkSize,
diff --git a/src/d8-debug.cc b/src/d8-debug.cc
index 5f3ed766..8a3886c6 100644
--- a/src/d8-debug.cc
+++ b/src/d8-debug.cc
@@ -34,12 +34,21 @@
namespace v8 {
-void PrintPrompt() {
- printf("dbg> ");
+static bool was_running = true;
+
+void PrintPrompt(bool is_running) {
+ const char* prompt = is_running? "> " : "dbg> ";
+ was_running = is_running;
+ printf("%s", prompt);
fflush(stdout);
}
+void PrintPrompt() {
+ PrintPrompt(was_running);
+}
+
+
void HandleDebugEvent(DebugEvent event,
Handle<Object> exec_state,
Handle<Object> event_data,
@@ -91,7 +100,7 @@ void HandleDebugEvent(DebugEvent event,
bool running = false;
while (!running) {
char command[kBufferSize];
- PrintPrompt();
+ PrintPrompt(running);
char* str = fgets(command, kBufferSize, stdin);
if (str == NULL) break;
@@ -284,7 +293,9 @@ void RemoteDebugger::HandleMessageReceived(char* message) {
} else {
printf("???\n");
}
- PrintPrompt();
+
+ bool is_running = details->Get(String::New("running"))->ToBoolean()->Value();
+ PrintPrompt(is_running);
}
diff --git a/src/d8-debug.h b/src/d8-debug.h
index c7acc2f7..4e33e6f4 100644
--- a/src/d8-debug.h
+++ b/src/d8-debug.h
@@ -98,7 +98,8 @@ class RemoteDebugger {
class ReceiverThread: public i::Thread {
public:
explicit ReceiverThread(RemoteDebugger* remote_debugger)
- : remote_debugger_(remote_debugger) {}
+ : Thread("d8:ReceiverThrd"),
+ remote_debugger_(remote_debugger) {}
~ReceiverThread() {}
void Run();
@@ -112,7 +113,8 @@ class ReceiverThread: public i::Thread {
class KeyboardThread: public i::Thread {
public:
explicit KeyboardThread(RemoteDebugger* remote_debugger)
- : remote_debugger_(remote_debugger) {}
+ : Thread("d8:KeyboardThrd"),
+ remote_debugger_(remote_debugger) {}
~KeyboardThread() {}
void Run();
diff --git a/src/d8.cc b/src/d8.cc
index 5a1e63a7..f0da7ac8 100644
--- a/src/d8.cc
+++ b/src/d8.cc
@@ -599,7 +599,8 @@ void Shell::RunShell() {
class ShellThread : public i::Thread {
public:
ShellThread(int no, i::Vector<const char> files)
- : no_(no), files_(files) { }
+ : Thread("d8:ShellThread"),
+ no_(no), files_(files) { }
virtual void Run();
private:
int no_;
diff --git a/src/data-flow.h b/src/data-flow.h
index 6e2230c6..79d760f5 100644
--- a/src/data-flow.h
+++ b/src/data-flow.h
@@ -112,10 +112,13 @@ class BitVector: public ZoneObject {
}
void CopyFrom(const BitVector& other) {
- ASSERT(other.length() == length());
- for (int i = 0; i < data_length_; i++) {
+ ASSERT(other.length() <= length());
+ for (int i = 0; i < other.data_length_; i++) {
data_[i] = other.data_[i];
}
+ for (int i = other.data_length_; i < data_length_; i++) {
+ data_[i] = 0;
+ }
}
bool Contains(int i) const {
diff --git a/src/date.js b/src/date.js
index bc70327c..9eb607c7 100644
--- a/src/date.js
+++ b/src/date.js
@@ -1000,7 +1000,7 @@ function DateToISOString() {
function DateToJSON(key) {
var o = ToObject(this);
var tv = DefaultNumber(o);
- if (IS_NUMBER(tv) && !$isFinite(tv)) {
+ if (IS_NUMBER(tv) && !NUMBER_IS_FINITE(tv)) {
return null;
}
return o.toISOString();
diff --git a/src/debug-agent.h b/src/debug-agent.h
index 36479943..4cedb831 100644
--- a/src/debug-agent.h
+++ b/src/debug-agent.h
@@ -44,7 +44,8 @@ class DebuggerAgentSession;
class DebuggerAgent: public Thread {
public:
explicit DebuggerAgent(const char* name, int port)
- : name_(StrDup(name)), port_(port),
+ : Thread(name),
+ name_(StrDup(name)), port_(port),
server_(OS::CreateSocket()), terminate_(false),
session_access_(OS::CreateMutex()), session_(NULL),
terminate_now_(OS::CreateSemaphore(0)),
@@ -90,7 +91,8 @@ class DebuggerAgent: public Thread {
class DebuggerAgentSession: public Thread {
public:
DebuggerAgentSession(DebuggerAgent* agent, Socket* client)
- : agent_(agent), client_(client) {}
+ : Thread("v8:DbgAgntSessn"),
+ agent_(agent), client_(client) {}
void DebuggerMessage(Vector<uint16_t> message);
void Shutdown();
diff --git a/src/debug.cc b/src/debug.cc
index ca3c1db7..c41e545c 100644
--- a/src/debug.cc
+++ b/src/debug.cc
@@ -3037,7 +3037,8 @@ void LockingCommandMessageQueue::Clear() {
MessageDispatchHelperThread::MessageDispatchHelperThread()
- : sem_(OS::CreateSemaphore(0)), mutex_(OS::CreateMutex()),
+ : Thread("v8:MsgDispHelpr"),
+ sem_(OS::CreateSemaphore(0)), mutex_(OS::CreateMutex()),
already_signalled_(false) {
}
diff --git a/src/deoptimizer.cc b/src/deoptimizer.cc
index dd70baaa..185ff922 100644
--- a/src/deoptimizer.cc
+++ b/src/deoptimizer.cc
@@ -309,9 +309,9 @@ void Deoptimizer::TearDown() {
}
-unsigned Deoptimizer::GetOutputInfo(DeoptimizationOutputData* data,
- unsigned id,
- SharedFunctionInfo* shared) {
+int Deoptimizer::GetOutputInfo(DeoptimizationOutputData* data,
+ unsigned id,
+ SharedFunctionInfo* shared) {
// TODO(kasperl): For now, we do a simple linear search for the PC
// offset associated with the given node id. This should probably be
// changed to a binary search.
diff --git a/src/deoptimizer.h b/src/deoptimizer.h
index 2d7dfc89..f9bf280e 100644
--- a/src/deoptimizer.h
+++ b/src/deoptimizer.h
@@ -145,9 +145,9 @@ class Deoptimizer : public Malloced {
static Address GetDeoptimizationEntry(int id, BailoutType type);
static int GetDeoptimizationId(Address addr, BailoutType type);
- static unsigned GetOutputInfo(DeoptimizationOutputData* data,
- unsigned node_id,
- SharedFunctionInfo* shared);
+ static int GetOutputInfo(DeoptimizationOutputData* data,
+ unsigned node_id,
+ SharedFunctionInfo* shared);
static void Setup();
static void TearDown();
diff --git a/src/factory.cc b/src/factory.cc
index 83af447d..2bc878cc 100644
--- a/src/factory.cc
+++ b/src/factory.cc
@@ -99,6 +99,14 @@ Handle<String> Factory::LookupSymbol(Vector<const char> string) {
CALL_HEAP_FUNCTION(Heap::LookupSymbol(string), String);
}
+Handle<String> Factory::LookupAsciiSymbol(Vector<const char> string) {
+ CALL_HEAP_FUNCTION(Heap::LookupAsciiSymbol(string), String);
+}
+
+Handle<String> Factory::LookupTwoByteSymbol(Vector<const uc16> string) {
+ CALL_HEAP_FUNCTION(Heap::LookupTwoByteSymbol(string), String);
+}
+
Handle<String> Factory::NewStringFromAscii(Vector<const char> string,
PretenureFlag pretenure) {
diff --git a/src/factory.h b/src/factory.h
index b7a2882e..a5e15912 100644
--- a/src/factory.h
+++ b/src/factory.h
@@ -61,6 +61,8 @@ class Factory : public AllStatic {
PretenureFlag pretenure);
static Handle<String> LookupSymbol(Vector<const char> str);
+ static Handle<String> LookupAsciiSymbol(Vector<const char> str);
+ static Handle<String> LookupTwoByteSymbol(Vector<const uc16> str);
static Handle<String> LookupAsciiSymbol(const char* str) {
return LookupSymbol(CStrVector(str));
}
diff --git a/src/flag-definitions.h b/src/flag-definitions.h
index f160a85a..2b24d13c 100644
--- a/src/flag-definitions.h
+++ b/src/flag-definitions.h
@@ -122,7 +122,6 @@ DEFINE_bool(trace_inlining, false, "trace inlining decisions")
DEFINE_bool(trace_alloc, false, "trace register allocator")
DEFINE_bool(trace_range, false, "trace range analysis")
DEFINE_bool(trace_gvn, false, "trace global value numbering")
-DEFINE_bool(trace_environment, false, "trace lithium environments")
DEFINE_bool(trace_representation, false, "trace representation types")
DEFINE_bool(stress_pointer_maps, false, "pointer map for every instruction")
DEFINE_bool(stress_environments, false, "environment for every instruction")
diff --git a/src/globals.h b/src/globals.h
index 35156ae6..9b24bf63 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -181,10 +181,6 @@ typedef byte* Address;
#define USING_BSD_ABI
#endif
-// Code-point values in Unicode 4.0 are 21 bits wide.
-typedef uint16_t uc16;
-typedef int32_t uc32;
-
// -----------------------------------------------------------------------------
// Constants
@@ -228,6 +224,15 @@ const int kBinary32MinExponent = 0x01;
const int kBinary32MantissaBits = 23;
const int kBinary32ExponentShift = 23;
+// ASCII/UC16 constants
+// Code-point values in Unicode 4.0 are 21 bits wide.
+typedef uint16_t uc16;
+typedef int32_t uc32;
+const int kASCIISize = kCharSize;
+const int kUC16Size = sizeof(uc16); // NOLINT
+const uc32 kMaxAsciiCharCode = 0x7f;
+const uint32_t kMaxAsciiCharCodeU = 0x7fu;
+
// The expression OFFSET_OF(type, field) computes the byte-offset
// of the specified field relative to the containing type. This
diff --git a/src/heap-inl.h b/src/heap-inl.h
index ef839988..e7700e9c 100644
--- a/src/heap-inl.h
+++ b/src/heap-inl.h
@@ -40,6 +40,19 @@ int Heap::MaxObjectSizeInPagedSpace() {
}
+MaybeObject* Heap::AllocateStringFromUtf8(Vector<const char> str,
+ PretenureFlag pretenure) {
+ // Check for ASCII first since this is the common case.
+ if (String::IsAscii(str.start(), str.length())) {
+ // If the string is ASCII, we do not need to convert the characters
+ // since UTF8 is backwards compatible with ASCII.
+ return AllocateStringFromAscii(str, pretenure);
+ }
+ // Non-ASCII and we need to decode.
+ return AllocateStringFromUtf8Slow(str, pretenure);
+}
+
+
MaybeObject* Heap::AllocateSymbol(Vector<const char> str,
int chars,
uint32_t hash_field) {
@@ -49,6 +62,71 @@ MaybeObject* Heap::AllocateSymbol(Vector<const char> str,
}
+MaybeObject* Heap::AllocateAsciiSymbol(Vector<const char> str,
+ uint32_t hash_field) {
+ if (str.length() > SeqAsciiString::kMaxLength) {
+ return Failure::OutOfMemoryException();
+ }
+ // Compute map and object size.
+ Map* map = ascii_symbol_map();
+ int size = SeqAsciiString::SizeFor(str.length());
+
+ // Allocate string.
+ Object* result;
+ { MaybeObject* maybe_result = (size > MaxObjectSizeInPagedSpace())
+ ? lo_space_->AllocateRaw(size)
+ : old_data_space_->AllocateRaw(size);
+ if (!maybe_result->ToObject(&result)) return maybe_result;
+ }
+
+ reinterpret_cast<HeapObject*>(result)->set_map(map);
+ // Set length and hash fields of the allocated string.
+ String* answer = String::cast(result);
+ answer->set_length(str.length());
+ answer->set_hash_field(hash_field);
+
+ ASSERT_EQ(size, answer->Size());
+
+ // Fill in the characters.
+ memcpy(answer->address() + SeqAsciiString::kHeaderSize,
+ str.start(), str.length());
+
+ return answer;
+}
+
+
+MaybeObject* Heap::AllocateTwoByteSymbol(Vector<const uc16> str,
+ uint32_t hash_field) {
+ if (str.length() > SeqTwoByteString::kMaxLength) {
+ return Failure::OutOfMemoryException();
+ }
+ // Compute map and object size.
+ Map* map = symbol_map();
+ int size = SeqTwoByteString::SizeFor(str.length());
+
+ // Allocate string.
+ Object* result;
+ { MaybeObject* maybe_result = (size > MaxObjectSizeInPagedSpace())
+ ? lo_space_->AllocateRaw(size)
+ : old_data_space_->AllocateRaw(size);
+ if (!maybe_result->ToObject(&result)) return maybe_result;
+ }
+
+ reinterpret_cast<HeapObject*>(result)->set_map(map);
+ // Set length and hash fields of the allocated string.
+ String* answer = String::cast(result);
+ answer->set_length(str.length());
+ answer->set_hash_field(hash_field);
+
+ ASSERT_EQ(size, answer->Size());
+
+ // Fill in the characters.
+ memcpy(answer->address() + SeqTwoByteString::kHeaderSize,
+ str.start(), str.length() * kUC16Size);
+
+ return answer;
+}
+
MaybeObject* Heap::CopyFixedArray(FixedArray* src) {
return CopyFixedArrayWithMap(src, src->map());
}
@@ -443,6 +521,10 @@ void Heap::SetLastScriptId(Object* last_script_id) {
CALL_AND_RETRY(FUNCTION_CALL, return, return)
+#define CALL_HEAP_FUNCTION_INLINE(FUNCTION_CALL) \
+ CALL_AND_RETRY(FUNCTION_CALL, break, break)
+
+
#ifdef DEBUG
inline bool Heap::allow_allocation(bool new_state) {
diff --git a/src/heap.cc b/src/heap.cc
index 1e999916..44229f09 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -2549,20 +2549,10 @@ MaybeObject* Heap::AllocateExternalStringFromTwoByte(
}
// For small strings we check whether the resource contains only
- // ascii characters. If yes, we use a different string map.
- bool is_ascii = true;
- if (length >= static_cast<size_t>(String::kMinNonFlatLength)) {
- is_ascii = false;
- } else {
- const uc16* data = resource->data();
- for (size_t i = 0; i < length; i++) {
- if (data[i] > String::kMaxAsciiCharCode) {
- is_ascii = false;
- break;
- }
- }
- }
-
+ // ASCII characters. If yes, we use a different string map.
+ static const size_t kAsciiCheckLengthLimit = 32;
+ bool is_ascii = length <= kAsciiCheckLengthLimit &&
+ String::IsAscii(resource->data(), static_cast<int>(length));
Map* map = is_ascii ?
Heap::external_string_with_ascii_data_map() : Heap::external_string_map();
Object* result;
@@ -3307,8 +3297,8 @@ MaybeObject* Heap::AllocateStringFromAscii(Vector<const char> string,
}
-MaybeObject* Heap::AllocateStringFromUtf8(Vector<const char> string,
- PretenureFlag pretenure) {
+MaybeObject* Heap::AllocateStringFromUtf8Slow(Vector<const char> string,
+ PretenureFlag pretenure) {
// V8 only supports characters in the Basic Multilingual Plane.
const uc32 kMaxSupportedChar = 0xFFFF;
// Count the number of characters in the UTF-8 string and check if
@@ -3317,17 +3307,11 @@ MaybeObject* Heap::AllocateStringFromUtf8(Vector<const char> string,
decoder(ScannerConstants::utf8_decoder());
decoder->Reset(string.start(), string.length());
int chars = 0;
- bool is_ascii = true;
while (decoder->has_more()) {
- uc32 r = decoder->GetNext();
- if (r > String::kMaxAsciiCharCode) is_ascii = false;
+ decoder->GetNext();
chars++;
}
- // If the string is ascii, we do not need to convert the characters
- // since UTF8 is backwards compatible with ascii.
- if (is_ascii) return AllocateStringFromAscii(string, pretenure);
-
Object* result;
{ MaybeObject* maybe_result = AllocateRawTwoByteString(chars, pretenure);
if (!maybe_result->ToObject(&result)) return maybe_result;
@@ -3348,11 +3332,8 @@ MaybeObject* Heap::AllocateStringFromUtf8(Vector<const char> string,
MaybeObject* Heap::AllocateStringFromTwoByte(Vector<const uc16> string,
PretenureFlag pretenure) {
// Check if the string is an ASCII string.
- int i = 0;
- while (i < string.length() && string[i] <= String::kMaxAsciiCharCode) i++;
-
MaybeObject* maybe_result;
- if (i == string.length()) { // It's an ASCII string.
+ if (String::IsAscii(string.start(), string.length())) {
maybe_result = AllocateRawAsciiString(string.length(), pretenure);
} else { // It's not an ASCII string.
maybe_result = AllocateRawTwoByteString(string.length(), pretenure);
@@ -4032,6 +4013,36 @@ MaybeObject* Heap::LookupSymbol(Vector<const char> string) {
}
+MaybeObject* Heap::LookupAsciiSymbol(Vector<const char> string) {
+ Object* symbol = NULL;
+ Object* new_table;
+ { MaybeObject* maybe_new_table =
+ symbol_table()->LookupAsciiSymbol(string, &symbol);
+ if (!maybe_new_table->ToObject(&new_table)) return maybe_new_table;
+ }
+ // Can't use set_symbol_table because SymbolTable::cast knows that
+ // SymbolTable is a singleton and checks for identity.
+ roots_[kSymbolTableRootIndex] = new_table;
+ ASSERT(symbol != NULL);
+ return symbol;
+}
+
+
+MaybeObject* Heap::LookupTwoByteSymbol(Vector<const uc16> string) {
+ Object* symbol = NULL;
+ Object* new_table;
+ { MaybeObject* maybe_new_table =
+ symbol_table()->LookupTwoByteSymbol(string, &symbol);
+ if (!maybe_new_table->ToObject(&new_table)) return maybe_new_table;
+ }
+ // Can't use set_symbol_table because SymbolTable::cast knows that
+ // SymbolTable is a singleton and checks for identity.
+ roots_[kSymbolTableRootIndex] = new_table;
+ ASSERT(symbol != NULL);
+ return symbol;
+}
+
+
MaybeObject* Heap::LookupSymbol(String* string) {
if (string->IsSymbol()) return string;
Object* symbol = NULL;
diff --git a/src/heap.h b/src/heap.h
index 18a4afbe..3ceefd80 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -412,7 +412,10 @@ class Heap : public AllStatic {
MUST_USE_RESULT static MaybeObject* AllocateStringFromAscii(
Vector<const char> str,
PretenureFlag pretenure = NOT_TENURED);
- MUST_USE_RESULT static MaybeObject* AllocateStringFromUtf8(
+ MUST_USE_RESULT static inline MaybeObject* AllocateStringFromUtf8(
+ Vector<const char> str,
+ PretenureFlag pretenure = NOT_TENURED);
+ MUST_USE_RESULT static MaybeObject* AllocateStringFromUtf8Slow(
Vector<const char> str,
PretenureFlag pretenure = NOT_TENURED);
MUST_USE_RESULT static MaybeObject* AllocateStringFromTwoByte(
@@ -428,6 +431,14 @@ class Heap : public AllStatic {
int chars,
uint32_t hash_field);
+ MUST_USE_RESULT static inline MaybeObject* AllocateAsciiSymbol(
+ Vector<const char> str,
+ uint32_t hash_field);
+
+ MUST_USE_RESULT static inline MaybeObject* AllocateTwoByteSymbol(
+ Vector<const uc16> str,
+ uint32_t hash_field);
+
MUST_USE_RESULT static MaybeObject* AllocateInternalSymbol(
unibrow::CharacterStream* buffer, int chars, uint32_t hash_field);
@@ -683,6 +694,9 @@ class Heap : public AllStatic {
// failed.
// Please note this function does not perform a garbage collection.
MUST_USE_RESULT static MaybeObject* LookupSymbol(Vector<const char> str);
+ MUST_USE_RESULT static MaybeObject* LookupAsciiSymbol(Vector<const char> str);
+ MUST_USE_RESULT static MaybeObject* LookupTwoByteSymbol(
+ Vector<const uc16> str);
MUST_USE_RESULT static MaybeObject* LookupAsciiSymbol(const char* str) {
return LookupSymbol(CStrVector(str));
}
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index cbbe8fcc..a3c23c67 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -76,7 +76,6 @@ class LChunkBuilder;
// HLoadKeyed
// HLoadKeyedFastElement
// HLoadKeyedGeneric
-// HLoadNamedGeneric
// HPower
// HStoreNamed
// HStoreNamedField
@@ -119,7 +118,6 @@ class LChunkBuilder;
// HStoreKeyedFastElement
// HStoreKeyedGeneric
// HUnaryOperation
-// HArrayLength
// HBitNot
// HChange
// HCheckFunction
@@ -129,9 +127,13 @@ class LChunkBuilder;
// HCheckPrototypeMaps
// HCheckSmi
// HDeleteProperty
+// HFixedArrayLength
+// HJSArrayLength
// HLoadElements
// HTypeofIs
// HLoadNamedField
+// HLoadNamedGeneric
+// HLoadFunctionPrototype
// HPushArgument
// HTypeof
// HUnaryMathOperation
@@ -170,7 +172,6 @@ class LChunkBuilder;
V(ArgumentsElements) \
V(ArgumentsLength) \
V(ArgumentsObject) \
- V(ArrayLength) \
V(ArrayLiteral) \
V(BitAnd) \
V(BitNot) \
@@ -203,6 +204,7 @@ class LChunkBuilder;
V(Deoptimize) \
V(Div) \
V(EnterInlined) \
+ V(FixedArrayLength) \
V(FunctionLiteral) \
V(GlobalObject) \
V(GlobalReceiver) \
@@ -213,6 +215,7 @@ class LChunkBuilder;
V(IsSmi) \
V(HasInstanceType) \
V(HasCachedArrayIndex) \
+ V(JSArrayLength) \
V(ClassOfTest) \
V(LeaveInlined) \
V(LoadElements) \
@@ -221,6 +224,7 @@ class LChunkBuilder;
V(LoadKeyedGeneric) \
V(LoadNamedField) \
V(LoadNamedGeneric) \
+ V(LoadFunctionPrototype) \
V(Mod) \
V(Mul) \
V(ObjectLiteral) \
@@ -256,6 +260,7 @@ class LChunkBuilder;
V(GlobalVars) \
V(Maps) \
V(ArrayLengths) \
+ V(FunctionPrototypes) \
V(OsrEntries)
#define DECLARE_INSTRUCTION(type) \
@@ -905,6 +910,9 @@ class HCompareMapAndBranch: public HUnaryControlInstruction {
virtual HBasicBlock* FirstSuccessor() const { return true_destination_; }
virtual HBasicBlock* SecondSuccessor() const { return false_destination_; }
+ HBasicBlock* true_destination() const { return true_destination_; }
+ HBasicBlock* false_destination() const { return false_destination_; }
+
virtual void PrintDataTo(StringStream* stream) const;
Handle<Map> map() const { return map_; }
@@ -1015,10 +1023,10 @@ class HChange: public HUnaryOperation {
class HSimulate: public HInstruction {
public:
- HSimulate(int ast_id, int pop_count, int environment_height)
+ HSimulate(int ast_id, int pop_count, int environment_length)
: ast_id_(ast_id),
pop_count_(pop_count),
- environment_height_(environment_height),
+ environment_length_(environment_length),
values_(2),
assigned_indexes_(2) {}
virtual ~HSimulate() {}
@@ -1032,7 +1040,7 @@ class HSimulate: public HInstruction {
ast_id_ = id;
}
- int environment_height() const { return environment_height_; }
+ int environment_length() const { return environment_length_; }
int pop_count() const { return pop_count_; }
const ZoneList<HValue*>* values() const { return &values_; }
int GetAssignedIndexAt(int index) const {
@@ -1074,7 +1082,7 @@ class HSimulate: public HInstruction {
}
int ast_id_;
int pop_count_;
- int environment_height_;
+ int environment_length_;
ZoneList<HValue*> values_;
ZoneList<int> assigned_indexes_;
};
@@ -1336,9 +1344,9 @@ class HCallRuntime: public HCall {
};
-class HArrayLength: public HUnaryOperation {
+class HJSArrayLength: public HUnaryOperation {
public:
- explicit HArrayLength(HValue* value) : HUnaryOperation(value) {
+ explicit HJSArrayLength(HValue* value) : HUnaryOperation(value) {
// The length of an array is stored as a tagged value in the array
// object. It is guaranteed to be 32 bit integer, but it can be
// represented as either a smi or heap number.
@@ -1351,7 +1359,23 @@ class HArrayLength: public HUnaryOperation {
return Representation::Tagged();
}
- DECLARE_CONCRETE_INSTRUCTION(ArrayLength, "array_length")
+ DECLARE_CONCRETE_INSTRUCTION(JSArrayLength, "js_array_length")
+};
+
+
+class HFixedArrayLength: public HUnaryOperation {
+ public:
+ explicit HFixedArrayLength(HValue* value) : HUnaryOperation(value) {
+ set_representation(Representation::Tagged());
+ SetFlag(kDependsOnArrayLengths);
+ SetFlag(kUseGVN);
+ }
+
+ virtual Representation RequiredInputRepresentation(int index) const {
+ return Representation::Tagged();
+ }
+
+ DECLARE_CONCRETE_INSTRUCTION(FixedArrayLength, "fixed_array_length")
};
@@ -1766,6 +1790,8 @@ class HConstant: public HInstruction {
Handle<Object> handle() const { return handle_; }
+ bool InOldSpace() const { return !Heap::InNewSpace(*handle_); }
+
virtual bool EmitAtUses() const { return !representation().IsDouble(); }
virtual void PrintDataTo(StringStream* stream) const;
virtual HType CalculateInferredType() const;
@@ -2617,6 +2643,27 @@ class HLoadNamedGeneric: public HUnaryOperation {
};
+class HLoadFunctionPrototype: public HUnaryOperation {
+ public:
+ explicit HLoadFunctionPrototype(HValue* function)
+ : HUnaryOperation(function) {
+ set_representation(Representation::Tagged());
+ SetFlagMask(kDependsOnFunctionPrototypes);
+ }
+
+ HValue* function() const { return OperandAt(0); }
+
+ virtual Representation RequiredInputRepresentation(int index) const {
+ return Representation::Tagged();
+ }
+
+ DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype, "load_function_prototype")
+
+ protected:
+ virtual bool DataEquals(HValue* other) const { return true; }
+};
+
+
class HLoadKeyed: public HBinaryOperation {
public:
HLoadKeyed(HValue* obj, HValue* key) : HBinaryOperation(obj, key) {
@@ -2663,6 +2710,12 @@ class HLoadKeyedGeneric: public HLoadKeyed {
};
+static inline bool StoringValueNeedsWriteBarrier(HValue* value) {
+ return !value->type().IsSmi() &&
+ !(value->IsConstant() && HConstant::cast(value)->InOldSpace());
+}
+
+
class HStoreNamed: public HBinaryOperation {
public:
HStoreNamed(HValue* obj, Handle<Object> name, HValue* val)
@@ -2680,6 +2733,10 @@ class HStoreNamed: public HBinaryOperation {
HValue* value() const { return OperandAt(1); }
void set_value(HValue* value) { SetOperandAt(1, value); }
+ bool NeedsWriteBarrier() const {
+ return StoringValueNeedsWriteBarrier(value());
+ }
+
DECLARE_INSTRUCTION(StoreNamed)
protected:
@@ -2760,6 +2817,10 @@ class HStoreKeyed: public HInstruction {
HValue* key() const { return OperandAt(1); }
HValue* value() const { return OperandAt(2); }
+ bool NeedsWriteBarrier() const {
+ return StoringValueNeedsWriteBarrier(value());
+ }
+
DECLARE_INSTRUCTION(StoreKeyed)
protected:
@@ -2779,10 +2840,6 @@ class HStoreKeyedFastElement: public HStoreKeyed {
SetFlag(kChangesArrayElements);
}
- bool NeedsWriteBarrier() const {
- return !value()->type().IsSmi();
- }
-
virtual Representation RequiredInputRepresentation(int index) const {
// The key is supposed to be Integer32.
return (index == 1) ? Representation::Integer32()
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index e34acd67..fbe4cd72 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -128,7 +128,7 @@ HSimulate* HBasicBlock::CreateSimulate(int id) {
int push_count = environment->push_count();
int pop_count = environment->pop_count();
- int length = environment->values()->length();
+ int length = environment->length();
HSimulate* instr = new HSimulate(id, pop_count, length);
for (int i = push_count - 1; i >= 0; --i) {
instr->AddPushedValue(environment->ExpressionStackAt(i));
@@ -222,7 +222,7 @@ void HBasicBlock::RegisterPredecessor(HBasicBlock* pred) {
ASSERT(IsLoopHeader() || first_ == NULL);
HEnvironment* incoming_env = pred->last_environment();
if (IsLoopHeader()) {
- ASSERT(phis()->length() == incoming_env->values()->length());
+ ASSERT(phis()->length() == incoming_env->length());
for (int i = 0; i < phis_.length(); ++i) {
phis_[i]->AddInput(incoming_env->values()->at(i));
}
@@ -1982,7 +1982,7 @@ AstContext::AstContext(HGraphBuilder* owner, Expression::Context kind)
: owner_(owner), kind_(kind), outer_(owner->ast_context()) {
owner->set_ast_context(this); // Push.
#ifdef DEBUG
- original_count_ = owner->environment()->total_count();
+ original_length_ = owner->environment()->length();
#endif
}
@@ -1995,14 +1995,14 @@ AstContext::~AstContext() {
EffectContext::~EffectContext() {
ASSERT(owner()->HasStackOverflow() ||
!owner()->subgraph()->HasExit() ||
- owner()->environment()->total_count() == original_count_);
+ owner()->environment()->length() == original_length_);
}
ValueContext::~ValueContext() {
ASSERT(owner()->HasStackOverflow() ||
!owner()->subgraph()->HasExit() ||
- owner()->environment()->total_count() == original_count_ + 1);
+ owner()->environment()->length() == original_length_ + 1);
}
@@ -2343,7 +2343,7 @@ void HGraphBuilder::SetupScope(Scope* scope) {
}
// Set the initial values of stack-allocated locals.
- for (int i = count; i < environment()->values()->length(); ++i) {
+ for (int i = count; i < environment()->length(); ++i) {
environment()->Bind(i, undefined_constant);
}
@@ -2702,7 +2702,7 @@ void HSubgraph::PreProcessOsrEntry(IterationStatement* statement) {
int osr_entry_id = statement->OsrEntryId();
// We want the correct environment at the OsrEntry instruction. Build
// it explicitly. The expression stack should be empty.
- int count = osr_entry->last_environment()->total_count();
+ int count = osr_entry->last_environment()->length();
ASSERT(count == (osr_entry->last_environment()->parameter_count() +
osr_entry->last_environment()->local_count()));
for (int i = 0; i < count; ++i) {
@@ -3103,8 +3103,15 @@ HBasicBlock* HGraphBuilder::BuildTypeSwitch(ZoneMapList* maps,
// this basic block the current basic block.
HBasicBlock* join_block = graph_->CreateBasicBlock();
for (int i = 0; i < subgraphs->length(); ++i) {
- if (subgraphs->at(i)->HasExit()) {
- subgraphs->at(i)->exit_block()->Goto(join_block);
+ HSubgraph* subgraph = subgraphs->at(i);
+ if (subgraph->HasExit()) {
+ // In an effect context the value of the type switch is not needed.
+ // There is no need to merge it at the join block only to discard it.
+ HBasicBlock* subgraph_exit = subgraph->exit_block();
+ if (ast_context()->IsEffect()) {
+ subgraph_exit->last_environment()->Drop(1);
+ }
+ subgraph_exit->Goto(join_block);
}
}
@@ -3242,7 +3249,8 @@ void HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr,
Push(value);
instr->set_position(expr->position());
AddInstruction(instr);
- if (instr->HasSideEffects()) AddSimulate(expr->id());
+ if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId());
+ ast_context()->ReturnValue(Pop());
} else {
// Build subgraph for generic store through IC.
{
@@ -3260,11 +3268,14 @@ void HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr,
}
HBasicBlock* new_exit_block =
- BuildTypeSwitch(&maps, &subgraphs, object, expr->AssignmentId());
+ BuildTypeSwitch(&maps, &subgraphs, object, expr->id());
subgraph()->set_exit_block(new_exit_block);
+ // In an effect context, we did not materialized the value in the
+ // predecessor environments so there's no need to handle it here.
+ if (subgraph()->HasExit() && !ast_context()->IsEffect()) {
+ ast_context()->ReturnValue(Pop());
+ }
}
-
- if (subgraph()->HasExit()) ast_context()->ReturnValue(Pop());
}
@@ -3548,8 +3559,7 @@ void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr,
if (maps.length() == 0) {
HInstruction* instr = BuildLoadNamedGeneric(object, expr);
instr->set_position(expr->position());
- PushAndAdd(instr);
- if (instr->HasSideEffects()) AddSimulate(expr->id());
+ ast_context()->ReturnInstruction(instr, expr->id());
} else {
// Build subgraph for generic load through IC.
{
@@ -3568,9 +3578,12 @@ void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr,
HBasicBlock* new_exit_block =
BuildTypeSwitch(&maps, &subgraphs, object, expr->id());
subgraph()->set_exit_block(new_exit_block);
+ // In an effect context, we did not materialized the value in the
+ // predecessor environments so there's no need to handle it here.
+ if (subgraph()->HasExit() && !ast_context()->IsEffect()) {
+ ast_context()->ReturnValue(Pop());
+ }
}
-
- if (subgraph()->HasExit()) ast_context()->ReturnValue(Pop());
}
@@ -3643,9 +3656,18 @@ HInstruction* HGraphBuilder::BuildLoadKeyedFastElement(HValue* object,
Handle<Map> map = expr->GetMonomorphicReceiverType();
ASSERT(map->has_fast_elements());
AddInstruction(new HCheckMap(object, map));
- HInstruction* elements = AddInstruction(new HLoadElements(object));
- HInstruction* length = AddInstruction(new HArrayLength(elements));
- AddInstruction(new HBoundsCheck(key, length));
+ bool is_array = (map->instance_type() == JS_ARRAY_TYPE);
+ HLoadElements* elements = new HLoadElements(object);
+ HInstruction* length = NULL;
+ if (is_array) {
+ length = AddInstruction(new HJSArrayLength(object));
+ AddInstruction(new HBoundsCheck(key, length));
+ AddInstruction(elements);
+ } else {
+ AddInstruction(elements);
+ length = AddInstruction(new HFixedArrayLength(elements));
+ AddInstruction(new HBoundsCheck(key, length));
+ }
return new HLoadKeyedFastElement(elements, key);
}
@@ -3671,9 +3693,9 @@ HInstruction* HGraphBuilder::BuildStoreKeyedFastElement(HValue* object,
bool is_array = (map->instance_type() == JS_ARRAY_TYPE);
HInstruction* length = NULL;
if (is_array) {
- length = AddInstruction(new HArrayLength(object));
+ length = AddInstruction(new HJSArrayLength(object));
} else {
- length = AddInstruction(new HArrayLength(elements));
+ length = AddInstruction(new HFixedArrayLength(elements));
}
AddInstruction(new HBoundsCheck(key, length));
return new HStoreKeyedFastElement(elements, key, val);
@@ -3720,7 +3742,13 @@ void HGraphBuilder::VisitProperty(Property* expr) {
if (expr->IsArrayLength()) {
HValue* array = Pop();
AddInstruction(new HCheckNonSmi(array));
- instr = new HArrayLength(array);
+ AddInstruction(new HCheckInstanceType(array, JS_ARRAY_TYPE, JS_ARRAY_TYPE));
+ instr = new HJSArrayLength(array);
+
+ } else if (expr->IsFunctionPrototype()) {
+ HValue* function = Pop();
+ AddInstruction(new HCheckNonSmi(function));
+ instr = new HLoadFunctionPrototype(function);
} else if (expr->key()->IsPropertyName()) {
Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
@@ -3841,7 +3869,11 @@ void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr,
HBasicBlock* new_exit_block =
BuildTypeSwitch(&maps, &subgraphs, receiver, expr->id());
subgraph()->set_exit_block(new_exit_block);
- if (new_exit_block != NULL) ast_context()->ReturnValue(Pop());
+ // In an effect context, we did not materialized the value in the
+ // predecessor environments so there's no need to handle it here.
+ if (new_exit_block != NULL && !ast_context()->IsEffect()) {
+ ast_context()->ReturnValue(Pop());
+ }
}
}
@@ -4854,7 +4886,9 @@ void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
switch (op) {
case Token::EQ:
case Token::EQ_STRICT: {
+ AddInstruction(new HCheckNonSmi(left));
AddInstruction(HCheckInstanceType::NewIsJSObjectOrJSFunction(left));
+ AddInstruction(new HCheckNonSmi(right));
AddInstruction(HCheckInstanceType::NewIsJSObjectOrJSFunction(right));
instr = new HCompareJSObjectEq(left, right);
break;
@@ -5262,6 +5296,19 @@ void HEnvironment::Initialize(int parameter_count,
}
+void HEnvironment::Initialize(const HEnvironment* other) {
+ closure_ = other->closure();
+ values_.AddAll(other->values_);
+ assigned_variables_.AddAll(other->assigned_variables_);
+ parameter_count_ = other->parameter_count_;
+ local_count_ = other->local_count_;
+ if (other->outer_ != NULL) outer_ = other->outer_->Copy(); // Deep copy.
+ pop_count_ = other->pop_count_;
+ push_count_ = other->push_count_;
+ ast_id_ = other->ast_id_;
+}
+
+
void HEnvironment::AddIncomingEdge(HBasicBlock* block, HEnvironment* other) {
ASSERT(!block->IsLoopHeader());
ASSERT(values_.length() == other->values_.length());
@@ -5292,26 +5339,45 @@ void HEnvironment::AddIncomingEdge(HBasicBlock* block, HEnvironment* other) {
}
-void HEnvironment::Initialize(const HEnvironment* other) {
- closure_ = other->closure();
- values_.AddAll(other->values_);
- assigned_variables_.AddAll(other->assigned_variables_);
- parameter_count_ = other->parameter_count_;
- local_count_ = other->local_count_;
- if (other->outer_ != NULL) outer_ = other->outer_->Copy(); // Deep copy.
- pop_count_ = other->pop_count_;
- push_count_ = other->push_count_;
- ast_id_ = other->ast_id_;
+void HEnvironment::Bind(int index, HValue* value) {
+ ASSERT(value != NULL);
+ if (!assigned_variables_.Contains(index)) {
+ assigned_variables_.Add(index);
+ }
+ values_[index] = value;
}
-int HEnvironment::IndexFor(Variable* variable) const {
- Slot* slot = variable->AsSlot();
- ASSERT(slot != NULL && slot->IsStackAllocated());
- if (slot->type() == Slot::PARAMETER) {
- return slot->index() + 1;
- } else {
- return parameter_count_ + slot->index();
+bool HEnvironment::HasExpressionAt(int index) const {
+ return index >= parameter_count_ + local_count_;
+}
+
+
+bool HEnvironment::ExpressionStackIsEmpty() const {
+ int first_expression = parameter_count() + local_count();
+ ASSERT(length() >= first_expression);
+ return length() == first_expression;
+}
+
+
+void HEnvironment::SetExpressionStackAt(int index_from_top, HValue* value) {
+ int count = index_from_top + 1;
+ int index = values_.length() - count;
+ ASSERT(HasExpressionAt(index));
+ // The push count must include at least the element in question or else
+ // the new value will not be included in this environment's history.
+ if (push_count_ < count) {
+ // This is the same effect as popping then re-pushing 'count' elements.
+ pop_count_ += (count - push_count_);
+ push_count_ = count;
+ }
+ values_[index] = value;
+}
+
+
+void HEnvironment::Drop(int count) {
+ for (int i = 0; i < count; ++i) {
+ Pop();
}
}
@@ -5376,7 +5442,7 @@ HEnvironment* HEnvironment::CopyForInlining(Handle<JSFunction> target,
void HEnvironment::PrintTo(StringStream* stream) {
- for (int i = 0; i < total_count(); i++) {
+ for (int i = 0; i < length(); i++) {
if (i == 0) stream->Add("parameters\n");
if (i == parameter_count()) stream->Add("locals\n");
if (i == parameter_count() + local_count()) stream->Add("expressions");
diff --git a/src/hydrogen.h b/src/hydrogen.h
index ebabf3d2..872ae98e 100644
--- a/src/hydrogen.h
+++ b/src/hydrogen.h
@@ -401,27 +401,33 @@ class HEnvironment: public ZoneObject {
Scope* scope,
Handle<JSFunction> closure);
+ // Simple accessors.
+ Handle<JSFunction> closure() const { return closure_; }
+ const ZoneList<HValue*>* values() const { return &values_; }
+ const ZoneList<int>* assigned_variables() const {
+ return &assigned_variables_;
+ }
+ int parameter_count() const { return parameter_count_; }
+ int local_count() const { return local_count_; }
+ HEnvironment* outer() const { return outer_; }
+ int pop_count() const { return pop_count_; }
+ int push_count() const { return push_count_; }
+
+ int ast_id() const { return ast_id_; }
+ void set_ast_id(int id) { ast_id_ = id; }
+
+ int length() const { return values_.length(); }
+
void Bind(Variable* variable, HValue* value) {
Bind(IndexFor(variable), value);
-
- if (FLAG_trace_environment) {
- PrintF("Slot index=%d name=%s\n",
- variable->AsSlot()->index(),
- *variable->name()->ToCString());
- }
}
- void Bind(int index, HValue* value) {
- ASSERT(value != NULL);
- if (!assigned_variables_.Contains(index)) {
- assigned_variables_.Add(index);
- }
- values_[index] = value;
- }
+ void Bind(int index, HValue* value);
HValue* Lookup(Variable* variable) const {
return Lookup(IndexFor(variable));
}
+
HValue* Lookup(int index) const {
HValue* result = values_[index];
ASSERT(result != NULL);
@@ -434,53 +440,28 @@ class HEnvironment: public ZoneObject {
values_.Add(value);
}
- HValue* Top() const { return ExpressionStackAt(0); }
-
- HValue* ExpressionStackAt(int index_from_top) const {
- int index = values_.length() - index_from_top - 1;
- ASSERT(IsExpressionStackIndex(index));
- return values_[index];
- }
-
- void SetExpressionStackAt(int index_from_top, HValue* value) {
- int index = values_.length() - index_from_top - 1;
- ASSERT(IsExpressionStackIndex(index));
- values_[index] = value;
- }
-
HValue* Pop() {
- ASSERT(!IsExpressionStackEmpty());
+ ASSERT(!ExpressionStackIsEmpty());
if (push_count_ > 0) {
--push_count_;
- ASSERT(push_count_ >= 0);
} else {
++pop_count_;
}
return values_.RemoveLast();
}
- void Drop(int count) {
- for (int i = 0; i < count; ++i) {
- Pop();
- }
- }
-
- Handle<JSFunction> closure() const { return closure_; }
+ void Drop(int count);
- // ID of the original AST node to identify deoptimization points.
- int ast_id() const { return ast_id_; }
- void set_ast_id(int id) { ast_id_ = id; }
+ HValue* Top() const { return ExpressionStackAt(0); }
- const ZoneList<HValue*>* values() const { return &values_; }
- const ZoneList<int>* assigned_variables() const {
- return &assigned_variables_;
+ HValue* ExpressionStackAt(int index_from_top) const {
+ int index = length() - index_from_top - 1;
+ ASSERT(HasExpressionAt(index));
+ return values_[index];
}
- int parameter_count() const { return parameter_count_; }
- int local_count() const { return local_count_; }
- int push_count() const { return push_count_; }
- int pop_count() const { return pop_count_; }
- int total_count() const { return values_.length(); }
- HEnvironment* outer() const { return outer_; }
+
+ void SetExpressionStackAt(int index_from_top, HValue* value);
+
HEnvironment* Copy() const;
HEnvironment* CopyWithoutHistory() const;
HEnvironment* CopyAsLoopHeader(HBasicBlock* block) const;
@@ -496,13 +477,15 @@ class HEnvironment: public ZoneObject {
HConstant* undefined) const;
void AddIncomingEdge(HBasicBlock* block, HEnvironment* other);
+
void ClearHistory() {
pop_count_ = 0;
push_count_ = 0;
assigned_variables_.Clear();
}
+
void SetValueAt(int index, HValue* value) {
- ASSERT(index < total_count());
+ ASSERT(index < length());
values_[index] = value;
}
@@ -512,19 +495,23 @@ class HEnvironment: public ZoneObject {
private:
explicit HEnvironment(const HEnvironment* other);
- bool IsExpressionStackIndex(int index) const {
- return index >= parameter_count_ + local_count_;
- }
- bool IsExpressionStackEmpty() const {
- int length = values_.length();
- int first_expression = parameter_count() + local_count();
- ASSERT(length >= first_expression);
- return length == first_expression;
- }
+ // True if index is included in the expression stack part of the environment.
+ bool HasExpressionAt(int index) const;
+
+ bool ExpressionStackIsEmpty() const;
+
void Initialize(int parameter_count, int local_count, int stack_height);
void Initialize(const HEnvironment* other);
- int VariableToIndex(Variable* var);
- int IndexFor(Variable* variable) const;
+
+ // Map a variable to an environment index. Parameter indices are shifted
+ // by 1 (receiver is parameter index -1 but environment index 0).
+ // Stack-allocated local indices are shifted by the number of parameters.
+ int IndexFor(Variable* variable) const {
+ Slot* slot = variable->AsSlot();
+ ASSERT(slot != NULL && slot->IsStackAllocated());
+ int shift = (slot->type() == Slot::PARAMETER) ? 1 : parameter_count_;
+ return slot->index() + shift;
+ }
Handle<JSFunction> closure_;
// Value array [parameters] [locals] [temporaries].
@@ -567,7 +554,7 @@ class AstContext {
// We want to be able to assert, in a context-specific way, that the stack
// height makes sense when the context is filled.
#ifdef DEBUG
- int original_count_;
+ int original_length_;
#endif
private:
diff --git a/src/ia32/builtins-ia32.cc b/src/ia32/builtins-ia32.cc
index 918f346d..0a3e0930 100644
--- a/src/ia32/builtins-ia32.cc
+++ b/src/ia32/builtins-ia32.cc
@@ -399,7 +399,7 @@ void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) {
static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
bool is_construct) {
// Clear the context before we push it when entering the JS frame.
- __ xor_(esi, Operand(esi)); // clear esi
+ __ Set(esi, Immediate(0));
// Enter an internal frame.
__ EnterInternalFrame();
@@ -421,7 +421,7 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
// Copy arguments to the stack in a loop.
Label loop, entry;
- __ xor_(ecx, Operand(ecx)); // clear ecx
+ __ Set(ecx, Immediate(0));
__ jmp(&entry);
__ bind(&loop);
__ mov(edx, Operand(ebx, ecx, times_4, 0)); // push parameter from argv
@@ -644,7 +644,7 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
__ bind(&non_function);
__ mov(Operand(esp, eax, times_4, 0), edi);
// Clear edi to indicate a non-function being called.
- __ xor_(edi, Operand(edi));
+ __ Set(edi, Immediate(0));
// 4. Shift arguments and return address one slot down on the stack
// (overwriting the original receiver). Adjust argument count to make
@@ -665,7 +665,7 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
{ Label function;
__ test(edi, Operand(edi));
__ j(not_zero, &function, taken);
- __ xor_(ebx, Operand(ebx));
+ __ Set(ebx, Immediate(0));
__ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION);
__ jmp(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)),
RelocInfo::CODE_TARGET);
diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc
index a371c963..bd95c8d0 100644
--- a/src/ia32/code-stubs-ia32.cc
+++ b/src/ia32/code-stubs-ia32.cc
@@ -104,7 +104,7 @@ void FastNewContextStub::Generate(MacroAssembler* masm) {
Immediate(Smi::FromInt(length)));
// Setup the fixed slots.
- __ xor_(ebx, Operand(ebx)); // Set to NULL.
+ __ Set(ebx, Immediate(0)); // Set to NULL.
__ mov(Operand(eax, Context::SlotOffset(Context::CLOSURE_INDEX)), ecx);
__ mov(Operand(eax, Context::SlotOffset(Context::FCONTEXT_INDEX)), eax);
__ mov(Operand(eax, Context::SlotOffset(Context::PREVIOUS_INDEX)), ebx);
@@ -4303,7 +4303,7 @@ void CompareStub::Generate(MacroAssembler* masm) {
// that contains the exponent and high bit of the mantissa.
STATIC_ASSERT(((kQuietNaNHighBitsMask << 1) & 0x80000000u) != 0);
__ mov(edx, FieldOperand(edx, HeapNumber::kExponentOffset));
- __ xor_(eax, Operand(eax));
+ __ Set(eax, Immediate(0));
// Shift value and mask so kQuietNaNHighBitsMask applies to topmost
// bits.
__ add(edx, Operand(edx));
@@ -4433,7 +4433,7 @@ void CompareStub::Generate(MacroAssembler* masm) {
__ j(below, &below_label, not_taken);
__ j(above, &above_label, not_taken);
- __ xor_(eax, Operand(eax));
+ __ Set(eax, Immediate(0));
__ ret(0);
__ bind(&below_label);
@@ -4646,7 +4646,7 @@ void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) {
// Before returning we restore the context from the frame pointer if
// not NULL. The frame pointer is NULL in the exception handler of
// a JS entry frame.
- __ xor_(esi, Operand(esi)); // Tentatively set context pointer to NULL.
+ __ Set(esi, Immediate(0)); // Tentatively set context pointer to NULL.
NearLabel skip;
__ cmp(ebp, 0);
__ j(equal, &skip, not_taken);
@@ -4799,7 +4799,7 @@ void CEntryStub::GenerateThrowUncatchable(MacroAssembler* masm,
}
// Clear the context pointer.
- __ xor_(esi, Operand(esi));
+ __ Set(esi, Immediate(0));
// Restore fp from handler and discard handler state.
STATIC_ASSERT(StackHandlerConstants::kFPOffset == 1 * kPointerSize);
diff --git a/src/ia32/debug-ia32.cc b/src/ia32/debug-ia32.cc
index ee945656..678cc931 100644
--- a/src/ia32/debug-ia32.cc
+++ b/src/ia32/debug-ia32.cc
@@ -125,7 +125,7 @@ static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
#ifdef DEBUG
__ RecordComment("// Calling from debug break to runtime - come in - over");
#endif
- __ Set(eax, Immediate(0)); // no arguments
+ __ Set(eax, Immediate(0)); // No arguments.
__ mov(ebx, Immediate(ExternalReference::debug_break()));
CEntryStub ceb(1);
diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc
index 13a11777..5beec0d3 100644
--- a/src/ia32/full-codegen-ia32.cc
+++ b/src/ia32/full-codegen-ia32.cc
@@ -379,7 +379,7 @@ void FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const {
void FullCodeGenerator::AccumulatorValueContext::Plug(
Handle<Object> lit) const {
- __ mov(result_register(), lit);
+ __ Set(result_register(), Immediate(lit));
}
diff --git a/src/ia32/ic-ia32.cc b/src/ia32/ic-ia32.cc
index 9c9304d5..90bfd4b6 100644
--- a/src/ia32/ic-ia32.cc
+++ b/src/ia32/ic-ia32.cc
@@ -1199,7 +1199,7 @@ void KeyedStoreIC::GenerateExternalArray(MacroAssembler* masm,
break;
case kExternalShortArray:
case kExternalUnsignedShortArray:
- __ xor_(ecx, Operand(ecx));
+ __ Set(ecx, Immediate(0));
__ mov_w(Operand(edi, ebx, times_2, 0), ecx);
break;
case kExternalIntArray:
@@ -1219,9 +1219,6 @@ void KeyedStoreIC::GenerateExternalArray(MacroAssembler* masm,
}
-// Defined in ic.cc.
-Object* CallIC_Miss(Arguments args);
-
// The generated code does not accept smi keys.
// The generated code falls through if both probes miss.
static void GenerateMonomorphicCacheProbe(MacroAssembler* masm,
@@ -1567,9 +1564,6 @@ void KeyedCallIC::GenerateMiss(MacroAssembler* masm, int argc) {
}
-// Defined in ic.cc.
-Object* LoadIC_Miss(Arguments args);
-
void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- eax : receiver
@@ -1795,10 +1789,6 @@ bool KeyedStoreIC::PatchInlinedStore(Address address, Object* map) {
}
-// Defined in ic.cc.
-Object* KeyedLoadIC_Miss(Arguments args);
-
-
void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- eax : key
@@ -1982,9 +1972,6 @@ void StoreIC::GenerateGlobalProxy(MacroAssembler* masm) {
}
-// Defined in ic.cc.
-Object* KeyedStoreIC_Miss(Arguments args);
-
void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- eax : value
diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc
index d64f528e..0f568257 100644
--- a/src/ia32/lithium-codegen-ia32.cc
+++ b/src/ia32/lithium-codegen-ia32.cc
@@ -940,7 +940,7 @@ void LCodeGen::DoSubI(LSubI* instr) {
void LCodeGen::DoConstantI(LConstantI* instr) {
ASSERT(instr->result()->IsRegister());
- __ mov(ToRegister(instr->result()), instr->value());
+ __ Set(ToRegister(instr->result()), Immediate(instr->value()));
}
@@ -973,27 +973,21 @@ void LCodeGen::DoConstantD(LConstantD* instr) {
void LCodeGen::DoConstantT(LConstantT* instr) {
ASSERT(instr->result()->IsRegister());
- __ mov(ToRegister(instr->result()), Immediate(instr->value()));
+ __ Set(ToRegister(instr->result()), Immediate(instr->value()));
}
-void LCodeGen::DoArrayLength(LArrayLength* instr) {
+void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) {
Register result = ToRegister(instr->result());
+ Register array = ToRegister(instr->input());
+ __ mov(result, FieldOperand(array, JSArray::kLengthOffset));
+}
- if (instr->hydrogen()->value()->IsLoadElements()) {
- // We load the length directly from the elements array.
- Register elements = ToRegister(instr->input());
- __ mov(result, FieldOperand(elements, FixedArray::kLengthOffset));
- } else {
- // Check that the receiver really is an array.
- Register array = ToRegister(instr->input());
- Register temporary = ToRegister(instr->temporary());
- __ CmpObjectType(array, JS_ARRAY_TYPE, temporary);
- DeoptimizeIf(not_equal, instr->environment());
- // Load length directly from the array.
- __ mov(result, FieldOperand(array, JSArray::kLengthOffset));
- }
+void LCodeGen::DoFixedArrayLength(LFixedArrayLength* instr) {
+ Register result = ToRegister(instr->result());
+ Register array = ToRegister(instr->input());
+ __ mov(result, FieldOperand(array, FixedArray::kLengthOffset));
}
@@ -1837,6 +1831,48 @@ void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
}
+void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) {
+ Register function = ToRegister(instr->function());
+ Register temp = ToRegister(instr->temporary());
+ Register result = ToRegister(instr->result());
+
+ // Check that the function really is a function.
+ __ CmpObjectType(function, JS_FUNCTION_TYPE, result);
+ DeoptimizeIf(not_equal, instr->environment());
+
+ // Check whether the function has an instance prototype.
+ NearLabel non_instance;
+ __ test_b(FieldOperand(result, Map::kBitFieldOffset),
+ 1 << Map::kHasNonInstancePrototype);
+ __ j(not_zero, &non_instance);
+
+ // Get the prototype or initial map from the function.
+ __ mov(result,
+ FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
+
+ // Check that the function has a prototype or an initial map.
+ __ cmp(Operand(result), Immediate(Factory::the_hole_value()));
+ DeoptimizeIf(equal, instr->environment());
+
+ // If the function does not have an initial map, we're done.
+ NearLabel done;
+ __ CmpObjectType(result, MAP_TYPE, temp);
+ __ j(not_equal, &done);
+
+ // Get the prototype from the initial map.
+ __ mov(result, FieldOperand(result, Map::kPrototypeOffset));
+ __ jmp(&done);
+
+ // Non-instance prototype: Fetch prototype from constructor field
+ // in the function's map.
+ __ bind(&non_instance);
+ __ mov(result, FieldOperand(result, Map::kConstructorOffset));
+
+ // All done.
+ __ bind(&done);
+}
+
+
void LCodeGen::DoLoadElements(LLoadElements* instr) {
ASSERT(instr->result()->Equals(instr->input()));
Register reg = ToRegister(instr->input());
@@ -2891,9 +2927,6 @@ void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
InstanceType first = instr->hydrogen()->first();
InstanceType last = instr->hydrogen()->last();
- __ test(input, Immediate(kSmiTagMask));
- DeoptimizeIf(zero, instr->environment());
-
__ mov(temp, FieldOperand(input, HeapObject::kMapOffset));
__ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset),
static_cast<int8_t>(first));
@@ -3006,7 +3039,7 @@ void LCodeGen::DoObjectLiteral(LObjectLiteral* instr) {
__ push(Immediate(instr->hydrogen()->constant_properties()));
__ push(Immediate(Smi::FromInt(instr->hydrogen()->fast_elements() ? 1 : 0)));
- // Pick the right runtime function or stub to call.
+ // Pick the right runtime function to call.
if (instr->hydrogen()->depth() > 1) {
CallRuntime(Runtime::kCreateObjectLiteral, 4, instr);
} else {
diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc
index 3b272d0b..4fde3d46 100644
--- a/src/ia32/lithium-ia32.cc
+++ b/src/ia32/lithium-ia32.cc
@@ -767,11 +767,6 @@ LInstruction* LChunkBuilder::DefineAsSpilled(LInstruction* instr, int index) {
}
-LInstruction* LChunkBuilder::DefineSameAsAny(LInstruction* instr) {
- return Define(instr, new LUnallocated(LUnallocated::SAME_AS_ANY_INPUT));
-}
-
-
LInstruction* LChunkBuilder::DefineSameAsFirst(LInstruction* instr) {
return Define(instr, new LUnallocated(LUnallocated::SAME_AS_FIRST_INPUT));
}
@@ -1016,9 +1011,6 @@ void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) {
HInstruction* current = block->first();
int start = chunk_->instructions()->length();
while (current != NULL && !is_aborted()) {
- if (FLAG_trace_environment) {
- PrintF("Process instruction %d\n", current->id());
- }
// Code for constants in registers is generated lazily.
if (!current->EmitAtUses()) {
VisitInstruction(current);
@@ -1125,7 +1117,7 @@ LEnvironment* LChunkBuilder::CreateEnvironment(HEnvironment* hydrogen_env) {
LEnvironment* outer = CreateEnvironment(hydrogen_env->outer());
int ast_id = hydrogen_env->ast_id();
ASSERT(ast_id != AstNode::kNoNumber);
- int value_count = hydrogen_env->values()->length();
+ int value_count = hydrogen_env->length();
LEnvironment* result = new LEnvironment(hydrogen_env->closure(),
ast_id,
hydrogen_env->parameter_count(),
@@ -1677,19 +1669,15 @@ LInstruction* LChunkBuilder::DoClassOfTest(HClassOfTest* instr) {
}
-LInstruction* LChunkBuilder::DoArrayLength(HArrayLength* instr) {
- LOperand* array = NULL;
- LOperand* temporary = NULL;
+LInstruction* LChunkBuilder::DoJSArrayLength(HJSArrayLength* instr) {
+ LOperand* array = UseRegisterAtStart(instr->value());
+ return DefineAsRegister(new LJSArrayLength(array));
+}
- if (instr->value()->IsLoadElements()) {
- array = UseRegisterAtStart(instr->value());
- } else {
- array = UseRegister(instr->value());
- temporary = TempRegister();
- }
- LInstruction* result = new LArrayLength(array, temporary);
- return AssignEnvironment(DefineAsRegister(result));
+LInstruction* LChunkBuilder::DoFixedArrayLength(HFixedArrayLength* instr) {
+ LOperand* array = UseRegisterAtStart(instr->value());
+ return DefineAsRegister(new LFixedArrayLength(array));
}
@@ -1860,6 +1848,14 @@ LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
}
+LInstruction* LChunkBuilder::DoLoadFunctionPrototype(
+ HLoadFunctionPrototype* instr) {
+ return AssignEnvironment(DefineAsRegister(
+ new LLoadFunctionPrototype(UseRegister(instr->function()),
+ TempRegister())));
+}
+
+
LInstruction* LChunkBuilder::DoLoadElements(HLoadElements* instr) {
LOperand* input = UseRegisterAtStart(instr->value());
return DefineSameAsFirst(new LLoadElements(input));
@@ -1931,7 +1927,7 @@ LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
- bool needs_write_barrier = !instr->value()->type().IsSmi();
+ bool needs_write_barrier = instr->NeedsWriteBarrier();
LOperand* obj = needs_write_barrier
? UseTempRegister(instr->object())
@@ -2035,7 +2031,7 @@ LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) {
- LInstruction* result = new LTypeof(Use(instr->value()));
+ LInstruction* result = new LTypeof(UseAtStart(instr->value()));
return MarkAsCall(DefineFixed(result, eax), instr);
}
@@ -2059,14 +2055,7 @@ LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
env->Push(value);
}
}
-
- if (FLAG_trace_environment) {
- PrintF("Reconstructed environment ast_id=%d, instr_id=%d\n",
- instr->ast_id(),
- instr->id());
- env->PrintToStd();
- }
- ASSERT(env->values()->length() == instr->environment_height());
+ ASSERT(env->length() == instr->environment_length());
// If there is an instruction pending deoptimization environment create a
// lazy bailout instruction to capture the environment.
diff --git a/src/ia32/lithium-ia32.h b/src/ia32/lithium-ia32.h
index 3f48e50e..00dc3944 100644
--- a/src/ia32/lithium-ia32.h
+++ b/src/ia32/lithium-ia32.h
@@ -104,7 +104,6 @@ class LGapNode;
// LStoreNamedField
// LStoreNamedGeneric
// LUnaryOperation
-// LArrayLength
// LBitNotI
// LBranch
// LCallNew
@@ -117,6 +116,7 @@ class LGapNode;
// LClassOfTestAndBranch
// LDeleteProperty
// LDoubleToI
+// LFixedArrayLength
// LHasCachedArrayIndex
// LHasCachedArrayIndexAndBranch
// LHasInstanceType
@@ -128,8 +128,10 @@ class LGapNode;
// LIsObjectAndBranch
// LIsSmi
// LIsSmiAndBranch
+// LJSArrayLength
// LLoadNamedField
// LLoadNamedGeneric
+// LLoadFunctionPrototype
// LNumberTagD
// LNumberTagI
// LPushArgument
@@ -164,7 +166,6 @@ class LGapNode;
V(ArgumentsLength) \
V(ArithmeticD) \
V(ArithmeticT) \
- V(ArrayLength) \
V(ArrayLiteral) \
V(BitI) \
V(BitNotI) \
@@ -203,6 +204,7 @@ class LGapNode;
V(GlobalObject) \
V(GlobalReceiver) \
V(Goto) \
+ V(FixedArrayLength) \
V(InstanceOf) \
V(InstanceOfAndBranch) \
V(Integer32ToDouble) \
@@ -212,6 +214,7 @@ class LGapNode;
V(IsObjectAndBranch) \
V(IsSmi) \
V(IsSmiAndBranch) \
+ V(JSArrayLength) \
V(HasInstanceType) \
V(HasInstanceTypeAndBranch) \
V(HasCachedArrayIndex) \
@@ -226,6 +229,7 @@ class LGapNode;
V(LoadKeyedGeneric) \
V(LoadNamedField) \
V(LoadNamedGeneric) \
+ V(LoadFunctionPrototype) \
V(ModI) \
V(MulI) \
V(NumberTagD) \
@@ -1146,18 +1150,21 @@ class LCmpMapAndBranch: public LUnaryOperation {
};
-class LArrayLength: public LUnaryOperation {
+class LJSArrayLength: public LUnaryOperation {
public:
- LArrayLength(LOperand* input, LOperand* temporary)
- : LUnaryOperation(input), temporary_(temporary) { }
+ explicit LJSArrayLength(LOperand* input) : LUnaryOperation(input) { }
- LOperand* temporary() const { return temporary_; }
+ DECLARE_CONCRETE_INSTRUCTION(JSArrayLength, "js-array-length")
+ DECLARE_HYDROGEN_ACCESSOR(JSArrayLength)
+};
- DECLARE_CONCRETE_INSTRUCTION(ArrayLength, "array-length")
- DECLARE_HYDROGEN_ACCESSOR(ArrayLength)
- private:
- LOperand* temporary_;
+class LFixedArrayLength: public LUnaryOperation {
+ public:
+ explicit LFixedArrayLength(LOperand* input) : LUnaryOperation(input) { }
+
+ DECLARE_CONCRETE_INSTRUCTION(FixedArrayLength, "fixed-array-length")
+ DECLARE_HYDROGEN_ACCESSOR(FixedArrayLength)
};
@@ -1271,6 +1278,22 @@ class LLoadNamedGeneric: public LUnaryOperation {
};
+class LLoadFunctionPrototype: public LUnaryOperation {
+ public:
+ LLoadFunctionPrototype(LOperand* function, LOperand* temporary)
+ : LUnaryOperation(function), temporary_(temporary) { }
+
+ DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype, "load-function-prototype")
+ DECLARE_HYDROGEN_ACCESSOR(LoadFunctionPrototype)
+
+ LOperand* function() const { return input(); }
+ LOperand* temporary() const { return temporary_; }
+
+ private:
+ LOperand* temporary_;
+};
+
+
class LLoadElements: public LUnaryOperation {
public:
explicit LLoadElements(LOperand* obj) : LUnaryOperation(obj) { }
@@ -2064,7 +2087,6 @@ class LChunkBuilder BASE_EMBEDDED {
LInstruction* Define(LInstruction* instr);
LInstruction* DefineAsRegister(LInstruction* instr);
LInstruction* DefineAsSpilled(LInstruction* instr, int index);
- LInstruction* DefineSameAsAny(LInstruction* instr);
LInstruction* DefineSameAsFirst(LInstruction* instr);
LInstruction* DefineFixed(LInstruction* instr, Register reg);
LInstruction* DefineFixedDouble(LInstruction* instr, XMMRegister reg);
diff --git a/src/ia32/regexp-macro-assembler-ia32.cc b/src/ia32/regexp-macro-assembler-ia32.cc
index d435a707..12134488 100644
--- a/src/ia32/regexp-macro-assembler-ia32.cc
+++ b/src/ia32/regexp-macro-assembler-ia32.cc
@@ -211,9 +211,7 @@ void RegExpMacroAssemblerIA32::CheckCharacters(Vector<const uc16> str,
// If input is ASCII, don't even bother calling here if the string to
// match contains a non-ascii character.
if (mode_ == ASCII) {
- for (int i = 0; i < str.length(); i++) {
- ASSERT(str[i] <= String::kMaxAsciiCharCodeU);
- }
+ ASSERT(String::IsAscii(str.start(), str.length()));
}
#endif
int byte_length = str.length() * char_size();
@@ -654,7 +652,7 @@ bool RegExpMacroAssemblerIA32::CheckSpecialCharacterClass(uc16 type,
void RegExpMacroAssemblerIA32::Fail() {
ASSERT(FAILURE == 0); // Return value for failure is zero.
- __ xor_(eax, Operand(eax)); // zero eax.
+ __ Set(eax, Immediate(0));
__ jmp(&exit_label_);
}
diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc
index 99888b08..bcb02ed7 100644
--- a/src/ia32/stub-cache-ia32.cc
+++ b/src/ia32/stub-cache-ia32.cc
@@ -1686,6 +1686,7 @@ MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall(
Label miss;
Label index_out_of_range;
+
GenerateNameCheck(name, &miss);
// Check that the maps starting from the prototype haven't changed.
diff --git a/src/json.js b/src/json.js
index 89009a96..0034176b 100644
--- a/src/json.js
+++ b/src/json.js
@@ -27,11 +27,6 @@
var $JSON = global.JSON;
-function ParseJSONUnfiltered(text) {
- var s = $String(text);
- return %ParseJson(s);
-}
-
function Revive(holder, name, reviver) {
var val = holder[name];
if (IS_OBJECT(val)) {
@@ -58,7 +53,7 @@ function Revive(holder, name, reviver) {
}
function JSONParse(text, reviver) {
- var unfiltered = ParseJSONUnfiltered(text);
+ var unfiltered = %ParseJson(TO_STRING_INLINE(text));
if (IS_FUNCTION(reviver)) {
return Revive({'': unfiltered}, '', reviver);
} else {
@@ -158,7 +153,7 @@ function JSONSerialize(key, holder, replacer, stack, indent, gap) {
if (IS_STRING(value)) {
return %QuoteJSONString(value);
} else if (IS_NUMBER(value)) {
- return $isFinite(value) ? $String(value) : "null";
+ return NUMBER_IS_FINITE(value) ? $String(value) : "null";
} else if (IS_BOOLEAN(value)) {
return value ? "true" : "false";
} else if (IS_NULL(value)) {
@@ -169,7 +164,7 @@ function JSONSerialize(key, holder, replacer, stack, indent, gap) {
return SerializeArray(value, replacer, stack, indent, gap);
} else if (IS_NUMBER_WRAPPER(value)) {
value = ToNumber(value);
- return $isFinite(value) ? ToString(value) : "null";
+ return NUMBER_IS_FINITE(value) ? ToString(value) : "null";
} else if (IS_STRING_WRAPPER(value)) {
return %QuoteJSONString(ToString(value));
} else if (IS_BOOLEAN_WRAPPER(value)) {
@@ -244,7 +239,7 @@ function BasicJSONSerialize(key, holder, stack, builder) {
if (IS_STRING(value)) {
builder.push(%QuoteJSONString(value));
} else if (IS_NUMBER(value)) {
- builder.push(($isFinite(value) ? %_NumberToString(value) : "null"));
+ builder.push(NUMBER_IS_FINITE(value) ? %_NumberToString(value) : "null");
} else if (IS_BOOLEAN(value)) {
builder.push(value ? "true" : "false");
} else if (IS_NULL(value)) {
@@ -254,7 +249,7 @@ function BasicJSONSerialize(key, holder, stack, builder) {
// Unwrap value if necessary
if (IS_NUMBER_WRAPPER(value)) {
value = ToNumber(value);
- builder.push(($isFinite(value) ? %_NumberToString(value) : "null"));
+ builder.push(NUMBER_IS_FINITE(value) ? %_NumberToString(value) : "null");
} else if (IS_STRING_WRAPPER(value)) {
builder.push(%QuoteJSONString(ToString(value)));
} else if (IS_BOOLEAN_WRAPPER(value)) {
diff --git a/src/lithium-allocator.cc b/src/lithium-allocator.cc
index ac61c17b..eecc441f 100644
--- a/src/lithium-allocator.cc
+++ b/src/lithium-allocator.cc
@@ -27,7 +27,6 @@
#include "lithium-allocator.h"
-#include "data-flow.h"
#include "hydrogen.h"
#include "string-stream.h"
@@ -107,9 +106,6 @@ void LOperand::PrintTo(StringStream* stream) {
case LUnallocated::SAME_AS_FIRST_INPUT:
stream->Add("(1)");
break;
- case LUnallocated::SAME_AS_ANY_INPUT:
- stream->Add("(A)");
- break;
case LUnallocated::ANY:
stream->Add("(-)");
break;
@@ -834,6 +830,13 @@ void LAllocator::MeetConstraintsBetween(InstructionSummary* first,
} else if (cur_input->policy() == LUnallocated::WRITABLE_REGISTER) {
LUnallocated* input_copy = cur_input->CopyUnconstrained();
cur_input->set_virtual_register(next_virtual_register_++);
+
+ if (RequiredRegisterKind(input_copy->virtual_register()) ==
+ DOUBLE_REGISTERS) {
+ double_artificial_registers_.Add(
+ cur_input->virtual_register() - first_artificial_register_);
+ }
+
second->AddTemp(cur_input);
AddConstraintsGapMove(gap_index, input_copy, cur_input);
}
@@ -1036,6 +1039,7 @@ void LAllocator::Allocate(LChunk* chunk) {
void LAllocator::MeetRegisterConstraints() {
HPhase phase("Register constraints", chunk());
+ first_artificial_register_ = next_virtual_register_;
const ZoneList<HBasicBlock*>* blocks = graph()->blocks();
for (int i = 0; i < blocks->length(); ++i) {
HBasicBlock* block = blocks->at(i);
@@ -1564,16 +1568,42 @@ bool LAllocator::HasTaggedValue(int virtual_register) const {
RegisterKind LAllocator::RequiredRegisterKind(int virtual_register) const {
- HValue* value = graph()->LookupValue(virtual_register);
- if (value != NULL && value->representation().IsDouble()) {
+ if (virtual_register < first_artificial_register_) {
+ HValue* value = graph()->LookupValue(virtual_register);
+ if (value != NULL && value->representation().IsDouble()) {
+ return DOUBLE_REGISTERS;
+ }
+ } else if (double_artificial_registers_.Contains(
+ virtual_register - first_artificial_register_)) {
return DOUBLE_REGISTERS;
}
+
return GENERAL_REGISTERS;
}
void LAllocator::MarkAsCall() {
- current_summary()->MarkAsCall();
+ // Call instructions can use only fixed registers as
+ // temporaries and outputs because all registers
+ // are blocked by the calling convention.
+ // Inputs can use either fixed register or have a short lifetime (be
+ // used at start of the instruction).
+ InstructionSummary* summary = current_summary();
+#ifdef DEBUG
+ ASSERT(summary->Output() == NULL ||
+ LUnallocated::cast(summary->Output())->HasFixedPolicy() ||
+ !LUnallocated::cast(summary->Output())->HasRegisterPolicy());
+ for (int i = 0; i < summary->InputCount(); i++) {
+ ASSERT(LUnallocated::cast(summary->InputAt(i))->HasFixedPolicy() ||
+ LUnallocated::cast(summary->InputAt(i))->IsUsedAtStart() ||
+ !LUnallocated::cast(summary->InputAt(i))->HasRegisterPolicy());
+ }
+ for (int i = 0; i < summary->TempCount(); i++) {
+ ASSERT(LUnallocated::cast(summary->TempAt(i))->HasFixedPolicy() ||
+ !LUnallocated::cast(summary->TempAt(i))->HasRegisterPolicy());
+ }
+#endif
+ summary->MarkAsCall();
}
diff --git a/src/lithium-allocator.h b/src/lithium-allocator.h
index 3ec984e2..fe837e2f 100644
--- a/src/lithium-allocator.h
+++ b/src/lithium-allocator.h
@@ -30,6 +30,7 @@
#include "v8.h"
+#include "data-flow.h"
#include "zone.h"
namespace v8 {
@@ -204,7 +205,6 @@ class LUnallocated: public LOperand {
MUST_HAVE_REGISTER,
WRITABLE_REGISTER,
SAME_AS_FIRST_INPUT,
- SAME_AS_ANY_INPUT,
IGNORE
};
@@ -275,7 +275,7 @@ class LUnallocated: public LOperand {
return policy() == WRITABLE_REGISTER || policy() == MUST_HAVE_REGISTER;
}
bool HasSameAsInputPolicy() const {
- return policy() == SAME_AS_FIRST_INPUT || policy() == SAME_AS_ANY_INPUT;
+ return policy() == SAME_AS_FIRST_INPUT;
}
Policy policy() const { return PolicyField::decode(value_); }
void set_policy(Policy policy) {
@@ -754,6 +754,40 @@ class LiveRange: public ZoneObject {
};
+class GrowableBitVector BASE_EMBEDDED {
+ public:
+ GrowableBitVector() : bits_(NULL) { }
+
+ bool Contains(int value) const {
+ if (!InBitsRange(value)) return false;
+ return bits_->Contains(value);
+ }
+
+ void Add(int value) {
+ EnsureCapacity(value);
+ bits_->Add(value);
+ }
+
+ private:
+ static const int kInitialLength = 1024;
+
+ bool InBitsRange(int value) const {
+ return bits_ != NULL && bits_->length() > value;
+ }
+
+ void EnsureCapacity(int value) {
+ if (InBitsRange(value)) return;
+ int new_length = bits_ == NULL ? kInitialLength : bits_->length();
+ while (new_length <= value) new_length *= 2;
+ BitVector* new_bits = new BitVector(new_length);
+ if (bits_ != NULL) new_bits->CopyFrom(*bits_);
+ bits_ = new_bits;
+ }
+
+ BitVector* bits_;
+};
+
+
class LAllocator BASE_EMBEDDED {
public:
explicit LAllocator(int first_virtual_register, HGraph* graph)
@@ -770,6 +804,7 @@ class LAllocator BASE_EMBEDDED {
inactive_live_ranges_(8),
reusable_slots_(8),
next_virtual_register_(first_virtual_register),
+ first_artificial_register_(first_virtual_register),
mode_(NONE),
num_registers_(-1),
graph_(graph),
@@ -972,6 +1007,8 @@ class LAllocator BASE_EMBEDDED {
// Next virtual register number to be assigned to temporaries.
int next_virtual_register_;
+ int first_artificial_register_;
+ GrowableBitVector double_artificial_registers_;
RegisterKind mode_;
int num_registers_;
diff --git a/src/liveedit-debugger.js b/src/liveedit-debugger.js
index 0f7c12d7..7ed22c84 100644
--- a/src/liveedit-debugger.js
+++ b/src/liveedit-debugger.js
@@ -144,8 +144,8 @@ Debug.LiveEdit = new function() {
replace_code_list[i].live_shared_function_infos;
if (live_shared_function_infos) {
- for (var i = 0; i < live_shared_function_infos.length; i++) {
- replaced_function_infos.push(live_shared_function_infos[i]);
+ for (var j = 0; j < live_shared_function_infos.length; j++) {
+ replaced_function_infos.push(live_shared_function_infos[j]);
}
}
}
diff --git a/src/log.cc b/src/log.cc
index db9ff7a1..6eb3c9b0 100644
--- a/src/log.cc
+++ b/src/log.cc
@@ -276,7 +276,8 @@ void SlidingStateWindow::AddState(StateTag state) {
// Profiler implementation.
//
Profiler::Profiler()
- : head_(0),
+ : Thread("v8:Profiler"),
+ head_(0),
tail_(0),
overflow_(false),
buffer_semaphore_(OS::CreateSemaphore(0)),
diff --git a/src/macros.py b/src/macros.py
index 6d66defb..01512e46 100644
--- a/src/macros.py
+++ b/src/macros.py
@@ -120,6 +120,7 @@ macro IS_SPEC_OBJECT(arg) = (%_IsSpecObject(arg));
# Inline macros. Use %IS_VAR to make sure arg is evaluated only once.
macro NUMBER_IS_NAN(arg) = (!%_IsSmi(%IS_VAR(arg)) && !(arg == arg));
+macro NUMBER_IS_FINITE(arg) = (%_IsSmi(%IS_VAR(arg)) || arg - arg == 0);
macro TO_INTEGER(arg) = (%_IsSmi(%IS_VAR(arg)) ? arg : %NumberToInteger(ToNumber(arg)));
macro TO_INTEGER_MAP_MINUS_ZERO(arg) = (%_IsSmi(%IS_VAR(arg)) ? arg : %NumberToIntegerMapMinusZero(ToNumber(arg)));
macro TO_INT32(arg) = (%_IsSmi(%IS_VAR(arg)) ? arg : (arg >> 0));
diff --git a/src/mirror-debugger.js b/src/mirror-debugger.js
index 55836ce7..9177a6bc 100644
--- a/src/mirror-debugger.js
+++ b/src/mirror-debugger.js
@@ -2369,7 +2369,7 @@ function NumberToJSON_(value) {
if (isNaN(value)) {
return 'NaN';
}
- if (!isFinite(value)) {
+ if (!NUMBER_IS_FINITE(value)) {
if (value > 0) {
return 'Infinity';
} else {
diff --git a/src/objects-debug.cc b/src/objects-debug.cc
index 53296d92..0b83182d 100644
--- a/src/objects-debug.cc
+++ b/src/objects-debug.cc
@@ -1,4 +1,4 @@
-// Copyright 2006-2008 the V8 project authors. All rights reserved.
+// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@@ -35,34 +35,8 @@
namespace v8 {
namespace internal {
-#ifdef OBJECT_PRINT
-
-static const char* TypeToString(InstanceType type);
-
-
-void MaybeObject::Print(FILE* out) {
- Object* this_as_object;
- if (ToObject(&this_as_object)) {
- if (this_as_object->IsSmi()) {
- Smi::cast(this_as_object)->SmiPrint(out);
- } else {
- HeapObject::cast(this_as_object)->HeapObjectPrint(out);
- }
- } else {
- Failure::cast(this)->FailurePrint(out);
- }
- Flush(out);
-}
-
-
-void MaybeObject::PrintLn(FILE* out) {
- Print(out);
- PrintF(out, "\n");
-}
-#endif // OBJECT_PRINT
-
-
#ifdef DEBUG
+
void MaybeObject::Verify() {
Object* this_as_object;
if (ToObject(&this_as_object)) {
@@ -94,120 +68,8 @@ void Smi::SmiVerify() {
void Failure::FailureVerify() {
ASSERT(IsFailure());
}
-#endif // DEBUG
-
-
-#ifdef OBJECT_PRINT
-void HeapObject::PrintHeader(FILE* out, const char* id) {
- PrintF(out, "%p: [%s]\n", reinterpret_cast<void*>(this), id);
-}
-void HeapObject::HeapObjectPrint(FILE* out) {
- InstanceType instance_type = map()->instance_type();
-
- HandleScope scope;
- if (instance_type < FIRST_NONSTRING_TYPE) {
- String::cast(this)->StringPrint(out);
- return;
- }
-
- switch (instance_type) {
- case MAP_TYPE:
- Map::cast(this)->MapPrint(out);
- break;
- case HEAP_NUMBER_TYPE:
- HeapNumber::cast(this)->HeapNumberPrint(out);
- break;
- case FIXED_ARRAY_TYPE:
- FixedArray::cast(this)->FixedArrayPrint(out);
- break;
- case BYTE_ARRAY_TYPE:
- ByteArray::cast(this)->ByteArrayPrint(out);
- break;
- case PIXEL_ARRAY_TYPE:
- PixelArray::cast(this)->PixelArrayPrint(out);
- break;
- case EXTERNAL_BYTE_ARRAY_TYPE:
- ExternalByteArray::cast(this)->ExternalByteArrayPrint(out);
- break;
- case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
- ExternalUnsignedByteArray::cast(this)
- ->ExternalUnsignedByteArrayPrint(out);
- break;
- case EXTERNAL_SHORT_ARRAY_TYPE:
- ExternalShortArray::cast(this)->ExternalShortArrayPrint(out);
- break;
- case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
- ExternalUnsignedShortArray::cast(this)
- ->ExternalUnsignedShortArrayPrint(out);
- break;
- case EXTERNAL_INT_ARRAY_TYPE:
- ExternalIntArray::cast(this)->ExternalIntArrayPrint(out);
- break;
- case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
- ExternalUnsignedIntArray::cast(this)->ExternalUnsignedIntArrayPrint(out);
- break;
- case EXTERNAL_FLOAT_ARRAY_TYPE:
- ExternalFloatArray::cast(this)->ExternalFloatArrayPrint(out);
- break;
- case FILLER_TYPE:
- PrintF(out, "filler");
- break;
- case JS_OBJECT_TYPE: // fall through
- case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
- case JS_ARRAY_TYPE:
- case JS_REGEXP_TYPE:
- JSObject::cast(this)->JSObjectPrint(out);
- break;
- case ODDBALL_TYPE:
- Oddball::cast(this)->to_string()->Print(out);
- break;
- case JS_FUNCTION_TYPE:
- JSFunction::cast(this)->JSFunctionPrint(out);
- break;
- case JS_GLOBAL_PROXY_TYPE:
- JSGlobalProxy::cast(this)->JSGlobalProxyPrint(out);
- break;
- case JS_GLOBAL_OBJECT_TYPE:
- JSGlobalObject::cast(this)->JSGlobalObjectPrint(out);
- break;
- case JS_BUILTINS_OBJECT_TYPE:
- JSBuiltinsObject::cast(this)->JSBuiltinsObjectPrint(out);
- break;
- case JS_VALUE_TYPE:
- PrintF(out, "Value wrapper around:");
- JSValue::cast(this)->value()->Print(out);
- break;
- case CODE_TYPE:
- Code::cast(this)->CodePrint(out);
- break;
- case PROXY_TYPE:
- Proxy::cast(this)->ProxyPrint(out);
- break;
- case SHARED_FUNCTION_INFO_TYPE:
- SharedFunctionInfo::cast(this)->SharedFunctionInfoPrint(out);
- break;
- case JS_GLOBAL_PROPERTY_CELL_TYPE:
- JSGlobalPropertyCell::cast(this)->JSGlobalPropertyCellPrint(out);
- break;
-#define MAKE_STRUCT_CASE(NAME, Name, name) \
- case NAME##_TYPE: \
- Name::cast(this)->Name##Print(out); \
- break;
- STRUCT_LIST(MAKE_STRUCT_CASE)
-#undef MAKE_STRUCT_CASE
-
- default:
- PrintF(out, "UNKNOWN TYPE %d", map()->instance_type());
- UNREACHABLE();
- break;
- }
-}
-#endif // OBJECT_PRINT
-
-
-#ifdef DEBUG
void HeapObject::HeapObjectVerify() {
InstanceType instance_type = map()->instance_type();
@@ -320,57 +182,8 @@ void HeapObject::VerifyHeapPointer(Object* p) {
void HeapNumber::HeapNumberVerify() {
ASSERT(IsHeapNumber());
}
-#endif // DEBUG
-
-
-#ifdef OBJECT_PRINT
-void ByteArray::ByteArrayPrint(FILE* out) {
- PrintF(out, "byte array, data starts at %p", GetDataStartAddress());
-}
-
-
-void PixelArray::PixelArrayPrint(FILE* out) {
- PrintF(out, "pixel array");
-}
-
-
-void ExternalByteArray::ExternalByteArrayPrint(FILE* out) {
- PrintF(out, "external byte array");
-}
-void ExternalUnsignedByteArray::ExternalUnsignedByteArrayPrint(FILE* out) {
- PrintF(out, "external unsigned byte array");
-}
-
-
-void ExternalShortArray::ExternalShortArrayPrint(FILE* out) {
- PrintF(out, "external short array");
-}
-
-
-void ExternalUnsignedShortArray::ExternalUnsignedShortArrayPrint(FILE* out) {
- PrintF(out, "external unsigned short array");
-}
-
-
-void ExternalIntArray::ExternalIntArrayPrint(FILE* out) {
- PrintF(out, "external int array");
-}
-
-
-void ExternalUnsignedIntArray::ExternalUnsignedIntArrayPrint(FILE* out) {
- PrintF(out, "external unsigned int array");
-}
-
-
-void ExternalFloatArray::ExternalFloatArrayPrint(FILE* out) {
- PrintF(out, "external float array");
-}
-#endif // OBJECT_PRINT
-
-
-#ifdef DEBUG
void ByteArray::ByteArrayVerify() {
ASSERT(IsByteArray());
}
@@ -414,146 +227,8 @@ void ExternalUnsignedIntArray::ExternalUnsignedIntArrayVerify() {
void ExternalFloatArray::ExternalFloatArrayVerify() {
ASSERT(IsExternalFloatArray());
}
-#endif // DEBUG
-
-
-#ifdef OBJECT_PRINT
-void JSObject::PrintProperties(FILE* out) {
- if (HasFastProperties()) {
- DescriptorArray* descs = map()->instance_descriptors();
- for (int i = 0; i < descs->number_of_descriptors(); i++) {
- PrintF(out, " ");
- descs->GetKey(i)->StringPrint(out);
- PrintF(out, ": ");
- switch (descs->GetType(i)) {
- case FIELD: {
- int index = descs->GetFieldIndex(i);
- FastPropertyAt(index)->ShortPrint(out);
- PrintF(out, " (field at offset %d)\n", index);
- break;
- }
- case CONSTANT_FUNCTION:
- descs->GetConstantFunction(i)->ShortPrint(out);
- PrintF(out, " (constant function)\n");
- break;
- case CALLBACKS:
- descs->GetCallbacksObject(i)->ShortPrint(out);
- PrintF(out, " (callback)\n");
- break;
- case MAP_TRANSITION:
- PrintF(out, " (map transition)\n");
- break;
- case CONSTANT_TRANSITION:
- PrintF(out, " (constant transition)\n");
- break;
- case NULL_DESCRIPTOR:
- PrintF(out, " (null descriptor)\n");
- break;
- default:
- UNREACHABLE();
- break;
- }
- }
- } else {
- property_dictionary()->Print(out);
- }
-}
-
-
-void JSObject::PrintElements(FILE* out) {
- switch (GetElementsKind()) {
- case FAST_ELEMENTS: {
- // Print in array notation for non-sparse arrays.
- FixedArray* p = FixedArray::cast(elements());
- for (int i = 0; i < p->length(); i++) {
- PrintF(out, " %d: ", i);
- p->get(i)->ShortPrint(out);
- PrintF(out, "\n");
- }
- break;
- }
- case PIXEL_ELEMENTS: {
- PixelArray* p = PixelArray::cast(elements());
- for (int i = 0; i < p->length(); i++) {
- PrintF(out, " %d: %d\n", i, p->get(i));
- }
- break;
- }
- case EXTERNAL_BYTE_ELEMENTS: {
- ExternalByteArray* p = ExternalByteArray::cast(elements());
- for (int i = 0; i < p->length(); i++) {
- PrintF(out, " %d: %d\n", i, static_cast<int>(p->get(i)));
- }
- break;
- }
- case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: {
- ExternalUnsignedByteArray* p =
- ExternalUnsignedByteArray::cast(elements());
- for (int i = 0; i < p->length(); i++) {
- PrintF(out, " %d: %d\n", i, static_cast<int>(p->get(i)));
- }
- break;
- }
- case EXTERNAL_SHORT_ELEMENTS: {
- ExternalShortArray* p = ExternalShortArray::cast(elements());
- for (int i = 0; i < p->length(); i++) {
- PrintF(out, " %d: %d\n", i, static_cast<int>(p->get(i)));
- }
- break;
- }
- case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: {
- ExternalUnsignedShortArray* p =
- ExternalUnsignedShortArray::cast(elements());
- for (int i = 0; i < p->length(); i++) {
- PrintF(out, " %d: %d\n", i, static_cast<int>(p->get(i)));
- }
- break;
- }
- case EXTERNAL_INT_ELEMENTS: {
- ExternalIntArray* p = ExternalIntArray::cast(elements());
- for (int i = 0; i < p->length(); i++) {
- PrintF(out, " %d: %d\n", i, static_cast<int>(p->get(i)));
- }
- break;
- }
- case EXTERNAL_UNSIGNED_INT_ELEMENTS: {
- ExternalUnsignedIntArray* p =
- ExternalUnsignedIntArray::cast(elements());
- for (int i = 0; i < p->length(); i++) {
- PrintF(out, " %d: %d\n", i, static_cast<int>(p->get(i)));
- }
- break;
- }
- case EXTERNAL_FLOAT_ELEMENTS: {
- ExternalFloatArray* p = ExternalFloatArray::cast(elements());
- for (int i = 0; i < p->length(); i++) {
- PrintF(out, " %d: %f\n", i, p->get(i));
- }
- break;
- }
- case DICTIONARY_ELEMENTS:
- elements()->Print(out);
- break;
- default:
- UNREACHABLE();
- break;
- }
-}
-void JSObject::JSObjectPrint(FILE* out) {
- PrintF(out, "%p: [JSObject]\n", reinterpret_cast<void*>(this));
- PrintF(out, " - map = %p\n", reinterpret_cast<void*>(map()));
- PrintF(out, " - prototype = %p\n", reinterpret_cast<void*>(GetPrototype()));
- PrintF(out, " {\n");
- PrintProperties(out);
- PrintElements(out);
- PrintF(out, " }\n");
-}
-#endif // OBJECT_PRINT
-
-
-#ifdef DEBUG
void JSObject::JSObjectVerify() {
VerifyHeapPointer(properties());
VerifyHeapPointer(elements());
@@ -567,103 +242,8 @@ void JSObject::JSObjectVerify() {
elements()->map() == Heap::fixed_cow_array_map()));
ASSERT(map()->has_fast_elements() == HasFastElements());
}
-#endif // DEBUG
-#ifdef OBJECT_PRINT
-static const char* TypeToString(InstanceType type) {
- switch (type) {
- case INVALID_TYPE: return "INVALID";
- case MAP_TYPE: return "MAP";
- case HEAP_NUMBER_TYPE: return "HEAP_NUMBER";
- case SYMBOL_TYPE: return "SYMBOL";
- case ASCII_SYMBOL_TYPE: return "ASCII_SYMBOL";
- case CONS_SYMBOL_TYPE: return "CONS_SYMBOL";
- case CONS_ASCII_SYMBOL_TYPE: return "CONS_ASCII_SYMBOL";
- case EXTERNAL_ASCII_SYMBOL_TYPE:
- case EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE:
- case EXTERNAL_SYMBOL_TYPE: return "EXTERNAL_SYMBOL";
- case ASCII_STRING_TYPE: return "ASCII_STRING";
- case STRING_TYPE: return "TWO_BYTE_STRING";
- case CONS_STRING_TYPE:
- case CONS_ASCII_STRING_TYPE: return "CONS_STRING";
- case EXTERNAL_ASCII_STRING_TYPE:
- case EXTERNAL_STRING_WITH_ASCII_DATA_TYPE:
- case EXTERNAL_STRING_TYPE: return "EXTERNAL_STRING";
- case FIXED_ARRAY_TYPE: return "FIXED_ARRAY";
- case BYTE_ARRAY_TYPE: return "BYTE_ARRAY";
- case PIXEL_ARRAY_TYPE: return "PIXEL_ARRAY";
- case EXTERNAL_BYTE_ARRAY_TYPE: return "EXTERNAL_BYTE_ARRAY";
- case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
- return "EXTERNAL_UNSIGNED_BYTE_ARRAY";
- case EXTERNAL_SHORT_ARRAY_TYPE: return "EXTERNAL_SHORT_ARRAY";
- case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
- return "EXTERNAL_UNSIGNED_SHORT_ARRAY";
- case EXTERNAL_INT_ARRAY_TYPE: return "EXTERNAL_INT_ARRAY";
- case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
- return "EXTERNAL_UNSIGNED_INT_ARRAY";
- case EXTERNAL_FLOAT_ARRAY_TYPE: return "EXTERNAL_FLOAT_ARRAY";
- case FILLER_TYPE: return "FILLER";
- case JS_OBJECT_TYPE: return "JS_OBJECT";
- case JS_CONTEXT_EXTENSION_OBJECT_TYPE: return "JS_CONTEXT_EXTENSION_OBJECT";
- case ODDBALL_TYPE: return "ODDBALL";
- case JS_GLOBAL_PROPERTY_CELL_TYPE: return "JS_GLOBAL_PROPERTY_CELL";
- case SHARED_FUNCTION_INFO_TYPE: return "SHARED_FUNCTION_INFO";
- case JS_FUNCTION_TYPE: return "JS_FUNCTION";
- case CODE_TYPE: return "CODE";
- case JS_ARRAY_TYPE: return "JS_ARRAY";
- case JS_REGEXP_TYPE: return "JS_REGEXP";
- case JS_VALUE_TYPE: return "JS_VALUE";
- case JS_GLOBAL_OBJECT_TYPE: return "JS_GLOBAL_OBJECT";
- case JS_BUILTINS_OBJECT_TYPE: return "JS_BUILTINS_OBJECT";
- case JS_GLOBAL_PROXY_TYPE: return "JS_GLOBAL_PROXY";
- case PROXY_TYPE: return "PROXY";
-#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return #NAME;
- STRUCT_LIST(MAKE_STRUCT_CASE)
-#undef MAKE_STRUCT_CASE
- }
- return "UNKNOWN";
-}
-
-
-void Map::MapPrint(FILE* out) {
- HeapObject::PrintHeader(out, "Map");
- PrintF(out, " - type: %s\n", TypeToString(instance_type()));
- PrintF(out, " - instance size: %d\n", instance_size());
- PrintF(out, " - inobject properties: %d\n", inobject_properties());
- PrintF(out, " - pre-allocated property fields: %d\n",
- pre_allocated_property_fields());
- PrintF(out, " - unused property fields: %d\n", unused_property_fields());
- if (is_hidden_prototype()) {
- PrintF(out, " - hidden_prototype\n");
- }
- if (has_named_interceptor()) {
- PrintF(out, " - named_interceptor\n");
- }
- if (has_indexed_interceptor()) {
- PrintF(out, " - indexed_interceptor\n");
- }
- if (is_undetectable()) {
- PrintF(out, " - undetectable\n");
- }
- if (has_instance_call_handler()) {
- PrintF(out, " - instance_call_handler\n");
- }
- if (is_access_check_needed()) {
- PrintF(out, " - access_check_needed\n");
- }
- PrintF(out, " - instance descriptors: ");
- instance_descriptors()->ShortPrint(out);
- PrintF(out, "\n - prototype: ");
- prototype()->ShortPrint(out);
- PrintF(out, "\n - constructor: ");
- constructor()->ShortPrint(out);
- PrintF(out, "\n");
-}
-#endif // OBJECT_PRINT
-
-
-#ifdef DEBUG
void Map::MapVerify() {
ASSERT(!Heap::InNewSpace(this));
ASSERT(FIRST_TYPE <= instance_type() && instance_type() <= LAST_TYPE);
@@ -685,21 +265,8 @@ void Map::SharedMapVerify() {
ASSERT_EQ(StaticVisitorBase::GetVisitorId(instance_type(), instance_size()),
visitor_id());
}
-#endif // DEBUG
-
-
-#ifdef OBJECT_PRINT
-void CodeCache::CodeCachePrint(FILE* out) {
- HeapObject::PrintHeader(out, "CodeCache");
- PrintF(out, "\n - default_cache: ");
- default_cache()->ShortPrint(out);
- PrintF(out, "\n - normal_type_cache: ");
- normal_type_cache()->ShortPrint(out);
-}
-#endif // OBJECT_PRINT
-#ifdef DEBUG
void CodeCache::CodeCacheVerify() {
VerifyHeapPointer(default_cache());
VerifyHeapPointer(normal_type_cache());
@@ -707,23 +274,8 @@ void CodeCache::CodeCacheVerify() {
ASSERT(normal_type_cache()->IsUndefined()
|| normal_type_cache()->IsCodeCacheHashTable());
}
-#endif // DEBUG
-
-
-#ifdef OBJECT_PRINT
-void FixedArray::FixedArrayPrint(FILE* out) {
- HeapObject::PrintHeader(out, "FixedArray");
- PrintF(out, " - length: %d", length());
- for (int i = 0; i < length(); i++) {
- PrintF(out, "\n [%d]: ", i);
- get(i)->ShortPrint(out);
- }
- PrintF(out, "\n");
-}
-#endif // OBJECT_PRINT
-#ifdef DEBUG
void FixedArray::FixedArrayVerify() {
for (int i = 0; i < length(); i++) {
Object* e = get(i);
@@ -734,57 +286,16 @@ void FixedArray::FixedArrayVerify() {
}
}
}
-#endif // DEBUG
-
-#ifdef OBJECT_PRINT
-void JSValue::JSValuePrint(FILE* out) {
- HeapObject::PrintHeader(out, "ValueObject");
- value()->Print(out);
-}
-#endif // OBJECT_PRINT
-
-#ifdef DEBUG
void JSValue::JSValueVerify() {
Object* v = value();
if (v->IsHeapObject()) {
VerifyHeapPointer(v);
}
}
-#endif // DEBUG
-
-
-#ifdef OBJECT_PRINT
-void String::StringPrint(FILE* out) {
- if (StringShape(this).IsSymbol()) {
- PrintF(out, "#");
- } else if (StringShape(this).IsCons()) {
- PrintF(out, "c\"");
- } else {
- PrintF(out, "\"");
- }
-
- const char truncated_epilogue[] = "...<truncated>";
- int len = length();
- if (!FLAG_use_verbose_printer) {
- if (len > 100) {
- len = 100 - sizeof(truncated_epilogue);
- }
- }
- for (int i = 0; i < len; i++) {
- PrintF(out, "%c", Get(i));
- }
- if (len != length()) {
- PrintF(out, "%s", truncated_epilogue);
- }
-
- if (!StringShape(this).IsSymbol()) PrintF(out, "\"");
-}
-#endif // OBJECT_PRINT
-#ifdef DEBUG
void String::StringVerify() {
CHECK(IsString());
CHECK(length() >= 0 && length() <= Smi::kMaxValue);
@@ -792,36 +303,8 @@ void String::StringVerify() {
CHECK(!Heap::InNewSpace(this));
}
}
-#endif // DEBUG
-
-
-#ifdef OBJECT_PRINT
-void JSFunction::JSFunctionPrint(FILE* out) {
- HeapObject::PrintHeader(out, "Function");
- PrintF(out, " - map = 0x%p\n", reinterpret_cast<void*>(map()));
- PrintF(out, " - initial_map = ");
- if (has_initial_map()) {
- initial_map()->ShortPrint(out);
- }
- PrintF(out, "\n - shared_info = ");
- shared()->ShortPrint(out);
- PrintF(out, "\n - name = ");
- shared()->name()->Print(out);
- PrintF(out, "\n - context = ");
- unchecked_context()->ShortPrint(out);
- PrintF(out, "\n - code = ");
- code()->ShortPrint(out);
- PrintF(out, "\n");
-
- PrintProperties(out);
- PrintElements(out);
-
- PrintF(out, "\n");
-}
-#endif // OBJECT_PRINT
-#ifdef DEBUG
void JSFunction::JSFunctionVerify() {
CHECK(IsJSFunction());
VerifyObjectField(kPrototypeOrInitialMapOffset);
@@ -829,41 +312,8 @@ void JSFunction::JSFunctionVerify() {
CHECK(next_function_link()->IsUndefined() ||
next_function_link()->IsJSFunction());
}
-#endif // DEBUG
-
-
-#ifdef OBJECT_PRINT
-void SharedFunctionInfo::SharedFunctionInfoPrint(FILE* out) {
- HeapObject::PrintHeader(out, "SharedFunctionInfo");
- PrintF(out, " - name: ");
- name()->ShortPrint(out);
- PrintF(out, "\n - expected_nof_properties: %d", expected_nof_properties());
- PrintF(out, "\n - instance class name = ");
- instance_class_name()->Print(out);
- PrintF(out, "\n - code = ");
- code()->ShortPrint(out);
- PrintF(out, "\n - source code = ");
- GetSourceCode()->ShortPrint(out);
- // Script files are often large, hard to read.
- // PrintF(out, "\n - script =");
- // script()->Print(out);
- PrintF(out, "\n - function token position = %d", function_token_position());
- PrintF(out, "\n - start position = %d", start_position());
- PrintF(out, "\n - end position = %d", end_position());
- PrintF(out, "\n - is expression = %d", is_expression());
- PrintF(out, "\n - debug info = ");
- debug_info()->ShortPrint(out);
- PrintF(out, "\n - length = %d", length());
- PrintF(out, "\n - has_only_simple_this_property_assignments = %d",
- has_only_simple_this_property_assignments());
- PrintF(out, "\n - this_property_assignments = ");
- this_property_assignments()->ShortPrint(out);
- PrintF(out, "\n");
-}
-#endif // OBJECT_PRINT
-#ifdef DEBUG
void SharedFunctionInfo::SharedFunctionInfoVerify() {
CHECK(IsSharedFunctionInfo());
VerifyObjectField(kNameOffset);
@@ -874,21 +324,8 @@ void SharedFunctionInfo::SharedFunctionInfoVerify() {
VerifyObjectField(kScriptOffset);
VerifyObjectField(kDebugInfoOffset);
}
-#endif // DEBUG
-
-
-#ifdef OBJECT_PRINT
-void JSGlobalProxy::JSGlobalProxyPrint(FILE* out) {
- PrintF(out, "global_proxy");
- JSObjectPrint(out);
- PrintF(out, "context : ");
- context()->ShortPrint(out);
- PrintF(out, "\n");
-}
-#endif // OBJECT_PRINT
-#ifdef DEBUG
void JSGlobalProxy::JSGlobalProxyVerify() {
CHECK(IsJSGlobalProxy());
JSObjectVerify();
@@ -898,21 +335,8 @@ void JSGlobalProxy::JSGlobalProxyVerify() {
CHECK(HasFastElements());
CHECK_EQ(0, FixedArray::cast(elements())->length());
}
-#endif // DEBUG
-
-
-#ifdef OBJECT_PRINT
-void JSGlobalObject::JSGlobalObjectPrint(FILE* out) {
- PrintF(out, "global ");
- JSObjectPrint(out);
- PrintF(out, "global context : ");
- global_context()->ShortPrint(out);
- PrintF(out, "\n");
-}
-#endif // OBJECT_PRINT
-#ifdef DEBUG
void JSGlobalObject::JSGlobalObjectVerify() {
CHECK(IsJSGlobalObject());
JSObjectVerify();
@@ -922,18 +346,8 @@ void JSGlobalObject::JSGlobalObjectVerify() {
VerifyObjectField(i);
}
}
-#endif // DEBUG
-#ifdef OBJECT_PRINT
-void JSBuiltinsObject::JSBuiltinsObjectPrint(FILE* out) {
- PrintF(out, "builtins ");
- JSObjectPrint(out);
-}
-#endif // OBJECT_PRINT
-
-
-#ifdef DEBUG
void JSBuiltinsObject::JSBuiltinsObjectVerify() {
CHECK(IsJSBuiltinsObject());
JSObjectVerify();
@@ -964,27 +378,8 @@ void JSGlobalPropertyCell::JSGlobalPropertyCellVerify() {
CHECK(IsJSGlobalPropertyCell());
VerifyObjectField(kValueOffset);
}
-#endif // DEBUG
-
-
-#ifdef OBJECT_PRINT
-void JSGlobalPropertyCell::JSGlobalPropertyCellPrint(FILE* out) {
- HeapObject::PrintHeader(out, "JSGlobalPropertyCell");
-}
-
-
-void Code::CodePrint(FILE* out) {
- HeapObject::PrintHeader(out, "Code");
-#ifdef ENABLE_DISASSEMBLER
- if (FLAG_use_verbose_printer) {
- Disassemble(NULL, out);
- }
-#endif
-}
-#endif // OBJECT_PRINT
-#ifdef DEBUG
void Code::CodeVerify() {
CHECK(IsAligned(reinterpret_cast<intptr_t>(instruction_start()),
kCodeAlignment));
@@ -1039,17 +434,8 @@ void JSRegExp::JSRegExpVerify() {
break;
}
}
-#endif // DEBUG
-
-
-#ifdef OBJECT_PRINT
-void Proxy::ProxyPrint(FILE* out) {
- PrintF(out, "proxy to %p", proxy());
-}
-#endif // OBJECT_PRINT
-#ifdef DEBUG
void Proxy::ProxyVerify() {
ASSERT(IsProxy());
}
@@ -1063,50 +449,16 @@ void AccessorInfo::AccessorInfoVerify() {
VerifyPointer(data());
VerifyPointer(flag());
}
-#endif // DEBUG
-
-
-#ifdef OBJECT_PRINT
-void AccessorInfo::AccessorInfoPrint(FILE* out) {
- HeapObject::PrintHeader(out, "AccessorInfo");
- PrintF(out, "\n - getter: ");
- getter()->ShortPrint(out);
- PrintF(out, "\n - setter: ");
- setter()->ShortPrint(out);
- PrintF(out, "\n - name: ");
- name()->ShortPrint(out);
- PrintF(out, "\n - data: ");
- data()->ShortPrint(out);
- PrintF(out, "\n - flag: ");
- flag()->ShortPrint(out);
-}
-#endif // OBJECT_PRINT
-#ifdef DEBUG
void AccessCheckInfo::AccessCheckInfoVerify() {
CHECK(IsAccessCheckInfo());
VerifyPointer(named_callback());
VerifyPointer(indexed_callback());
VerifyPointer(data());
}
-#endif // DEBUG
-
-
-#ifdef OBJECT_PRINT
-void AccessCheckInfo::AccessCheckInfoPrint(FILE* out) {
- HeapObject::PrintHeader(out, "AccessCheckInfo");
- PrintF(out, "\n - named_callback: ");
- named_callback()->ShortPrint(out);
- PrintF(out, "\n - indexed_callback: ");
- indexed_callback()->ShortPrint(out);
- PrintF(out, "\n - data: ");
- data()->ShortPrint(out);
-}
-#endif // OBJECT_PRINT
-#ifdef DEBUG
void InterceptorInfo::InterceptorInfoVerify() {
CHECK(IsInterceptorInfo());
VerifyPointer(getter());
@@ -1116,50 +468,15 @@ void InterceptorInfo::InterceptorInfoVerify() {
VerifyPointer(enumerator());
VerifyPointer(data());
}
-#endif // DEBUG
-
-
-#ifdef OBJECT_PRINT
-void InterceptorInfo::InterceptorInfoPrint(FILE* out) {
- HeapObject::PrintHeader(out, "InterceptorInfo");
- PrintF(out, "\n - getter: ");
- getter()->ShortPrint(out);
- PrintF(out, "\n - setter: ");
- setter()->ShortPrint(out);
- PrintF(out, "\n - query: ");
- query()->ShortPrint(out);
- PrintF(out, "\n - deleter: ");
- deleter()->ShortPrint(out);
- PrintF(out, "\n - enumerator: ");
- enumerator()->ShortPrint(out);
- PrintF(out, "\n - data: ");
- data()->ShortPrint(out);
-}
-#endif // OBJECT_PRINT
-#ifdef DEBUG
void CallHandlerInfo::CallHandlerInfoVerify() {
CHECK(IsCallHandlerInfo());
VerifyPointer(callback());
VerifyPointer(data());
}
-#endif // DEBUG
-
-
-#ifdef OBJECT_PRINT
-void CallHandlerInfo::CallHandlerInfoPrint(FILE* out) {
- HeapObject::PrintHeader(out, "CallHandlerInfo");
- PrintF(out, "\n - callback: ");
- callback()->ShortPrint(out);
- PrintF(out, "\n - data: ");
- data()->ShortPrint(out);
- PrintF(out, "\n - call_stub_cache: ");
-}
-#endif // OBJECT_PRINT
-#ifdef DEBUG
void TemplateInfo::TemplateInfoVerify() {
VerifyPointer(tag());
VerifyPointer(property_list());
@@ -1179,106 +496,29 @@ void FunctionTemplateInfo::FunctionTemplateInfoVerify() {
VerifyPointer(signature());
VerifyPointer(access_check_info());
}
-#endif // DEBUG
-
-
-#ifdef OBJECT_PRINT
-void FunctionTemplateInfo::FunctionTemplateInfoPrint(FILE* out) {
- HeapObject::PrintHeader(out, "FunctionTemplateInfo");
- PrintF(out, "\n - class name: ");
- class_name()->ShortPrint(out);
- PrintF(out, "\n - tag: ");
- tag()->ShortPrint(out);
- PrintF(out, "\n - property_list: ");
- property_list()->ShortPrint(out);
- PrintF(out, "\n - serial_number: ");
- serial_number()->ShortPrint(out);
- PrintF(out, "\n - call_code: ");
- call_code()->ShortPrint(out);
- PrintF(out, "\n - property_accessors: ");
- property_accessors()->ShortPrint(out);
- PrintF(out, "\n - prototype_template: ");
- prototype_template()->ShortPrint(out);
- PrintF(out, "\n - parent_template: ");
- parent_template()->ShortPrint(out);
- PrintF(out, "\n - named_property_handler: ");
- named_property_handler()->ShortPrint(out);
- PrintF(out, "\n - indexed_property_handler: ");
- indexed_property_handler()->ShortPrint(out);
- PrintF(out, "\n - instance_template: ");
- instance_template()->ShortPrint(out);
- PrintF(out, "\n - signature: ");
- signature()->ShortPrint(out);
- PrintF(out, "\n - access_check_info: ");
- access_check_info()->ShortPrint(out);
- PrintF(out, "\n - hidden_prototype: %s",
- hidden_prototype() ? "true" : "false");
- PrintF(out, "\n - undetectable: %s", undetectable() ? "true" : "false");
- PrintF(out, "\n - need_access_check: %s",
- needs_access_check() ? "true" : "false");
-}
-#endif // OBJECT_PRINT
-#ifdef DEBUG
void ObjectTemplateInfo::ObjectTemplateInfoVerify() {
CHECK(IsObjectTemplateInfo());
TemplateInfoVerify();
VerifyPointer(constructor());
VerifyPointer(internal_field_count());
}
-#endif // DEBUG
-
-
-#ifdef OBJECT_PRINT
-void ObjectTemplateInfo::ObjectTemplateInfoPrint(FILE* out) {
- HeapObject::PrintHeader(out, "ObjectTemplateInfo");
- PrintF(out, "\n - constructor: ");
- constructor()->ShortPrint(out);
- PrintF(out, "\n - internal_field_count: ");
- internal_field_count()->ShortPrint(out);
-}
-#endif // OBJECT_PRINT
-#ifdef DEBUG
void SignatureInfo::SignatureInfoVerify() {
CHECK(IsSignatureInfo());
VerifyPointer(receiver());
VerifyPointer(args());
}
-#endif // DEBUG
-
-
-#ifdef OBJECT_PRINT
-void SignatureInfo::SignatureInfoPrint(FILE* out) {
- HeapObject::PrintHeader(out, "SignatureInfo");
- PrintF(out, "\n - receiver: ");
- receiver()->ShortPrint(out);
- PrintF(out, "\n - args: ");
- args()->ShortPrint(out);
-}
-#endif // OBJECT_PRINT
-#ifdef DEBUG
void TypeSwitchInfo::TypeSwitchInfoVerify() {
CHECK(IsTypeSwitchInfo());
VerifyPointer(types());
}
-#endif // DEBUG
-
-
-#ifdef OBJECT_PRINT
-void TypeSwitchInfo::TypeSwitchInfoPrint(FILE* out) {
- HeapObject::PrintHeader(out, "TypeSwitchInfo");
- PrintF(out, "\n - types: ");
- types()->ShortPrint(out);
-}
-#endif // OBJECT_PRINT
-#ifdef DEBUG
void Script::ScriptVerify() {
CHECK(IsScript());
VerifyPointer(source());
@@ -1291,45 +531,9 @@ void Script::ScriptVerify() {
VerifyPointer(line_ends());
VerifyPointer(id());
}
-#endif // DEBUG
-
-
-#ifdef OBJECT_PRINT
-void Script::ScriptPrint(FILE* out) {
- HeapObject::PrintHeader(out, "Script");
- PrintF(out, "\n - source: ");
- source()->ShortPrint(out);
- PrintF(out, "\n - name: ");
- name()->ShortPrint(out);
- PrintF(out, "\n - line_offset: ");
- line_offset()->ShortPrint(out);
- PrintF(out, "\n - column_offset: ");
- column_offset()->ShortPrint(out);
- PrintF(out, "\n - type: ");
- type()->ShortPrint(out);
- PrintF(out, "\n - id: ");
- id()->ShortPrint(out);
- PrintF(out, "\n - data: ");
- data()->ShortPrint(out);
- PrintF(out, "\n - context data: ");
- context_data()->ShortPrint(out);
- PrintF(out, "\n - wrapper: ");
- wrapper()->ShortPrint(out);
- PrintF(out, "\n - compilation type: ");
- compilation_type()->ShortPrint(out);
- PrintF(out, "\n - line ends: ");
- line_ends()->ShortPrint(out);
- PrintF(out, "\n - eval from shared: ");
- eval_from_shared()->ShortPrint(out);
- PrintF(out, "\n - eval from instructions offset: ");
- eval_from_instructions_offset()->ShortPrint(out);
- PrintF(out, "\n");
-}
-#endif // OBJECT_PRINT
#ifdef ENABLE_DEBUGGER_SUPPORT
-#ifdef DEBUG
void DebugInfo::DebugInfoVerify() {
CHECK(IsDebugInfo());
VerifyPointer(shared());
@@ -1337,25 +541,8 @@ void DebugInfo::DebugInfoVerify() {
VerifyPointer(code());
VerifyPointer(break_points());
}
-#endif // DEBUG
-
-
-#ifdef OBJECT_PRINT
-void DebugInfo::DebugInfoPrint(FILE* out) {
- HeapObject::PrintHeader(out, "DebugInfo");
- PrintF(out, "\n - shared: ");
- shared()->ShortPrint(out);
- PrintF(out, "\n - original_code: ");
- original_code()->ShortPrint(out);
- PrintF(out, "\n - code: ");
- code()->ShortPrint(out);
- PrintF(out, "\n - break_points: ");
- break_points()->Print(out);
-}
-#endif // OBJECT_PRINT
-#ifdef DEBUG
void BreakPointInfo::BreakPointInfoVerify() {
CHECK(IsBreakPointInfo());
code_position()->SmiVerify();
@@ -1363,23 +550,9 @@ void BreakPointInfo::BreakPointInfoVerify() {
statement_position()->SmiVerify();
VerifyPointer(break_point_objects());
}
-#endif // DEBUG
-
-
-#ifdef OBJECT_PRINT
-void BreakPointInfo::BreakPointInfoPrint(FILE* out) {
- HeapObject::PrintHeader(out, "BreakPointInfo");
- PrintF(out, "\n - code_position: %d", code_position()->value());
- PrintF(out, "\n - source_position: %d", source_position()->value());
- PrintF(out, "\n - statement_position: %d", statement_position()->value());
- PrintF(out, "\n - break_point_objects: ");
- break_point_objects()->ShortPrint(out);
-}
-#endif // OBJECT_PRINT
#endif // ENABLE_DEBUGGER_SUPPORT
-#ifdef DEBUG
void JSObject::IncrementSpillStatistics(SpillInformation* info) {
info->number_of_objects_++;
// Named properties
@@ -1462,24 +635,8 @@ void JSObject::SpillInformation::Print() {
PrintF("\n");
}
-#endif // DEBUG
-
-
-#ifdef OBJECT_PRINT
-void DescriptorArray::PrintDescriptors(FILE* out) {
- PrintF(out, "Descriptor array %d\n", number_of_descriptors());
- for (int i = 0; i < number_of_descriptors(); i++) {
- PrintF(out, " %d: ", i);
- Descriptor desc;
- Get(i, &desc);
- desc.Print(out);
- }
- PrintF(out, "\n");
-}
-#endif // OBJECT_PRINT
-#ifdef DEBUG
bool DescriptorArray::IsSortedNoDuplicates() {
String* current_key = NULL;
uint32_t current = 0;
diff --git a/src/objects-printer.cc b/src/objects-printer.cc
new file mode 100644
index 00000000..9879da25
--- /dev/null
+++ b/src/objects-printer.cc
@@ -0,0 +1,778 @@
+// 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 "disassembler.h"
+#include "disasm.h"
+#include "jsregexp.h"
+#include "objects-visiting.h"
+
+namespace v8 {
+namespace internal {
+
+#ifdef OBJECT_PRINT
+
+static const char* TypeToString(InstanceType type);
+
+
+void MaybeObject::Print(FILE* out) {
+ Object* this_as_object;
+ if (ToObject(&this_as_object)) {
+ if (this_as_object->IsSmi()) {
+ Smi::cast(this_as_object)->SmiPrint(out);
+ } else {
+ HeapObject::cast(this_as_object)->HeapObjectPrint(out);
+ }
+ } else {
+ Failure::cast(this)->FailurePrint(out);
+ }
+ Flush(out);
+}
+
+
+void MaybeObject::PrintLn(FILE* out) {
+ Print(out);
+ PrintF(out, "\n");
+}
+
+
+void HeapObject::PrintHeader(FILE* out, const char* id) {
+ PrintF(out, "%p: [%s]\n", reinterpret_cast<void*>(this), id);
+}
+
+
+void HeapObject::HeapObjectPrint(FILE* out) {
+ InstanceType instance_type = map()->instance_type();
+
+ HandleScope scope;
+ if (instance_type < FIRST_NONSTRING_TYPE) {
+ String::cast(this)->StringPrint(out);
+ return;
+ }
+
+ switch (instance_type) {
+ case MAP_TYPE:
+ Map::cast(this)->MapPrint(out);
+ break;
+ case HEAP_NUMBER_TYPE:
+ HeapNumber::cast(this)->HeapNumberPrint(out);
+ break;
+ case FIXED_ARRAY_TYPE:
+ FixedArray::cast(this)->FixedArrayPrint(out);
+ break;
+ case BYTE_ARRAY_TYPE:
+ ByteArray::cast(this)->ByteArrayPrint(out);
+ break;
+ case PIXEL_ARRAY_TYPE:
+ PixelArray::cast(this)->PixelArrayPrint(out);
+ break;
+ case EXTERNAL_BYTE_ARRAY_TYPE:
+ ExternalByteArray::cast(this)->ExternalByteArrayPrint(out);
+ break;
+ case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
+ ExternalUnsignedByteArray::cast(this)
+ ->ExternalUnsignedByteArrayPrint(out);
+ break;
+ case EXTERNAL_SHORT_ARRAY_TYPE:
+ ExternalShortArray::cast(this)->ExternalShortArrayPrint(out);
+ break;
+ case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
+ ExternalUnsignedShortArray::cast(this)
+ ->ExternalUnsignedShortArrayPrint(out);
+ break;
+ case EXTERNAL_INT_ARRAY_TYPE:
+ ExternalIntArray::cast(this)->ExternalIntArrayPrint(out);
+ break;
+ case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
+ ExternalUnsignedIntArray::cast(this)->ExternalUnsignedIntArrayPrint(out);
+ break;
+ case EXTERNAL_FLOAT_ARRAY_TYPE:
+ ExternalFloatArray::cast(this)->ExternalFloatArrayPrint(out);
+ break;
+ case FILLER_TYPE:
+ PrintF(out, "filler");
+ break;
+ case JS_OBJECT_TYPE: // fall through
+ case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
+ case JS_ARRAY_TYPE:
+ case JS_REGEXP_TYPE:
+ JSObject::cast(this)->JSObjectPrint(out);
+ break;
+ case ODDBALL_TYPE:
+ Oddball::cast(this)->to_string()->Print(out);
+ break;
+ case JS_FUNCTION_TYPE:
+ JSFunction::cast(this)->JSFunctionPrint(out);
+ break;
+ case JS_GLOBAL_PROXY_TYPE:
+ JSGlobalProxy::cast(this)->JSGlobalProxyPrint(out);
+ break;
+ case JS_GLOBAL_OBJECT_TYPE:
+ JSGlobalObject::cast(this)->JSGlobalObjectPrint(out);
+ break;
+ case JS_BUILTINS_OBJECT_TYPE:
+ JSBuiltinsObject::cast(this)->JSBuiltinsObjectPrint(out);
+ break;
+ case JS_VALUE_TYPE:
+ PrintF(out, "Value wrapper around:");
+ JSValue::cast(this)->value()->Print(out);
+ break;
+ case CODE_TYPE:
+ Code::cast(this)->CodePrint(out);
+ break;
+ case PROXY_TYPE:
+ Proxy::cast(this)->ProxyPrint(out);
+ break;
+ case SHARED_FUNCTION_INFO_TYPE:
+ SharedFunctionInfo::cast(this)->SharedFunctionInfoPrint(out);
+ break;
+ case JS_GLOBAL_PROPERTY_CELL_TYPE:
+ JSGlobalPropertyCell::cast(this)->JSGlobalPropertyCellPrint(out);
+ break;
+#define MAKE_STRUCT_CASE(NAME, Name, name) \
+ case NAME##_TYPE: \
+ Name::cast(this)->Name##Print(out); \
+ break;
+ STRUCT_LIST(MAKE_STRUCT_CASE)
+#undef MAKE_STRUCT_CASE
+
+ default:
+ PrintF(out, "UNKNOWN TYPE %d", map()->instance_type());
+ UNREACHABLE();
+ break;
+ }
+}
+
+
+void ByteArray::ByteArrayPrint(FILE* out) {
+ PrintF(out, "byte array, data starts at %p", GetDataStartAddress());
+}
+
+
+void PixelArray::PixelArrayPrint(FILE* out) {
+ PrintF(out, "pixel array");
+}
+
+
+void ExternalByteArray::ExternalByteArrayPrint(FILE* out) {
+ PrintF(out, "external byte array");
+}
+
+
+void ExternalUnsignedByteArray::ExternalUnsignedByteArrayPrint(FILE* out) {
+ PrintF(out, "external unsigned byte array");
+}
+
+
+void ExternalShortArray::ExternalShortArrayPrint(FILE* out) {
+ PrintF(out, "external short array");
+}
+
+
+void ExternalUnsignedShortArray::ExternalUnsignedShortArrayPrint(FILE* out) {
+ PrintF(out, "external unsigned short array");
+}
+
+
+void ExternalIntArray::ExternalIntArrayPrint(FILE* out) {
+ PrintF(out, "external int array");
+}
+
+
+void ExternalUnsignedIntArray::ExternalUnsignedIntArrayPrint(FILE* out) {
+ PrintF(out, "external unsigned int array");
+}
+
+
+void ExternalFloatArray::ExternalFloatArrayPrint(FILE* out) {
+ PrintF(out, "external float array");
+}
+
+
+void JSObject::PrintProperties(FILE* out) {
+ if (HasFastProperties()) {
+ DescriptorArray* descs = map()->instance_descriptors();
+ for (int i = 0; i < descs->number_of_descriptors(); i++) {
+ PrintF(out, " ");
+ descs->GetKey(i)->StringPrint(out);
+ PrintF(out, ": ");
+ switch (descs->GetType(i)) {
+ case FIELD: {
+ int index = descs->GetFieldIndex(i);
+ FastPropertyAt(index)->ShortPrint(out);
+ PrintF(out, " (field at offset %d)\n", index);
+ break;
+ }
+ case CONSTANT_FUNCTION:
+ descs->GetConstantFunction(i)->ShortPrint(out);
+ PrintF(out, " (constant function)\n");
+ break;
+ case CALLBACKS:
+ descs->GetCallbacksObject(i)->ShortPrint(out);
+ PrintF(out, " (callback)\n");
+ break;
+ case MAP_TRANSITION:
+ PrintF(out, " (map transition)\n");
+ break;
+ case CONSTANT_TRANSITION:
+ PrintF(out, " (constant transition)\n");
+ break;
+ case NULL_DESCRIPTOR:
+ PrintF(out, " (null descriptor)\n");
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ }
+ } else {
+ property_dictionary()->Print(out);
+ }
+}
+
+
+void JSObject::PrintElements(FILE* out) {
+ switch (GetElementsKind()) {
+ case FAST_ELEMENTS: {
+ // Print in array notation for non-sparse arrays.
+ FixedArray* p = FixedArray::cast(elements());
+ for (int i = 0; i < p->length(); i++) {
+ PrintF(out, " %d: ", i);
+ p->get(i)->ShortPrint(out);
+ PrintF(out, "\n");
+ }
+ break;
+ }
+ case PIXEL_ELEMENTS: {
+ PixelArray* p = PixelArray::cast(elements());
+ for (int i = 0; i < p->length(); i++) {
+ PrintF(out, " %d: %d\n", i, p->get(i));
+ }
+ break;
+ }
+ case EXTERNAL_BYTE_ELEMENTS: {
+ ExternalByteArray* p = ExternalByteArray::cast(elements());
+ for (int i = 0; i < p->length(); i++) {
+ PrintF(out, " %d: %d\n", i, static_cast<int>(p->get(i)));
+ }
+ break;
+ }
+ case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: {
+ ExternalUnsignedByteArray* p =
+ ExternalUnsignedByteArray::cast(elements());
+ for (int i = 0; i < p->length(); i++) {
+ PrintF(out, " %d: %d\n", i, static_cast<int>(p->get(i)));
+ }
+ break;
+ }
+ case EXTERNAL_SHORT_ELEMENTS: {
+ ExternalShortArray* p = ExternalShortArray::cast(elements());
+ for (int i = 0; i < p->length(); i++) {
+ PrintF(out, " %d: %d\n", i, static_cast<int>(p->get(i)));
+ }
+ break;
+ }
+ case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: {
+ ExternalUnsignedShortArray* p =
+ ExternalUnsignedShortArray::cast(elements());
+ for (int i = 0; i < p->length(); i++) {
+ PrintF(out, " %d: %d\n", i, static_cast<int>(p->get(i)));
+ }
+ break;
+ }
+ case EXTERNAL_INT_ELEMENTS: {
+ ExternalIntArray* p = ExternalIntArray::cast(elements());
+ for (int i = 0; i < p->length(); i++) {
+ PrintF(out, " %d: %d\n", i, static_cast<int>(p->get(i)));
+ }
+ break;
+ }
+ case EXTERNAL_UNSIGNED_INT_ELEMENTS: {
+ ExternalUnsignedIntArray* p =
+ ExternalUnsignedIntArray::cast(elements());
+ for (int i = 0; i < p->length(); i++) {
+ PrintF(out, " %d: %d\n", i, static_cast<int>(p->get(i)));
+ }
+ break;
+ }
+ case EXTERNAL_FLOAT_ELEMENTS: {
+ ExternalFloatArray* p = ExternalFloatArray::cast(elements());
+ for (int i = 0; i < p->length(); i++) {
+ PrintF(out, " %d: %f\n", i, p->get(i));
+ }
+ break;
+ }
+ case DICTIONARY_ELEMENTS:
+ elements()->Print(out);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+
+void JSObject::JSObjectPrint(FILE* out) {
+ PrintF(out, "%p: [JSObject]\n", reinterpret_cast<void*>(this));
+ PrintF(out, " - map = %p\n", reinterpret_cast<void*>(map()));
+ PrintF(out, " - prototype = %p\n", reinterpret_cast<void*>(GetPrototype()));
+ PrintF(out, " {\n");
+ PrintProperties(out);
+ PrintElements(out);
+ PrintF(out, " }\n");
+}
+
+
+static const char* TypeToString(InstanceType type) {
+ switch (type) {
+ case INVALID_TYPE: return "INVALID";
+ case MAP_TYPE: return "MAP";
+ case HEAP_NUMBER_TYPE: return "HEAP_NUMBER";
+ case SYMBOL_TYPE: return "SYMBOL";
+ case ASCII_SYMBOL_TYPE: return "ASCII_SYMBOL";
+ case CONS_SYMBOL_TYPE: return "CONS_SYMBOL";
+ case CONS_ASCII_SYMBOL_TYPE: return "CONS_ASCII_SYMBOL";
+ case EXTERNAL_ASCII_SYMBOL_TYPE:
+ case EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE:
+ case EXTERNAL_SYMBOL_TYPE: return "EXTERNAL_SYMBOL";
+ case ASCII_STRING_TYPE: return "ASCII_STRING";
+ case STRING_TYPE: return "TWO_BYTE_STRING";
+ case CONS_STRING_TYPE:
+ case CONS_ASCII_STRING_TYPE: return "CONS_STRING";
+ case EXTERNAL_ASCII_STRING_TYPE:
+ case EXTERNAL_STRING_WITH_ASCII_DATA_TYPE:
+ case EXTERNAL_STRING_TYPE: return "EXTERNAL_STRING";
+ case FIXED_ARRAY_TYPE: return "FIXED_ARRAY";
+ case BYTE_ARRAY_TYPE: return "BYTE_ARRAY";
+ case PIXEL_ARRAY_TYPE: return "PIXEL_ARRAY";
+ case EXTERNAL_BYTE_ARRAY_TYPE: return "EXTERNAL_BYTE_ARRAY";
+ case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
+ return "EXTERNAL_UNSIGNED_BYTE_ARRAY";
+ case EXTERNAL_SHORT_ARRAY_TYPE: return "EXTERNAL_SHORT_ARRAY";
+ case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
+ return "EXTERNAL_UNSIGNED_SHORT_ARRAY";
+ case EXTERNAL_INT_ARRAY_TYPE: return "EXTERNAL_INT_ARRAY";
+ case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
+ return "EXTERNAL_UNSIGNED_INT_ARRAY";
+ case EXTERNAL_FLOAT_ARRAY_TYPE: return "EXTERNAL_FLOAT_ARRAY";
+ case FILLER_TYPE: return "FILLER";
+ case JS_OBJECT_TYPE: return "JS_OBJECT";
+ case JS_CONTEXT_EXTENSION_OBJECT_TYPE: return "JS_CONTEXT_EXTENSION_OBJECT";
+ case ODDBALL_TYPE: return "ODDBALL";
+ case JS_GLOBAL_PROPERTY_CELL_TYPE: return "JS_GLOBAL_PROPERTY_CELL";
+ case SHARED_FUNCTION_INFO_TYPE: return "SHARED_FUNCTION_INFO";
+ case JS_FUNCTION_TYPE: return "JS_FUNCTION";
+ case CODE_TYPE: return "CODE";
+ case JS_ARRAY_TYPE: return "JS_ARRAY";
+ case JS_REGEXP_TYPE: return "JS_REGEXP";
+ case JS_VALUE_TYPE: return "JS_VALUE";
+ case JS_GLOBAL_OBJECT_TYPE: return "JS_GLOBAL_OBJECT";
+ case JS_BUILTINS_OBJECT_TYPE: return "JS_BUILTINS_OBJECT";
+ case JS_GLOBAL_PROXY_TYPE: return "JS_GLOBAL_PROXY";
+ case PROXY_TYPE: return "PROXY";
+#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return #NAME;
+ STRUCT_LIST(MAKE_STRUCT_CASE)
+#undef MAKE_STRUCT_CASE
+ }
+ return "UNKNOWN";
+}
+
+
+void Map::MapPrint(FILE* out) {
+ HeapObject::PrintHeader(out, "Map");
+ PrintF(out, " - type: %s\n", TypeToString(instance_type()));
+ PrintF(out, " - instance size: %d\n", instance_size());
+ PrintF(out, " - inobject properties: %d\n", inobject_properties());
+ PrintF(out, " - pre-allocated property fields: %d\n",
+ pre_allocated_property_fields());
+ PrintF(out, " - unused property fields: %d\n", unused_property_fields());
+ if (is_hidden_prototype()) {
+ PrintF(out, " - hidden_prototype\n");
+ }
+ if (has_named_interceptor()) {
+ PrintF(out, " - named_interceptor\n");
+ }
+ if (has_indexed_interceptor()) {
+ PrintF(out, " - indexed_interceptor\n");
+ }
+ if (is_undetectable()) {
+ PrintF(out, " - undetectable\n");
+ }
+ if (has_instance_call_handler()) {
+ PrintF(out, " - instance_call_handler\n");
+ }
+ if (is_access_check_needed()) {
+ PrintF(out, " - access_check_needed\n");
+ }
+ PrintF(out, " - instance descriptors: ");
+ instance_descriptors()->ShortPrint(out);
+ PrintF(out, "\n - prototype: ");
+ prototype()->ShortPrint(out);
+ PrintF(out, "\n - constructor: ");
+ constructor()->ShortPrint(out);
+ PrintF(out, "\n");
+}
+
+
+void CodeCache::CodeCachePrint(FILE* out) {
+ HeapObject::PrintHeader(out, "CodeCache");
+ PrintF(out, "\n - default_cache: ");
+ default_cache()->ShortPrint(out);
+ PrintF(out, "\n - normal_type_cache: ");
+ normal_type_cache()->ShortPrint(out);
+}
+
+
+void FixedArray::FixedArrayPrint(FILE* out) {
+ HeapObject::PrintHeader(out, "FixedArray");
+ PrintF(out, " - length: %d", length());
+ for (int i = 0; i < length(); i++) {
+ PrintF(out, "\n [%d]: ", i);
+ get(i)->ShortPrint(out);
+ }
+ PrintF(out, "\n");
+}
+
+
+void JSValue::JSValuePrint(FILE* out) {
+ HeapObject::PrintHeader(out, "ValueObject");
+ value()->Print(out);
+}
+
+
+void String::StringPrint(FILE* out) {
+ if (StringShape(this).IsSymbol()) {
+ PrintF(out, "#");
+ } else if (StringShape(this).IsCons()) {
+ PrintF(out, "c\"");
+ } else {
+ PrintF(out, "\"");
+ }
+
+ const char truncated_epilogue[] = "...<truncated>";
+ int len = length();
+ if (!FLAG_use_verbose_printer) {
+ if (len > 100) {
+ len = 100 - sizeof(truncated_epilogue);
+ }
+ }
+ for (int i = 0; i < len; i++) {
+ PrintF(out, "%c", Get(i));
+ }
+ if (len != length()) {
+ PrintF(out, "%s", truncated_epilogue);
+ }
+
+ if (!StringShape(this).IsSymbol()) PrintF(out, "\"");
+}
+
+
+void JSFunction::JSFunctionPrint(FILE* out) {
+ HeapObject::PrintHeader(out, "Function");
+ PrintF(out, " - map = 0x%p\n", reinterpret_cast<void*>(map()));
+ PrintF(out, " - initial_map = ");
+ if (has_initial_map()) {
+ initial_map()->ShortPrint(out);
+ }
+ PrintF(out, "\n - shared_info = ");
+ shared()->ShortPrint(out);
+ PrintF(out, "\n - name = ");
+ shared()->name()->Print(out);
+ PrintF(out, "\n - context = ");
+ unchecked_context()->ShortPrint(out);
+ PrintF(out, "\n - code = ");
+ code()->ShortPrint(out);
+ PrintF(out, "\n");
+
+ PrintProperties(out);
+ PrintElements(out);
+
+ PrintF(out, "\n");
+}
+
+
+void SharedFunctionInfo::SharedFunctionInfoPrint(FILE* out) {
+ HeapObject::PrintHeader(out, "SharedFunctionInfo");
+ PrintF(out, " - name: ");
+ name()->ShortPrint(out);
+ PrintF(out, "\n - expected_nof_properties: %d", expected_nof_properties());
+ PrintF(out, "\n - instance class name = ");
+ instance_class_name()->Print(out);
+ PrintF(out, "\n - code = ");
+ code()->ShortPrint(out);
+ PrintF(out, "\n - source code = ");
+ GetSourceCode()->ShortPrint(out);
+ // Script files are often large, hard to read.
+ // PrintF(out, "\n - script =");
+ // script()->Print(out);
+ PrintF(out, "\n - function token position = %d", function_token_position());
+ PrintF(out, "\n - start position = %d", start_position());
+ PrintF(out, "\n - end position = %d", end_position());
+ PrintF(out, "\n - is expression = %d", is_expression());
+ PrintF(out, "\n - debug info = ");
+ debug_info()->ShortPrint(out);
+ PrintF(out, "\n - length = %d", length());
+ PrintF(out, "\n - has_only_simple_this_property_assignments = %d",
+ has_only_simple_this_property_assignments());
+ PrintF(out, "\n - this_property_assignments = ");
+ this_property_assignments()->ShortPrint(out);
+ PrintF(out, "\n");
+}
+
+
+void JSGlobalProxy::JSGlobalProxyPrint(FILE* out) {
+ PrintF(out, "global_proxy");
+ JSObjectPrint(out);
+ PrintF(out, "context : ");
+ context()->ShortPrint(out);
+ PrintF(out, "\n");
+}
+
+
+void JSGlobalObject::JSGlobalObjectPrint(FILE* out) {
+ PrintF(out, "global ");
+ JSObjectPrint(out);
+ PrintF(out, "global context : ");
+ global_context()->ShortPrint(out);
+ PrintF(out, "\n");
+}
+
+
+void JSBuiltinsObject::JSBuiltinsObjectPrint(FILE* out) {
+ PrintF(out, "builtins ");
+ JSObjectPrint(out);
+}
+
+
+void JSGlobalPropertyCell::JSGlobalPropertyCellPrint(FILE* out) {
+ HeapObject::PrintHeader(out, "JSGlobalPropertyCell");
+}
+
+
+void Code::CodePrint(FILE* out) {
+ HeapObject::PrintHeader(out, "Code");
+#ifdef ENABLE_DISASSEMBLER
+ if (FLAG_use_verbose_printer) {
+ Disassemble(NULL, out);
+ }
+#endif
+}
+
+
+void Proxy::ProxyPrint(FILE* out) {
+ PrintF(out, "proxy to %p", proxy());
+}
+
+
+void AccessorInfo::AccessorInfoPrint(FILE* out) {
+ HeapObject::PrintHeader(out, "AccessorInfo");
+ PrintF(out, "\n - getter: ");
+ getter()->ShortPrint(out);
+ PrintF(out, "\n - setter: ");
+ setter()->ShortPrint(out);
+ PrintF(out, "\n - name: ");
+ name()->ShortPrint(out);
+ PrintF(out, "\n - data: ");
+ data()->ShortPrint(out);
+ PrintF(out, "\n - flag: ");
+ flag()->ShortPrint(out);
+}
+
+
+void AccessCheckInfo::AccessCheckInfoPrint(FILE* out) {
+ HeapObject::PrintHeader(out, "AccessCheckInfo");
+ PrintF(out, "\n - named_callback: ");
+ named_callback()->ShortPrint(out);
+ PrintF(out, "\n - indexed_callback: ");
+ indexed_callback()->ShortPrint(out);
+ PrintF(out, "\n - data: ");
+ data()->ShortPrint(out);
+}
+
+
+void InterceptorInfo::InterceptorInfoPrint(FILE* out) {
+ HeapObject::PrintHeader(out, "InterceptorInfo");
+ PrintF(out, "\n - getter: ");
+ getter()->ShortPrint(out);
+ PrintF(out, "\n - setter: ");
+ setter()->ShortPrint(out);
+ PrintF(out, "\n - query: ");
+ query()->ShortPrint(out);
+ PrintF(out, "\n - deleter: ");
+ deleter()->ShortPrint(out);
+ PrintF(out, "\n - enumerator: ");
+ enumerator()->ShortPrint(out);
+ PrintF(out, "\n - data: ");
+ data()->ShortPrint(out);
+}
+
+
+void CallHandlerInfo::CallHandlerInfoPrint(FILE* out) {
+ HeapObject::PrintHeader(out, "CallHandlerInfo");
+ PrintF(out, "\n - callback: ");
+ callback()->ShortPrint(out);
+ PrintF(out, "\n - data: ");
+ data()->ShortPrint(out);
+ PrintF(out, "\n - call_stub_cache: ");
+}
+
+
+void FunctionTemplateInfo::FunctionTemplateInfoPrint(FILE* out) {
+ HeapObject::PrintHeader(out, "FunctionTemplateInfo");
+ PrintF(out, "\n - class name: ");
+ class_name()->ShortPrint(out);
+ PrintF(out, "\n - tag: ");
+ tag()->ShortPrint(out);
+ PrintF(out, "\n - property_list: ");
+ property_list()->ShortPrint(out);
+ PrintF(out, "\n - serial_number: ");
+ serial_number()->ShortPrint(out);
+ PrintF(out, "\n - call_code: ");
+ call_code()->ShortPrint(out);
+ PrintF(out, "\n - property_accessors: ");
+ property_accessors()->ShortPrint(out);
+ PrintF(out, "\n - prototype_template: ");
+ prototype_template()->ShortPrint(out);
+ PrintF(out, "\n - parent_template: ");
+ parent_template()->ShortPrint(out);
+ PrintF(out, "\n - named_property_handler: ");
+ named_property_handler()->ShortPrint(out);
+ PrintF(out, "\n - indexed_property_handler: ");
+ indexed_property_handler()->ShortPrint(out);
+ PrintF(out, "\n - instance_template: ");
+ instance_template()->ShortPrint(out);
+ PrintF(out, "\n - signature: ");
+ signature()->ShortPrint(out);
+ PrintF(out, "\n - access_check_info: ");
+ access_check_info()->ShortPrint(out);
+ PrintF(out, "\n - hidden_prototype: %s",
+ hidden_prototype() ? "true" : "false");
+ PrintF(out, "\n - undetectable: %s", undetectable() ? "true" : "false");
+ PrintF(out, "\n - need_access_check: %s",
+ needs_access_check() ? "true" : "false");
+}
+
+
+void ObjectTemplateInfo::ObjectTemplateInfoPrint(FILE* out) {
+ HeapObject::PrintHeader(out, "ObjectTemplateInfo");
+ PrintF(out, "\n - constructor: ");
+ constructor()->ShortPrint(out);
+ PrintF(out, "\n - internal_field_count: ");
+ internal_field_count()->ShortPrint(out);
+}
+
+
+void SignatureInfo::SignatureInfoPrint(FILE* out) {
+ HeapObject::PrintHeader(out, "SignatureInfo");
+ PrintF(out, "\n - receiver: ");
+ receiver()->ShortPrint(out);
+ PrintF(out, "\n - args: ");
+ args()->ShortPrint(out);
+}
+
+
+void TypeSwitchInfo::TypeSwitchInfoPrint(FILE* out) {
+ HeapObject::PrintHeader(out, "TypeSwitchInfo");
+ PrintF(out, "\n - types: ");
+ types()->ShortPrint(out);
+}
+
+
+void Script::ScriptPrint(FILE* out) {
+ HeapObject::PrintHeader(out, "Script");
+ PrintF(out, "\n - source: ");
+ source()->ShortPrint(out);
+ PrintF(out, "\n - name: ");
+ name()->ShortPrint(out);
+ PrintF(out, "\n - line_offset: ");
+ line_offset()->ShortPrint(out);
+ PrintF(out, "\n - column_offset: ");
+ column_offset()->ShortPrint(out);
+ PrintF(out, "\n - type: ");
+ type()->ShortPrint(out);
+ PrintF(out, "\n - id: ");
+ id()->ShortPrint(out);
+ PrintF(out, "\n - data: ");
+ data()->ShortPrint(out);
+ PrintF(out, "\n - context data: ");
+ context_data()->ShortPrint(out);
+ PrintF(out, "\n - wrapper: ");
+ wrapper()->ShortPrint(out);
+ PrintF(out, "\n - compilation type: ");
+ compilation_type()->ShortPrint(out);
+ PrintF(out, "\n - line ends: ");
+ line_ends()->ShortPrint(out);
+ PrintF(out, "\n - eval from shared: ");
+ eval_from_shared()->ShortPrint(out);
+ PrintF(out, "\n - eval from instructions offset: ");
+ eval_from_instructions_offset()->ShortPrint(out);
+ PrintF(out, "\n");
+}
+
+
+#ifdef ENABLE_DEBUGGER_SUPPORT
+void DebugInfo::DebugInfoPrint(FILE* out) {
+ HeapObject::PrintHeader(out, "DebugInfo");
+ PrintF(out, "\n - shared: ");
+ shared()->ShortPrint(out);
+ PrintF(out, "\n - original_code: ");
+ original_code()->ShortPrint(out);
+ PrintF(out, "\n - code: ");
+ code()->ShortPrint(out);
+ PrintF(out, "\n - break_points: ");
+ break_points()->Print(out);
+}
+
+
+void BreakPointInfo::BreakPointInfoPrint(FILE* out) {
+ HeapObject::PrintHeader(out, "BreakPointInfo");
+ PrintF(out, "\n - code_position: %d", code_position()->value());
+ PrintF(out, "\n - source_position: %d", source_position()->value());
+ PrintF(out, "\n - statement_position: %d", statement_position()->value());
+ PrintF(out, "\n - break_point_objects: ");
+ break_point_objects()->ShortPrint(out);
+}
+#endif // ENABLE_DEBUGGER_SUPPORT
+
+
+void DescriptorArray::PrintDescriptors(FILE* out) {
+ PrintF(out, "Descriptor array %d\n", number_of_descriptors());
+ for (int i = 0; i < number_of_descriptors(); i++) {
+ PrintF(out, " %d: ", i);
+ Descriptor desc;
+ Get(i, &desc);
+ desc.Print(out);
+ }
+ PrintF(out, "\n");
+}
+
+
+#endif // OBJECT_PRINT
+
+
+} } // namespace v8::internal
diff --git a/src/objects-visiting.h b/src/objects-visiting.h
index 55a0a53a..6510ca80 100644
--- a/src/objects-visiting.h
+++ b/src/objects-visiting.h
@@ -186,9 +186,9 @@ class VisitorDispatchTable {
template<typename StaticVisitor>
class BodyVisitorBase : public AllStatic {
public:
- static inline void IteratePointers(HeapObject* object,
+ INLINE(static void IteratePointers(HeapObject* object,
int start_offset,
- int end_offset) {
+ int end_offset)) {
Object** start_slot = reinterpret_cast<Object**>(object->address() +
start_offset);
Object** end_slot = reinterpret_cast<Object**>(object->address() +
diff --git a/src/objects.cc b/src/objects.cc
index ab2f9644..927194f7 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -2932,7 +2932,6 @@ MaybeObject* JSObject::DefineGetterSetter(String* name,
uint32_t index = 0;
bool is_element = name->AsArrayIndex(&index);
- if (is_element && IsJSArray()) return Heap::undefined_value();
if (is_element) {
switch (GetElementsKind()) {
@@ -5143,6 +5142,26 @@ bool String::IsEqualTo(Vector<const char> str) {
}
+bool String::IsAsciiEqualTo(Vector<const char> str) {
+ int slen = length();
+ if (str.length() != slen) return false;
+ for (int i = 0; i < slen; i++) {
+ if (Get(i) != static_cast<uint16_t>(str[i])) return false;
+ }
+ return true;
+}
+
+
+bool String::IsTwoByteEqualTo(Vector<const uc16> str) {
+ int slen = length();
+ if (str.length() != slen) return false;
+ for (int i = 0; i < slen; i++) {
+ if (Get(i) != str[i]) return false;
+ }
+ return true;
+}
+
+
template <typename schar>
static inline uint32_t HashSequentialString(const schar* chars, int length) {
StringHasher hasher(length);
@@ -6775,7 +6794,8 @@ bool JSObject::HasElementWithReceiver(JSObject* receiver, uint32_t index) {
MaybeObject* JSObject::SetElementWithInterceptor(uint32_t index,
- Object* value) {
+ Object* value,
+ bool check_prototype) {
// Make sure that the top context does not change when doing
// callbacks or interceptor calls.
AssertNoContextChange ncc;
@@ -6799,7 +6819,9 @@ MaybeObject* JSObject::SetElementWithInterceptor(uint32_t index,
if (!result.IsEmpty()) return *value_handle;
}
MaybeObject* raw_result =
- this_handle->SetElementWithoutInterceptor(index, *value_handle);
+ this_handle->SetElementWithoutInterceptor(index,
+ *value_handle,
+ check_prototype);
RETURN_IF_SCHEDULED_EXCEPTION();
return raw_result;
}
@@ -6910,7 +6932,9 @@ MaybeObject* JSObject::SetElementWithCallback(Object* structure,
// Adding n elements in fast case is O(n*n).
// Note: revisit design to have dual undefined values to capture absent
// elements.
-MaybeObject* JSObject::SetFastElement(uint32_t index, Object* value) {
+MaybeObject* JSObject::SetFastElement(uint32_t index,
+ Object* value,
+ bool check_prototype) {
ASSERT(HasFastElements());
Object* elms_obj;
@@ -6920,12 +6944,13 @@ MaybeObject* JSObject::SetFastElement(uint32_t index, Object* value) {
FixedArray* elms = FixedArray::cast(elms_obj);
uint32_t elms_length = static_cast<uint32_t>(elms->length());
- if (!IsJSArray() && (index >= elms_length || elms->get(index)->IsTheHole())) {
- if (SetElementWithCallbackSetterInPrototypes(index, value)) {
- return value;
- }
+ if (check_prototype &&
+ (index >= elms_length || elms->get(index)->IsTheHole()) &&
+ SetElementWithCallbackSetterInPrototypes(index, value)) {
+ return value;
}
+
// Check whether there is extra space in fixed array..
if (index < elms_length) {
elms->set(index, value);
@@ -6963,11 +6988,13 @@ MaybeObject* JSObject::SetFastElement(uint32_t index, Object* value) {
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
ASSERT(HasDictionaryElements());
- return SetElement(index, value);
+ return SetElement(index, value, check_prototype);
}
-MaybeObject* JSObject::SetElement(uint32_t index, Object* value) {
+MaybeObject* JSObject::SetElement(uint32_t index,
+ Object* value,
+ bool check_prototype) {
// Check access rights if needed.
if (IsAccessCheckNeeded() &&
!Top::MayIndexedAccess(this, index, v8::ACCESS_SET)) {
@@ -6981,24 +7008,25 @@ MaybeObject* JSObject::SetElement(uint32_t index, Object* value) {
Object* proto = GetPrototype();
if (proto->IsNull()) return value;
ASSERT(proto->IsJSGlobalObject());
- return JSObject::cast(proto)->SetElement(index, value);
+ return JSObject::cast(proto)->SetElement(index, value, check_prototype);
}
// Check for lookup interceptor
if (HasIndexedInterceptor()) {
- return SetElementWithInterceptor(index, value);
+ return SetElementWithInterceptor(index, value, check_prototype);
}
- return SetElementWithoutInterceptor(index, value);
+ return SetElementWithoutInterceptor(index, value, check_prototype);
}
MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index,
- Object* value) {
+ Object* value,
+ bool check_prototype) {
switch (GetElementsKind()) {
case FAST_ELEMENTS:
// Fast case.
- return SetFastElement(index, value);
+ return SetFastElement(index, value, check_prototype);
case PIXEL_ELEMENTS: {
PixelArray* pixels = PixelArray::cast(elements());
return pixels->SetValue(index, value);
@@ -7051,10 +7079,9 @@ MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index,
}
} else {
// Index not already used. Look for an accessor in the prototype chain.
- if (!IsJSArray()) {
- if (SetElementWithCallbackSetterInPrototypes(index, value)) {
- return value;
- }
+ if (check_prototype &&
+ SetElementWithCallbackSetterInPrototypes(index, value)) {
+ return value;
}
// When we set the is_extensible flag to false we always force
// the element into dictionary mode (and force them to stay there).
@@ -8086,6 +8113,85 @@ class Utf8SymbolKey : public HashTableKey {
};
+template <typename Char>
+class SequentialSymbolKey : public HashTableKey {
+ public:
+ explicit SequentialSymbolKey(Vector<const Char> string)
+ : string_(string), hash_field_(0) { }
+
+ uint32_t Hash() {
+ StringHasher hasher(string_.length());
+
+ // Very long strings have a trivial hash that doesn't inspect the
+ // string contents.
+ if (hasher.has_trivial_hash()) {
+ hash_field_ = hasher.GetHashField();
+ } else {
+ int i = 0;
+ // Do the iterative array index computation as long as there is a
+ // chance this is an array index.
+ while (i < string_.length() && hasher.is_array_index()) {
+ hasher.AddCharacter(static_cast<uc32>(string_[i]));
+ i++;
+ }
+
+ // Process the remaining characters without updating the array
+ // index.
+ while (i < string_.length()) {
+ hasher.AddCharacterNoIndex(static_cast<uc32>(string_[i]));
+ i++;
+ }
+ hash_field_ = hasher.GetHashField();
+ }
+
+ uint32_t result = hash_field_ >> String::kHashShift;
+ ASSERT(result != 0); // Ensure that the hash value of 0 is never computed.
+ return result;
+ }
+
+
+ uint32_t HashForObject(Object* other) {
+ return String::cast(other)->Hash();
+ }
+
+ Vector<const Char> string_;
+ uint32_t hash_field_;
+};
+
+
+
+class AsciiSymbolKey : public SequentialSymbolKey<char> {
+ public:
+ explicit AsciiSymbolKey(Vector<const char> str)
+ : SequentialSymbolKey<char>(str) { }
+
+ bool IsMatch(Object* string) {
+ return String::cast(string)->IsAsciiEqualTo(string_);
+ }
+
+ MaybeObject* AsObject() {
+ if (hash_field_ == 0) Hash();
+ return Heap::AllocateAsciiSymbol(string_, hash_field_);
+ }
+};
+
+
+class TwoByteSymbolKey : public SequentialSymbolKey<uc16> {
+ public:
+ explicit TwoByteSymbolKey(Vector<const uc16> str)
+ : SequentialSymbolKey<uc16>(str) { }
+
+ bool IsMatch(Object* string) {
+ return String::cast(string)->IsTwoByteEqualTo(string_);
+ }
+
+ MaybeObject* AsObject() {
+ if (hash_field_ == 0) Hash();
+ return Heap::AllocateTwoByteSymbol(string_, hash_field_);
+ }
+};
+
+
// SymbolKey carries a string/symbol object as key.
class SymbolKey : public HashTableKey {
public:
@@ -8830,6 +8936,19 @@ MaybeObject* SymbolTable::LookupSymbol(Vector<const char> str, Object** s) {
}
+MaybeObject* SymbolTable::LookupAsciiSymbol(Vector<const char> str,
+ Object** s) {
+ AsciiSymbolKey key(str);
+ return LookupKey(&key, s);
+}
+
+
+MaybeObject* SymbolTable::LookupTwoByteSymbol(Vector<const uc16> str,
+ Object** s) {
+ TwoByteSymbolKey key(str);
+ return LookupKey(&key, s);
+}
+
MaybeObject* SymbolTable::LookupKey(HashTableKey* key, Object** s) {
int entry = FindEntry(key);
diff --git a/src/objects.h b/src/objects.h
index c5fda7d0..eac7f920 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -1505,11 +1505,15 @@ class JSObject: public HeapObject {
bool HasElementWithInterceptor(JSObject* receiver, uint32_t index);
bool HasElementPostInterceptor(JSObject* receiver, uint32_t index);
- MUST_USE_RESULT MaybeObject* SetFastElement(uint32_t index, Object* value);
+ MUST_USE_RESULT MaybeObject* SetFastElement(uint32_t index,
+ Object* value,
+ bool check_prototype = true);
// Set the index'th array element.
// A Failure object is returned if GC is needed.
- MUST_USE_RESULT MaybeObject* SetElement(uint32_t index, Object* value);
+ MUST_USE_RESULT MaybeObject* SetElement(uint32_t index,
+ Object* value,
+ bool check_prototype = true);
// Returns the index'th element.
// The undefined object if index is out of bounds.
@@ -1763,9 +1767,12 @@ class JSObject: public HeapObject {
Object* value,
JSObject* holder);
MUST_USE_RESULT MaybeObject* SetElementWithInterceptor(uint32_t index,
- Object* value);
- MUST_USE_RESULT MaybeObject* SetElementWithoutInterceptor(uint32_t index,
- Object* value);
+ Object* value,
+ bool check_prototype);
+ MUST_USE_RESULT MaybeObject* SetElementWithoutInterceptor(
+ uint32_t index,
+ Object* value,
+ bool check_prototype);
MaybeObject* GetElementPostInterceptor(JSObject* receiver, uint32_t index);
@@ -2327,6 +2334,10 @@ class SymbolTable: public HashTable<SymbolTableShape, HashTableKey*> {
// been enlarged. If the return value is not a failure, the symbol
// pointer *s is set to the symbol found.
MUST_USE_RESULT MaybeObject* LookupSymbol(Vector<const char> str, Object** s);
+ MUST_USE_RESULT MaybeObject* LookupAsciiSymbol(Vector<const char> str,
+ Object** s);
+ MUST_USE_RESULT MaybeObject* LookupTwoByteSymbol(Vector<const uc16> str,
+ Object** s);
MUST_USE_RESULT MaybeObject* LookupString(String* key, Object** s);
// Looks up a symbol that is equal to the given string and returns
@@ -5074,6 +5085,8 @@ class String: public HeapObject {
// String equality operations.
inline bool Equals(String* other);
bool IsEqualTo(Vector<const char> str);
+ bool IsAsciiEqualTo(Vector<const char> str);
+ bool IsTwoByteEqualTo(Vector<const uc16> str);
// Return a UTF8 representation of the string. The string is null
// terminated but may optionally contain nulls. Length is returned
@@ -5245,6 +5258,34 @@ class String: public HeapObject {
int from,
int to);
+ static inline bool IsAscii(const char* chars, int length) {
+ const char* limit = chars + length;
+#ifdef V8_HOST_CAN_READ_UNALIGNED
+ ASSERT(kMaxAsciiCharCode == 0x7F);
+ const uintptr_t non_ascii_mask = kUintptrAllBitsSet / 0xFF * 0x80;
+ while (chars <= limit - sizeof(uintptr_t)) {
+ if (*reinterpret_cast<const uintptr_t*>(chars) & non_ascii_mask) {
+ return false;
+ }
+ chars += sizeof(uintptr_t);
+ }
+#endif
+ while (chars < limit) {
+ if (static_cast<uint8_t>(*chars) > kMaxAsciiCharCodeU) return false;
+ ++chars;
+ }
+ return true;
+ }
+
+ static inline bool IsAscii(const uc16* chars, int length) {
+ const uc16* limit = chars + length;
+ while (chars < limit) {
+ if (*chars > kMaxAsciiCharCodeU) return false;
+ ++chars;
+ }
+ return true;
+ }
+
protected:
class ReadBlockBuffer {
public:
diff --git a/src/parser.cc b/src/parser.cc
index 08f77b8f..55269339 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -323,22 +323,24 @@ TemporaryScope::~TemporaryScope() {
}
-Handle<String> Parser::LookupSymbol(int symbol_id,
- Vector<const char> string) {
+Handle<String> Parser::LookupSymbol(int symbol_id) {
// 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);
+ if (scanner().is_literal_ascii()) {
+ return Factory::LookupAsciiSymbol(scanner().literal_ascii_string());
+ } else {
+ return Factory::LookupTwoByteSymbol(scanner().literal_uc16_string());
+ }
}
- return LookupCachedSymbol(symbol_id, string);
+ return LookupCachedSymbol(symbol_id);
}
-Handle<String> Parser::LookupCachedSymbol(int symbol_id,
- Vector<const char> string) {
+Handle<String> Parser::LookupCachedSymbol(int symbol_id) {
// Make sure the cache is large enough to hold the symbol identifier.
if (symbol_cache_.length() <= symbol_id) {
// Increase length to index + 1.
@@ -347,7 +349,11 @@ Handle<String> Parser::LookupCachedSymbol(int symbol_id,
}
Handle<String> result = symbol_cache_.at(symbol_id);
if (result.is_null()) {
- result = Factory::LookupSymbol(string);
+ if (scanner().is_literal_ascii()) {
+ result = Factory::LookupAsciiSymbol(scanner().literal_ascii_string());
+ } else {
+ result = Factory::LookupTwoByteSymbol(scanner().literal_uc16_string());
+ }
symbol_cache_.at(symbol_id) = result;
return result;
}
@@ -615,11 +621,11 @@ FunctionLiteral* Parser::ParseProgram(Handle<String> source,
// identical calls.
ExternalTwoByteStringUC16CharacterStream stream(
Handle<ExternalTwoByteString>::cast(source), 0, source->length());
- scanner_.Initialize(&stream, JavaScriptScanner::kAllLiterals);
+ scanner_.Initialize(&stream);
return DoParseProgram(source, in_global_context, &zone_scope);
} else {
GenericStringUC16CharacterStream stream(source, 0, source->length());
- scanner_.Initialize(&stream, JavaScriptScanner::kAllLiterals);
+ scanner_.Initialize(&stream);
return DoParseProgram(source, in_global_context, &zone_scope);
}
}
@@ -705,7 +711,7 @@ FunctionLiteral* Parser::ParseLazy(Handle<SharedFunctionInfo> info) {
FunctionLiteral* Parser::ParseLazy(Handle<SharedFunctionInfo> info,
UC16CharacterStream* source,
ZoneScope* zone_scope) {
- scanner_.Initialize(source, JavaScriptScanner::kAllLiterals);
+ scanner_.Initialize(source);
ASSERT(target_stack_ == NULL);
Handle<String> name(String::cast(info->name()));
@@ -757,7 +763,7 @@ Handle<String> Parser::GetSymbol(bool* ok) {
if (pre_data() != NULL) {
symbol_id = pre_data()->GetSymbolIdentifier();
}
- return LookupSymbol(symbol_id, scanner().literal());
+ return LookupSymbol(symbol_id);
}
@@ -2715,8 +2721,9 @@ Expression* Parser::ParsePrimaryExpression(bool* ok) {
case Token::NUMBER: {
Consume(Token::NUMBER);
- double value =
- StringToDouble(scanner().literal(), ALLOW_HEX | ALLOW_OCTALS);
+ ASSERT(scanner().is_literal_ascii());
+ double value = StringToDouble(scanner().literal_ascii_string(),
+ ALLOW_HEX | ALLOW_OCTALS);
result = NewNumberLiteral(value);
break;
}
@@ -2988,14 +2995,22 @@ ObjectLiteral::Property* Parser::ParseObjectLiteralGetSet(bool is_getter,
// { ... , get foo() { ... }, ... , set foo(v) { ... v ... } , ... }
// We have already read the "get" or "set" keyword.
Token::Value next = Next();
- // TODO(820): Allow NUMBER and STRING as well (and handle array indices).
- if (next == Token::IDENTIFIER || Token::IsKeyword(next)) {
- Handle<String> name = GetSymbol(CHECK_OK);
+ bool is_keyword = Token::IsKeyword(next);
+ if (next == Token::IDENTIFIER || next == Token::NUMBER ||
+ next == Token::STRING || is_keyword) {
+ Handle<String> name;
+ if (is_keyword) {
+ name = Factory::LookupAsciiSymbol(Token::String(next));
+ } else {
+ name = GetSymbol(CHECK_OK);
+ }
FunctionLiteral* value =
ParseFunctionLiteral(name,
RelocInfo::kNoPosition,
DECLARATION,
CHECK_OK);
+ // Allow any number of parameters for compatiabilty with JSC.
+ // Specification only allows zero parameters for get and one for set.
ObjectLiteral::Property* property =
new ObjectLiteral::Property(is_getter, value);
return property;
@@ -3066,8 +3081,9 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
}
case Token::NUMBER: {
Consume(Token::NUMBER);
- double value =
- StringToDouble(scanner().literal(), ALLOW_HEX | ALLOW_OCTALS);
+ ASSERT(scanner().is_literal_ascii());
+ double value = StringToDouble(scanner().literal_ascii_string(),
+ ALLOW_HEX | ALLOW_OCTALS);
key = NewNumberLiteral(value);
break;
}
@@ -3137,11 +3153,9 @@ Expression* Parser::ParseRegExpLiteral(bool seen_equal, bool* ok) {
int literal_index = temp_scope_->NextMaterializedLiteralIndex();
- Handle<String> js_pattern =
- Factory::NewStringFromUtf8(scanner().next_literal(), TENURED);
+ Handle<String> js_pattern = NextLiteralString(TENURED);
scanner().ScanRegExpFlags();
- Handle<String> js_flags =
- Factory::NewStringFromUtf8(scanner().next_literal(), TENURED);
+ Handle<String> js_flags = NextLiteralString(TENURED);
Next();
return new RegExpLiteral(js_pattern, js_flags, literal_index);
@@ -3423,10 +3437,10 @@ Handle<String> Parser::ParseIdentifierOrGetOrSet(bool* is_get,
bool* ok) {
Expect(Token::IDENTIFIER, ok);
if (!*ok) return Handle<String>();
- if (scanner().literal_length() == 3) {
- const char* token = scanner().literal_string();
- *is_get = strcmp(token, "get") == 0;
- *is_set = !*is_get && strcmp(token, "set") == 0;
+ if (scanner().is_literal_ascii() && scanner().literal_length() == 3) {
+ const char* token = scanner().literal_ascii_string().start();
+ *is_get = strncmp(token, "get", 3) == 0;
+ *is_set = !*is_get && strncmp(token, "set", 3) == 0;
}
return GetSymbol(ok);
}
@@ -3604,9 +3618,11 @@ Handle<String> JsonParser::GetString() {
if (literal_length == 0) {
return Factory::empty_string();
}
- const char* literal_string = scanner_.literal_string();
- Vector<const char> literal(literal_string, literal_length);
- return Factory::NewStringFromUtf8(literal);
+ if (scanner_.is_literal_ascii()) {
+ return Factory::NewStringFromAscii(scanner_.literal_ascii_string());
+ } else {
+ return Factory::NewStringFromTwoByte(scanner_.literal_uc16_string());
+ }
}
@@ -3618,7 +3634,8 @@ Handle<Object> JsonParser::ParseJsonValue() {
return GetString();
}
case Token::NUMBER: {
- double value = StringToDouble(scanner_.literal(),
+ ASSERT(scanner_.is_literal_ascii());
+ double value = StringToDouble(scanner_.literal_ascii_string(),
NO_FLAGS, // Hex, octal or trailing junk.
OS::nan_value());
return Factory::NewNumber(value);
@@ -3663,9 +3680,11 @@ Handle<Object> JsonParser::ParseJsonObject() {
if (value.is_null()) return Handle<Object>::null();
uint32_t index;
if (key->AsArrayIndex(&index)) {
- SetElement(json_object, index, value);
+ CALL_HEAP_FUNCTION_INLINE(
+ (*json_object)->SetElement(index, *value, true));
} else {
- SetProperty(json_object, key, value, NONE);
+ CALL_HEAP_FUNCTION_INLINE(
+ (*json_object)->SetPropertyPostInterceptor(*key, *value, NONE));
}
} while (scanner_.Next() == Token::COMMA);
if (scanner_.current_token() != Token::RBRACE) {
@@ -4597,10 +4616,9 @@ int ScriptDataImpl::ReadNumber(byte** source) {
// Create a Scanner for the preparser to use as input, and preparse the source.
static ScriptDataImpl* DoPreParse(UC16CharacterStream* source,
bool allow_lazy,
- ParserRecorder* recorder,
- int literal_flags) {
+ ParserRecorder* recorder) {
V8JavaScriptScanner scanner;
- scanner.Initialize(source, literal_flags);
+ scanner.Initialize(source);
intptr_t stack_limit = StackGuard::real_climit();
if (!preparser::PreParser::PreParseProgram(&scanner,
recorder,
@@ -4628,8 +4646,7 @@ ScriptDataImpl* ParserApi::PartialPreParse(UC16CharacterStream* source,
return NULL;
}
PartialParserRecorder recorder;
- return DoPreParse(source, allow_lazy, &recorder,
- JavaScriptScanner::kNoLiterals);
+ return DoPreParse(source, allow_lazy, &recorder);
}
@@ -4638,9 +4655,7 @@ ScriptDataImpl* ParserApi::PreParse(UC16CharacterStream* source,
Handle<Script> no_script;
bool allow_lazy = FLAG_lazy && (extension == NULL);
CompleteParserRecorder recorder;
- int kPreParseLiteralsFlags =
- JavaScriptScanner::kLiteralString | JavaScriptScanner::kLiteralIdentifier;
- return DoPreParse(source, allow_lazy, &recorder, kPreParseLiteralsFlags);
+ return DoPreParse(source, allow_lazy, &recorder);
}
diff --git a/src/parser.h b/src/parser.h
index 70d0e18f..8623f384 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -578,6 +578,26 @@ class Parser {
bool Check(Token::Value token);
void ExpectSemicolon(bool* ok);
+ Handle<String> LiteralString(PretenureFlag tenured) {
+ if (scanner().is_literal_ascii()) {
+ return Factory::NewStringFromAscii(scanner().literal_ascii_string(),
+ tenured);
+ } else {
+ return Factory::NewStringFromTwoByte(scanner().literal_uc16_string(),
+ tenured);
+ }
+ }
+
+ Handle<String> NextLiteralString(PretenureFlag tenured) {
+ if (scanner().is_next_literal_ascii()) {
+ return Factory::NewStringFromAscii(scanner().next_literal_ascii_string(),
+ tenured);
+ } else {
+ return Factory::NewStringFromTwoByte(scanner().next_literal_uc16_string(),
+ tenured);
+ }
+ }
+
Handle<String> GetSymbol(bool* ok);
// Get odd-ball literals.
@@ -612,11 +632,9 @@ class Parser {
Scope* NewScope(Scope* parent, Scope::Type type, bool inside_with);
- Handle<String> LookupSymbol(int symbol_id,
- Vector<const char> string);
+ Handle<String> LookupSymbol(int symbol_id);
- Handle<String> LookupCachedSymbol(int symbol_id,
- Vector<const char> string);
+ Handle<String> LookupCachedSymbol(int symbol_id);
Expression* NewCall(Expression* expression,
ZoneList<Expression*>* arguments,
diff --git a/src/platform-freebsd.cc b/src/platform-freebsd.cc
index b58d0662..ad1e499a 100644
--- a/src/platform-freebsd.cc
+++ b/src/platform-freebsd.cc
@@ -411,6 +411,12 @@ bool ThreadHandle::IsValid() const {
Thread::Thread() : ThreadHandle(ThreadHandle::INVALID) {
+ set_name("v8:<unknown>");
+}
+
+
+Thread::Thread(const char* name) : ThreadHandle(ThreadHandle::INVALID) {
+ set_names(name);
}
@@ -430,6 +436,12 @@ static void* ThreadEntry(void* arg) {
}
+void Thread::set_name(const char* name) {
+ strncpy(name_, name, sizeof(name_));
+ name_[sizeof(name_) - 1] = '\0';
+}
+
+
void Thread::Start() {
pthread_create(&thread_handle_data()->thread_, NULL, ThreadEntry, this);
ASSERT(IsValid());
diff --git a/src/platform-linux.cc b/src/platform-linux.cc
index 7efb25de..25a9ca0b 100644
--- a/src/platform-linux.cc
+++ b/src/platform-linux.cc
@@ -31,6 +31,7 @@
#include <pthread.h>
#include <semaphore.h>
#include <signal.h>
+#include <sys/prctl.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/syscall.h>
@@ -551,6 +552,12 @@ bool ThreadHandle::IsValid() const {
Thread::Thread() : ThreadHandle(ThreadHandle::INVALID) {
+ set_name("v8:<unknown>");
+}
+
+
+Thread::Thread(const char* name) : ThreadHandle(ThreadHandle::INVALID) {
+ set_name(name);
}
@@ -563,6 +570,9 @@ static void* ThreadEntry(void* arg) {
// This is also initialized by the first argument to pthread_create() but we
// don't know which thread will run first (the original thread or the new
// one) so we initialize it here too.
+ prctl(PR_SET_NAME,
+ reinterpret_cast<unsigned long>(thread->name()), // NOLINT
+ 0, 0, 0);
thread->thread_handle_data()->thread_ = pthread_self();
ASSERT(thread->IsValid());
thread->Run();
@@ -570,6 +580,12 @@ static void* ThreadEntry(void* arg) {
}
+void Thread::set_name(const char* name) {
+ strncpy(name_, name, sizeof(name_));
+ name_[sizeof(name_) - 1] = '\0';
+}
+
+
void Thread::Start() {
pthread_create(&thread_handle_data()->thread_, NULL, ThreadEntry, this);
ASSERT(IsValid());
diff --git a/src/platform-macos.cc b/src/platform-macos.cc
index 85c70882..ce533051 100644
--- a/src/platform-macos.cc
+++ b/src/platform-macos.cc
@@ -28,6 +28,7 @@
// Platform specific code for MacOS goes here. For the POSIX comaptible parts
// the implementation is in platform-posix.cc.
+#include <dlfcn.h>
#include <unistd.h>
#include <sys/mman.h>
#include <mach/mach_init.h>
@@ -49,7 +50,6 @@
#include <sys/types.h>
#include <stdarg.h>
#include <stdlib.h>
-
#include <errno.h>
#undef MAP_TYPE
@@ -411,6 +411,12 @@ bool ThreadHandle::IsValid() const {
Thread::Thread() : ThreadHandle(ThreadHandle::INVALID) {
+ set_name("v8:<unknown>");
+}
+
+
+Thread::Thread(const char* name) : ThreadHandle(ThreadHandle::INVALID) {
+ set_name(name);
}
@@ -418,18 +424,43 @@ Thread::~Thread() {
}
+
+static void SetThreadName(const char* name) {
+ // pthread_setname_np is only available in 10.6 or later, so test
+ // for it at runtime.
+ int (*dynamic_pthread_setname_np)(const char*);
+ *reinterpret_cast<void**>(&dynamic_pthread_setname_np) =
+ dlsym(RTLD_DEFAULT, "pthread_setname_np");
+ if (!dynamic_pthread_setname_np)
+ return;
+
+ // Mac OS X does not expose the length limit of the name, so hardcode it.
+ static const int kMaxNameLength = 63;
+ USE(kMaxNameLength);
+ ASSERT(Thread::kMaxThreadNameLength <= kMaxNameLength);
+ dynamic_pthread_setname_np(name);
+}
+
+
static void* ThreadEntry(void* arg) {
Thread* thread = reinterpret_cast<Thread*>(arg);
// This is also initialized by the first argument to pthread_create() but we
// don't know which thread will run first (the original thread or the new
// one) so we initialize it here too.
thread->thread_handle_data()->thread_ = pthread_self();
+ SetThreadName(thread->name());
ASSERT(thread->IsValid());
thread->Run();
return NULL;
}
+void Thread::set_name(const char* name) {
+ strncpy(name_, name, sizeof(name_));
+ name_[sizeof(name_) - 1] = '\0';
+}
+
+
void Thread::Start() {
pthread_create(&thread_handle_data()->thread_, NULL, ThreadEntry, this);
}
diff --git a/src/platform-nullos.cc b/src/platform-nullos.cc
index 72ea0e57..f1b76959 100644
--- a/src/platform-nullos.cc
+++ b/src/platform-nullos.cc
@@ -335,6 +335,13 @@ bool ThreadHandle::IsValid() const {
Thread::Thread() : ThreadHandle(ThreadHandle::INVALID) {
+ set_name("v8:<unknown>");
+ UNIMPLEMENTED();
+}
+
+
+Thread::Thread(const char* name) : ThreadHandle(ThreadHandle::INVALID) {
+ set_name(name);
UNIMPLEMENTED();
}
@@ -344,6 +351,12 @@ Thread::~Thread() {
}
+void Thread::set_name(const char* name) {
+ strncpy(name_, name, sizeof(name_));
+ name_[sizeof(name_) - 1] = '\0';
+}
+
+
void Thread::Start() {
UNIMPLEMENTED();
}
diff --git a/src/platform-openbsd.cc b/src/platform-openbsd.cc
index b698d16b..5de60819 100644
--- a/src/platform-openbsd.cc
+++ b/src/platform-openbsd.cc
@@ -387,6 +387,12 @@ bool ThreadHandle::IsValid() const {
Thread::Thread() : ThreadHandle(ThreadHandle::INVALID) {
+ set_name("v8:<unknown>");
+}
+
+
+Thread::Thread(const char* name) : ThreadHandle(ThreadHandle::INVALID) {
+ set_name(name);
}
@@ -406,6 +412,12 @@ static void* ThreadEntry(void* arg) {
}
+void Thread::set_name(const char* name) {
+ strncpy(name_, name, sizeof(name_));
+ name_[sizeof(name_) - 1] = '\0';
+}
+
+
void Thread::Start() {
pthread_create(&thread_handle_data()->thread_, NULL, ThreadEntry, this);
ASSERT(IsValid());
diff --git a/src/platform-solaris.cc b/src/platform-solaris.cc
index f84e80d1..04c25a90 100644
--- a/src/platform-solaris.cc
+++ b/src/platform-solaris.cc
@@ -401,6 +401,12 @@ bool ThreadHandle::IsValid() const {
Thread::Thread() : ThreadHandle(ThreadHandle::INVALID) {
+ set_name("v8:<unknown>");
+}
+
+
+Thread::Thread(const char* name) : ThreadHandle(ThreadHandle::INVALID) {
+ set_name(name);
}
@@ -420,6 +426,12 @@ static void* ThreadEntry(void* arg) {
}
+void Thread::set_name(const char* name) {
+ strncpy(name_, name, sizeof(name_));
+ name_[sizeof(name_) - 1] = '\0';
+}
+
+
void Thread::Start() {
pthread_create(&thread_handle_data()->thread_, NULL, ThreadEntry, this);
ASSERT(IsValid());
diff --git a/src/platform-win32.cc b/src/platform-win32.cc
index 4438045e..81216e19 100644
--- a/src/platform-win32.cc
+++ b/src/platform-win32.cc
@@ -1463,6 +1463,19 @@ class Thread::PlatformData : public Malloced {
Thread::Thread() : ThreadHandle(ThreadHandle::INVALID) {
data_ = new PlatformData(kNoThread);
+ set_name("v8:<unknown>");
+}
+
+
+Thread::Thread(const char* name) : ThreadHandle(ThreadHandle::INVALID) {
+ data_ = new PlatformData(kNoThread);
+ set_name(name);
+}
+
+
+void Thread::set_name(const char* name) {
+ strncpy_s(name_, name, sizeof(name_));
+ name_[sizeof(name_) - 1] = '\0';
}
diff --git a/src/platform.h b/src/platform.h
index 5a3e4a3f..7b170674 100644
--- a/src/platform.h
+++ b/src/platform.h
@@ -387,6 +387,7 @@ class Thread: public ThreadHandle {
// Create new thread.
Thread();
+ explicit Thread(const char* name);
virtual ~Thread();
// Start new thread by calling the Run() method in the new thread.
@@ -395,6 +396,10 @@ class Thread: public ThreadHandle {
// Wait until thread terminates.
void Join();
+ inline const char* name() const {
+ return name_;
+ }
+
// Abstract method for run handler.
virtual void Run() = 0;
@@ -416,9 +421,17 @@ class Thread: public ThreadHandle {
// A hint to the scheduler to let another thread run.
static void YieldCPU();
+ // The thread name length is limited to 16 based on Linux's implementation of
+ // prctl().
+ static const int kMaxThreadNameLength = 16;
private:
+ void set_name(const char *name);
+
class PlatformData;
PlatformData* data_;
+
+ char name_[kMaxThreadNameLength];
+
DISALLOW_COPY_AND_ASSIGN(Thread);
};
diff --git a/src/preparse-data.cc b/src/preparse-data.cc
index 9a367718..7c9d8a61 100644
--- a/src/preparse-data.cc
+++ b/src/preparse-data.cc
@@ -110,26 +110,29 @@ Vector<unsigned> PartialParserRecorder::ExtractData() {
CompleteParserRecorder::CompleteParserRecorder()
: FunctionLoggingParserRecorder(),
+ literal_chars_(0),
symbol_store_(0),
- symbol_entries_(0),
+ symbol_keys_(0),
symbol_table_(vector_compare),
symbol_id_(0) {
}
-void CompleteParserRecorder::LogSymbol(
- int start, const char* literal_chars, int length) {
- if (!is_recording_) return;
-
- Vector<const char> literal(literal_chars, length);
- int hash = vector_hash(literal);
- HashMap::Entry* entry = symbol_table_.Lookup(&literal, hash, true);
+void CompleteParserRecorder::LogSymbol(int start,
+ int hash,
+ bool is_ascii,
+ Vector<const byte> literal_bytes) {
+ Key key = { is_ascii, literal_bytes };
+ HashMap::Entry* entry = symbol_table_.Lookup(&key, hash, true);
int id = static_cast<int>(reinterpret_cast<intptr_t>(entry->value));
if (id == 0) {
+ // Copy literal contents for later comparison.
+ key.literal_bytes =
+ Vector<const byte>::cast(literal_chars_.AddBlock(literal_bytes));
// 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);
+ Vector<Key> symbol = symbol_keys_.AddBlock(1, key);
entry->key = &symbol[0];
}
WriteNumber(id - 1);
diff --git a/src/preparse-data.h b/src/preparse-data.h
index a96e50fa..cc82bcc6 100644
--- a/src/preparse-data.h
+++ b/src/preparse-data.h
@@ -75,7 +75,8 @@ class ParserRecorder {
int properties) = 0;
// Logs a symbol creation of a literal or identifier.
- virtual void LogSymbol(int start, const char* symbol, int length) = 0;
+ virtual void LogAsciiSymbol(int start, Vector<const char> literal) { }
+ virtual void LogUC16Symbol(int start, Vector<const uc16> literal) { }
// Logs an error message and marks the log as containing an error.
// Further logging will be ignored, and ExtractData will return a vector
@@ -165,7 +166,8 @@ class FunctionLoggingParserRecorder : public ParserRecorder {
class PartialParserRecorder : public FunctionLoggingParserRecorder {
public:
PartialParserRecorder() : FunctionLoggingParserRecorder() { }
- virtual void LogSymbol(int start, const char* symbol, int length) { }
+ virtual void LogAsciiSymbol(int start, Vector<const char> literal) { }
+ virtual void LogUC16Symbol(int start, Vector<const uc16> literal) { }
virtual ~PartialParserRecorder() { }
virtual Vector<unsigned> ExtractData();
virtual int symbol_position() { return 0; }
@@ -181,7 +183,17 @@ class CompleteParserRecorder: public FunctionLoggingParserRecorder {
CompleteParserRecorder();
virtual ~CompleteParserRecorder() { }
- virtual void LogSymbol(int start, const char* symbol, int length);
+ virtual void LogAsciiSymbol(int start, Vector<const char> literal) {
+ if (!is_recording_) return;
+ int hash = vector_hash(literal);
+ LogSymbol(start, hash, true, Vector<const byte>::cast(literal));
+ }
+
+ virtual void LogUC16Symbol(int start, Vector<const uc16> literal) {
+ if (!is_recording_) return;
+ int hash = vector_hash(literal);
+ LogSymbol(start, hash, false, Vector<const byte>::cast(literal));
+ }
virtual Vector<unsigned> ExtractData();
@@ -189,10 +201,21 @@ class CompleteParserRecorder: public FunctionLoggingParserRecorder {
virtual int symbol_ids() { return symbol_id_; }
private:
- static int vector_hash(Vector<const char> string) {
+ struct Key {
+ bool is_ascii;
+ Vector<const byte> literal_bytes;
+ };
+
+ virtual void LogSymbol(int start,
+ int hash,
+ bool is_ascii,
+ Vector<const byte> literal);
+
+ template <typename Char>
+ static int vector_hash(Vector<const Char> string) {
int hash = 0;
for (int i = 0; i < string.length(); i++) {
- int c = string[i];
+ int c = static_cast<int>(string[i]);
hash += c;
hash += (hash << 10);
hash ^= (hash >> 6);
@@ -201,18 +224,21 @@ class CompleteParserRecorder: public FunctionLoggingParserRecorder {
}
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;
+ Key* string1 = reinterpret_cast<Key*>(a);
+ Key* string2 = reinterpret_cast<Key*>(b);
+ if (string1->is_ascii != string2->is_ascii) return false;
+ int length = string1->literal_bytes.length();
+ if (string2->literal_bytes.length() != length) return false;
+ return memcmp(string1->literal_bytes.start(),
+ string2->literal_bytes.start(), length) == 0;
}
// Write a non-negative number to the symbol store.
void WriteNumber(int number);
+ Collector<byte> literal_chars_;
Collector<byte> symbol_store_;
- Collector<Vector<const char> > symbol_entries_;
+ Collector<Key> symbol_keys_;
HashMap symbol_table_;
int symbol_id_;
};
diff --git a/src/preparser-api.cc b/src/preparser-api.cc
index cbec9b70..dba30265 100644
--- a/src/preparser-api.cc
+++ b/src/preparser-api.cc
@@ -155,7 +155,6 @@ class StandAloneJavaScriptScanner : public JavaScriptScanner {
public:
void Initialize(UC16CharacterStream* source) {
source_ = source;
- literal_flags_ = kLiteralString | kLiteralIdentifier;
Init();
// Skip initial whitespace allowing HTML comment ends just like
// after a newline and scan first token.
diff --git a/src/preparser.cc b/src/preparser.cc
index 7cce685e..e05f9037 100644
--- a/src/preparser.cc
+++ b/src/preparser.cc
@@ -950,13 +950,17 @@ PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) {
ParseIdentifierOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
if ((is_getter || is_setter) && peek() != i::Token::COLON) {
i::Token::Value name = Next();
+ bool is_keyword = i::Token::IsKeyword(name);
if (name != i::Token::IDENTIFIER &&
name != i::Token::NUMBER &&
name != i::Token::STRING &&
- !i::Token::IsKeyword(name)) {
+ !is_keyword) {
*ok = false;
return kUnknownExpression;
}
+ if (!is_keyword) {
+ LogSymbol();
+ }
ParseFunctionLiteral(CHECK_OK);
if (peek() != i::Token::RBRACE) {
Expect(i::Token::COMMA, CHECK_OK);
@@ -1120,24 +1124,24 @@ void PreParser::ExpectSemicolon(bool* ok) {
}
-PreParser::Identifier PreParser::GetIdentifierSymbol() {
- const char* literal_chars = scanner_->literal_string();
- int literal_length = scanner_->literal_length();
+void PreParser::LogSymbol() {
int identifier_pos = scanner_->location().beg_pos;
+ if (scanner_->is_literal_ascii()) {
+ log_->LogAsciiSymbol(identifier_pos, scanner_->literal_ascii_string());
+ } else {
+ log_->LogUC16Symbol(identifier_pos, scanner_->literal_uc16_string());
+ }
+}
- log_->LogSymbol(identifier_pos, literal_chars, literal_length);
- return kUnknownExpression;
+PreParser::Identifier PreParser::GetIdentifierSymbol() {
+ LogSymbol();
+ return kUnknownIdentifier;
}
PreParser::Expression PreParser::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);
-
+ LogSymbol();
return kUnknownExpression;
}
@@ -1154,7 +1158,8 @@ PreParser::Identifier PreParser::ParseIdentifierName(bool* ok) {
if (i::Token::IsKeyword(next)) {
int pos = scanner_->location().beg_pos;
const char* keyword = i::Token::String(next);
- log_->LogSymbol(pos, keyword, i::StrLength(keyword));
+ log_->LogAsciiSymbol(pos, i::Vector<const char>(keyword,
+ i::StrLength(keyword)));
return kUnknownExpression;
}
if (next == i::Token::IDENTIFIER) {
@@ -1173,8 +1178,8 @@ PreParser::Identifier PreParser::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();
+ if (scanner_->is_literal_ascii() && scanner_->literal_length() == 3) {
+ const char* token = scanner_->literal_ascii_string().start();
*is_get = strncmp(token, "get", 3) == 0;
*is_set = !*is_get && strncmp(token, "set", 3) == 0;
}
diff --git a/src/preparser.h b/src/preparser.h
index 893b5751..536e6d4f 100644
--- a/src/preparser.h
+++ b/src/preparser.h
@@ -216,8 +216,11 @@ class PreParser {
Identifier ParseIdentifierName(bool* ok);
Identifier ParseIdentifierOrGetOrSet(bool* is_get, bool* is_set, bool* ok);
+ // Logs the currently parsed literal as a symbol in the preparser data.
+ void LogSymbol();
+ // Log the currently parsed identifier.
Identifier GetIdentifierSymbol();
- unsigned int HexDigitValue(char digit);
+ // Log the currently parsed string literal.
Expression GetStringSymbol();
i::Token::Value peek() {
diff --git a/src/scanner-base.cc b/src/scanner-base.cc
index b26fee01..1babaebb 100644
--- a/src/scanner-base.cc
+++ b/src/scanner-base.cc
@@ -35,28 +35,6 @@ namespace v8 {
namespace internal {
// ----------------------------------------------------------------------------
-// LiteralCollector
-
-LiteralCollector::LiteralCollector()
- : buffer_(kInitialCapacity), recording_(false) { }
-
-
-LiteralCollector::~LiteralCollector() {}
-
-
-void LiteralCollector::AddCharSlow(uc32 c) {
- ASSERT(static_cast<unsigned>(c) > unibrow::Utf8::kMaxOneByteChar);
- int length = unibrow::Utf8::Length(c);
- Vector<char> block = buffer_.AddBlock(length, '\0');
-#ifdef DEBUG
- int written_length = unibrow::Utf8::Encode(block.start(), c);
- CHECK_EQ(length, written_length);
-#else
- unibrow::Utf8::Encode(block.start(), c);
-#endif
-}
-
-// ----------------------------------------------------------------------------
// Character predicates
unibrow::Predicate<IdentifierStart, 128> ScannerConstants::kIsIdentifierStart;
@@ -256,7 +234,7 @@ Token::Value JavaScriptScanner::ScanHtmlComment() {
void JavaScriptScanner::Scan() {
- next_.literal_chars = Vector<const char>();
+ next_.literal_chars = NULL;
Token::Value token;
do {
// Remember the position of the next token
@@ -561,7 +539,7 @@ Token::Value JavaScriptScanner::ScanString() {
uc32 quote = c0_;
Advance(); // consume quote
- LiteralScope literal(this, kLiteralString);
+ LiteralScope literal(this);
while (c0_ != quote && c0_ >= 0
&& !ScannerConstants::kIsLineTerminator.get(c0_)) {
uc32 c = c0_;
@@ -592,7 +570,7 @@ Token::Value JavaScriptScanner::ScanNumber(bool seen_period) {
enum { DECIMAL, HEX, OCTAL } kind = DECIMAL;
- LiteralScope literal(this, kLiteralNumber);
+ LiteralScope literal(this);
if (seen_period) {
// we have already seen a decimal point of the float
AddLiteralChar('.');
@@ -681,7 +659,7 @@ uc32 JavaScriptScanner::ScanIdentifierUnicodeEscape() {
Token::Value JavaScriptScanner::ScanIdentifierOrKeyword() {
ASSERT(ScannerConstants::kIsIdentifierStart.get(c0_));
- LiteralScope literal(this, kLiteralIdentifier);
+ LiteralScope literal(this);
KeywordMatcher keyword_match;
// Scan identifier start character.
if (c0_ == '\\') {
@@ -747,7 +725,7 @@ bool JavaScriptScanner::ScanRegExpPattern(bool seen_equal) {
// Scan regular expression body: According to ECMA-262, 3rd, 7.8.5,
// the scanner should pass uninterpreted bodies to the RegExp
// constructor.
- LiteralScope literal(this, kLiteralRegExp);
+ LiteralScope literal(this);
if (seen_equal)
AddLiteralChar('=');
@@ -773,7 +751,7 @@ bool JavaScriptScanner::ScanRegExpPattern(bool seen_equal) {
bool JavaScriptScanner::ScanRegExpFlags() {
// Scan regular expression flags.
- LiteralScope literal(this, kLiteralRegExpFlags);
+ LiteralScope literal(this);
while (ScannerConstants::kIsIdentifierPart.get(c0_)) {
if (c0_ == '\\') {
uc32 c = ScanIdentifierUnicodeEscape();
diff --git a/src/scanner-base.h b/src/scanner-base.h
index c50b8f3e..b668df50 100644
--- a/src/scanner-base.h
+++ b/src/scanner-base.h
@@ -141,61 +141,105 @@ class ScannerConstants : AllStatic {
};
// ----------------------------------------------------------------------------
-// LiteralCollector - Collector of chars of literals.
+// LiteralBuffer - Collector of chars of literals.
-class LiteralCollector {
+class LiteralBuffer {
public:
- LiteralCollector();
- ~LiteralCollector();
-
- inline void AddChar(uc32 c) {
- if (recording_) {
- if (static_cast<unsigned>(c) <= unibrow::Utf8::kMaxOneByteChar) {
- buffer_.Add(static_cast<char>(c));
- } else {
- AddCharSlow(c);
+ LiteralBuffer() : is_ascii_(true), position_(0), backing_store_() { }
+
+ ~LiteralBuffer() {
+ if (backing_store_.length() > 0) {
+ backing_store_.Dispose();
+ }
+ }
+
+ inline void AddChar(uc16 character) {
+ if (position_ >= backing_store_.length()) ExpandBuffer();
+ if (is_ascii_) {
+ if (character < kMaxAsciiCharCodeU) {
+ backing_store_[position_] = static_cast<byte>(character);
+ position_ += kASCIISize;
+ return;
}
+ ConvertToUC16();
}
+ *reinterpret_cast<uc16*>(&backing_store_[position_]) = character;
+ position_ += kUC16Size;
}
- void StartLiteral() {
- buffer_.StartSequence();
- recording_ = true;
+ bool is_ascii() { return is_ascii_; }
+
+ Vector<const uc16> uc16_literal() {
+ ASSERT(!is_ascii_);
+ ASSERT((position_ & 0x1) == 0);
+ return Vector<const uc16>(
+ reinterpret_cast<const uc16*>(backing_store_.start()),
+ position_ >> 1);
}
- Vector<const char> EndLiteral() {
- if (recording_) {
- recording_ = false;
- buffer_.Add(kEndMarker);
- Vector<char> sequence = buffer_.EndSequence();
- return Vector<const char>(sequence.start(), sequence.length());
- }
- return Vector<const char>();
+ Vector<const char> ascii_literal() {
+ ASSERT(is_ascii_);
+ return Vector<const char>(
+ reinterpret_cast<const char*>(backing_store_.start()),
+ position_);
}
- void DropLiteral() {
- if (recording_) {
- recording_ = false;
- buffer_.DropSequence();
- }
+ int length() {
+ return is_ascii_ ? position_ : (position_ >> 1);
}
void Reset() {
- buffer_.Reset();
+ position_ = 0;
+ is_ascii_ = true;
}
-
- // The end marker added after a parsed literal.
- // Using zero allows the usage of strlen and similar functions on
- // identifiers and numbers (but not strings, since they may contain zero
- // bytes).
- static const char kEndMarker = '\x00';
private:
- static const int kInitialCapacity = 256;
- SequenceCollector<char, 4> buffer_;
- bool recording_;
- void AddCharSlow(uc32 c);
+ static const int kInitialCapacity = 16;
+ static const int kGrowthFactory = 4;
+ static const int kMinConversionSlack = 256;
+ static const int kMaxGrowth = 1 * MB;
+ inline int NewCapacity(int min_capacity) {
+ int capacity = Max(min_capacity, backing_store_.length());
+ int new_capacity = Min(capacity * kGrowthFactory, capacity + kMaxGrowth);
+ return new_capacity;
+ }
+
+ void ExpandBuffer() {
+ Vector<byte> new_store = Vector<byte>::New(NewCapacity(kInitialCapacity));
+ memcpy(new_store.start(), backing_store_.start(), position_);
+ backing_store_.Dispose();
+ backing_store_ = new_store;
+ }
+
+ void ConvertToUC16() {
+ ASSERT(is_ascii_);
+ Vector<byte> new_store;
+ int new_content_size = position_ * kUC16Size;
+ if (new_content_size >= backing_store_.length()) {
+ // Ensure room for all currently read characters as UC16 as well
+ // as the character about to be stored.
+ new_store = Vector<byte>::New(NewCapacity(new_content_size));
+ } else {
+ new_store = backing_store_;
+ }
+ char* src = reinterpret_cast<char*>(backing_store_.start());
+ uc16* dst = reinterpret_cast<uc16*>(new_store.start());
+ for (int i = position_ - 1; i >= 0; i--) {
+ dst[i] = src[i];
+ }
+ if (new_store.start() != backing_store_.start()) {
+ backing_store_.Dispose();
+ backing_store_ = new_store;
+ }
+ position_ = new_content_size;
+ is_ascii_ = false;
+ }
+
+ bool is_ascii_;
+ int position_;
+ Vector<byte> backing_store_;
};
+
// ----------------------------------------------------------------------------
// Scanner base-class.
@@ -241,35 +285,40 @@ class Scanner {
// collected for identifiers, strings, and numbers.
// These functions only give the correct result if the literal
// was scanned between calls to StartLiteral() and TerminateLiteral().
- const char* literal_string() const {
- return current_.literal_chars.start();
+ bool is_literal_ascii() {
+ ASSERT_NOT_NULL(current_.literal_chars);
+ return current_.literal_chars->is_ascii();
}
-
- int literal_length() const {
- // Excluding terminal '\x00' added by TerminateLiteral().
- return current_.literal_chars.length() - 1;
+ Vector<const char> literal_ascii_string() {
+ ASSERT_NOT_NULL(current_.literal_chars);
+ return current_.literal_chars->ascii_literal();
}
-
- Vector<const char> literal() const {
- return Vector<const char>(literal_string(), literal_length());
+ Vector<const uc16> literal_uc16_string() {
+ ASSERT_NOT_NULL(current_.literal_chars);
+ return current_.literal_chars->uc16_literal();
+ }
+ int literal_length() const {
+ ASSERT_NOT_NULL(current_.literal_chars);
+ return current_.literal_chars->length();
}
// Returns the literal string for the next token (the token that
// would be returned if Next() were called).
- const char* next_literal_string() const {
- return next_.literal_chars.start();
+ bool is_next_literal_ascii() {
+ ASSERT_NOT_NULL(next_.literal_chars);
+ return next_.literal_chars->is_ascii();
}
-
-
- // Returns the length of the next token (that would be returned if
- // Next() were called).
- int next_literal_length() const {
- // Excluding terminal '\x00' added by TerminateLiteral().
- return next_.literal_chars.length() - 1;
+ Vector<const char> next_literal_ascii_string() {
+ ASSERT_NOT_NULL(next_.literal_chars);
+ return next_.literal_chars->ascii_literal();
}
-
- Vector<const char> next_literal() const {
- return Vector<const char>(next_literal_string(), next_literal_length());
+ Vector<const uc16> next_literal_uc16_string() {
+ ASSERT_NOT_NULL(next_.literal_chars);
+ return next_.literal_chars->uc16_literal();
+ }
+ int next_literal_length() const {
+ ASSERT_NOT_NULL(next_.literal_chars);
+ return next_.literal_chars->length();
}
static const int kCharacterLookaheadBufferSize = 1;
@@ -279,7 +328,7 @@ class Scanner {
struct TokenDesc {
Token::Value token;
Location location;
- Vector<const char> literal_chars;
+ LiteralBuffer* literal_chars;
};
// Call this after setting source_ to the input.
@@ -288,29 +337,31 @@ class Scanner {
ASSERT(kCharacterLookaheadBufferSize == 1);
Advance();
// Initialize current_ to not refer to a literal.
- current_.literal_chars = Vector<const char>();
- // Reset literal buffer.
- literal_buffer_.Reset();
+ current_.literal_chars = NULL;
}
// Literal buffer support
inline void StartLiteral() {
- literal_buffer_.StartLiteral();
+ LiteralBuffer* free_buffer = (current_.literal_chars == &literal_buffer1_) ?
+ &literal_buffer2_ : &literal_buffer1_;
+ free_buffer->Reset();
+ next_.literal_chars = free_buffer;
}
inline void AddLiteralChar(uc32 c) {
- literal_buffer_.AddChar(c);
+ ASSERT_NOT_NULL(next_.literal_chars);
+ next_.literal_chars->AddChar(c);
}
// Complete scanning of a literal.
inline void TerminateLiteral() {
- next_.literal_chars = literal_buffer_.EndLiteral();
+ // Does nothing in the current implementation.
}
// Stops scanning of a literal and drop the collected characters,
// e.g., due to an encountered error.
inline void DropLiteral() {
- literal_buffer_.DropLiteral();
+ next_.literal_chars = NULL;
}
inline void AddLiteralCharAdvance() {
@@ -348,15 +399,16 @@ class Scanner {
return source_->pos() - kCharacterLookaheadBufferSize;
}
+ // Buffers collecting literal strings, numbers, etc.
+ LiteralBuffer literal_buffer1_;
+ LiteralBuffer literal_buffer2_;
+
TokenDesc current_; // desc for current token (as returned by Next())
TokenDesc next_; // desc for next token (one token look-ahead)
// Input stream. Must be initialized to an UC16CharacterStream.
UC16CharacterStream* source_;
- // Buffer to hold literal values (identifiers, strings, numbers)
- // using '\x00'-terminated UTF-8 encoding. Handles allocation internally.
- LiteralCollector literal_buffer_;
// One Unicode character look-ahead; c0_ < 0 at the end of the input.
uc32 c0_;
@@ -367,28 +419,14 @@ class Scanner {
class JavaScriptScanner : public Scanner {
public:
-
- // Bit vector representing set of types of literals.
- enum LiteralType {
- kNoLiterals = 0,
- kLiteralNumber = 1,
- kLiteralIdentifier = 2,
- kLiteralString = 4,
- kLiteralRegExp = 8,
- kLiteralRegExpFlags = 16,
- kAllLiterals = 31
- };
-
// A LiteralScope that disables recording of some types of JavaScript
// literals. If the scanner is configured to not record the specific
// type of literal, the scope will not call StartLiteral.
class LiteralScope {
public:
- LiteralScope(JavaScriptScanner* self, LiteralType type)
+ explicit LiteralScope(JavaScriptScanner* self)
: scanner_(self), complete_(false) {
- if (scanner_->RecordsLiteral(type)) {
- scanner_->StartLiteral();
- }
+ scanner_->StartLiteral();
}
~LiteralScope() {
if (!complete_) scanner_->DropLiteral();
@@ -430,11 +468,6 @@ class JavaScriptScanner : public Scanner {
// tokens, which is what it is used for.
void SeekForward(int pos);
- // Whether this scanner records the given literal type or not.
- bool RecordsLiteral(LiteralType type) {
- return (literal_flags_ & type) != 0;
- }
-
protected:
bool SkipWhiteSpace();
Token::Value SkipSingleLineComment();
@@ -458,7 +491,6 @@ class JavaScriptScanner : public Scanner {
// If the escape sequence cannot be decoded the result is kBadChar.
uc32 ScanIdentifierUnicodeEscape();
- int literal_flags_;
bool has_line_terminator_before_next_;
};
diff --git a/src/scanner.cc b/src/scanner.cc
index 47e9895c..7fd6ef22 100755
--- a/src/scanner.cc
+++ b/src/scanner.cc
@@ -324,10 +324,8 @@ void Scanner::LiteralScope::Complete() {
V8JavaScriptScanner::V8JavaScriptScanner() : JavaScriptScanner() { }
-void V8JavaScriptScanner::Initialize(UC16CharacterStream* source,
- int literal_flags) {
+void V8JavaScriptScanner::Initialize(UC16CharacterStream* source) {
source_ = source;
- literal_flags_ = literal_flags | kLiteralIdentifier;
// Need to capture identifiers in order to recognize "get" and "set"
// in object literals.
Init();
@@ -377,7 +375,7 @@ bool JsonScanner::SkipJsonWhiteSpace() {
void JsonScanner::ScanJson() {
- next_.literal_chars = Vector<const char>();
+ next_.literal_chars = NULL;
Token::Value token;
do {
// Remember the position of the next token
@@ -459,7 +457,7 @@ Token::Value JsonScanner::ScanJsonString() {
ASSERT_EQ('"', c0_);
Advance();
LiteralScope literal(this);
- while (c0_ != '"' && c0_ > 0) {
+ while (c0_ != '"') {
// Check for control character (0x00-0x1f) or unterminated string (<0).
if (c0_ < 0x20) return Token::ILLEGAL;
if (c0_ != '\\') {
@@ -506,9 +504,6 @@ Token::Value JsonScanner::ScanJsonString() {
Advance();
}
}
- if (c0_ != '"') {
- return Token::ILLEGAL;
- }
literal.Complete();
Advance();
return Token::STRING;
diff --git a/src/scanner.h b/src/scanner.h
index 572778f8..bdf899b5 100644
--- a/src/scanner.h
+++ b/src/scanner.h
@@ -134,8 +134,7 @@ class ExternalTwoByteStringUC16CharacterStream: public UC16CharacterStream {
class V8JavaScriptScanner : public JavaScriptScanner {
public:
V8JavaScriptScanner();
- void Initialize(UC16CharacterStream* source,
- int literal_flags = kAllLiterals);
+ void Initialize(UC16CharacterStream* source);
};
diff --git a/src/string-search.h b/src/string-search.h
index eac84757..5de3c095 100644
--- a/src/string-search.h
+++ b/src/string-search.h
@@ -66,12 +66,7 @@ class StringSearchBase {
}
static inline bool IsAsciiString(Vector<const uc16> string) {
- for (int i = 0, n = string.length(); i < n; i++) {
- if (static_cast<unsigned>(string[i]) > String::kMaxAsciiCharCodeU) {
- return false;
- }
- }
- return true;
+ return String::IsAscii(string.start(), string.length());
}
// The following tables are shared by all searches.
diff --git a/src/string.js b/src/string.js
index 95275995..ab0ab54f 100644
--- a/src/string.js
+++ b/src/string.js
@@ -127,7 +127,7 @@ function StringLastIndexOf(pat /* position */) { // length == 1
var index = subLength - patLength;
if (%_ArgumentsLength() > 1) {
var position = ToNumber(%_Arguments(1));
- if (!$isNaN(position)) {
+ if (!NUMBER_IS_NAN(position)) {
position = TO_INTEGER(position);
if (position < 0) {
position = 0;
diff --git a/src/top.cc b/src/top.cc
index 3d86d11b..98c673c1 100644
--- a/src/top.cc
+++ b/src/top.cc
@@ -170,7 +170,9 @@ void Top::InitializeThreadLocal() {
// into for use by a stacks only core dump (aka minidump).
class PreallocatedMemoryThread: public Thread {
public:
- PreallocatedMemoryThread() : keep_running_(true) {
+ PreallocatedMemoryThread()
+ : Thread("v8:PreallocMem"),
+ keep_running_(true) {
wait_for_ever_semaphore_ = OS::CreateSemaphore(0);
data_ready_semaphore_ = OS::CreateSemaphore(0);
}
diff --git a/src/unicode.cc b/src/unicode.cc
index 35a66c69..346f673f 100644
--- a/src/unicode.cc
+++ b/src/unicode.cc
@@ -25,7 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
-// This file was generated at 2010-07-30 14:07:24.988557
+// This file was generated at 2011-01-03 10:57:02.088925
#include "unicode-inl.h"
#include <stdlib.h>
@@ -35,6 +35,7 @@ namespace unibrow {
static const int kStartBit = (1 << 30);
static const int kChunkBits = (1 << 13);
+static const uchar kSentinel = static_cast<uchar>(-1);
/**
* \file
@@ -96,12 +97,12 @@ static bool LookupPredicate(const int32_t* table, uint16_t size, uchar chr) {
int32_t field = TableGet<kEntryDist>(table, low);
uchar entry = GetEntry(field);
bool is_start = IsStart(field);
- return (entry == value) ||
- (entry < value && is_start);
+ return (entry == value) || (entry < value && is_start);
}
template <int kW>
struct MultiCharacterSpecialCase {
+ static const uchar kEndOfEncoding = kSentinel;
uchar chars[kW];
};
@@ -172,7 +173,7 @@ static int LookupMapping(const int32_t* table,
int length = 0;
for (length = 0; length < kW; length++) {
uchar mapped = mapping.chars[length];
- if (mapped == static_cast<uchar>(-1)) break;
+ if (mapped == MultiCharacterSpecialCase<kW>::kEndOfEncoding) break;
if (ranges_are_linear) {
result[length] = mapped + (key - entry);
} else {
@@ -225,13 +226,13 @@ uchar Utf8::CalculateValue(const byte* str,
*cursor += 1;
return kBadChar;
}
- uchar l = ((first << 6) | second) & kMaxTwoByteChar;
- if (l <= kMaxOneByteChar) {
+ uchar code_point = ((first << 6) | second) & kMaxTwoByteChar;
+ if (code_point <= kMaxOneByteChar) {
*cursor += 1;
return kBadChar;
}
*cursor += 2;
- return l;
+ return code_point;
}
if (length == 2) {
*cursor += 1;
@@ -243,13 +244,14 @@ uchar Utf8::CalculateValue(const byte* str,
return kBadChar;
}
if (first < 0xF0) {
- uchar l = ((((first << 6) | second) << 6) | third) & kMaxThreeByteChar;
- if (l <= kMaxTwoByteChar) {
+ uchar code_point = ((((first << 6) | second) << 6) | third)
+ & kMaxThreeByteChar;
+ if (code_point <= kMaxTwoByteChar) {
*cursor += 1;
return kBadChar;
}
*cursor += 3;
- return l;
+ return code_point;
}
if (length == 3) {
*cursor += 1;
@@ -261,14 +263,14 @@ uchar Utf8::CalculateValue(const byte* str,
return kBadChar;
}
if (first < 0xF8) {
- uchar l = (((((first << 6 | second) << 6) | third) << 6) | fourth) &
- kMaxFourByteChar;
- if (l <= kMaxThreeByteChar) {
+ uchar code_point = (((((first << 6 | second) << 6) | third) << 6) | fourth)
+ & kMaxFourByteChar;
+ if (code_point <= kMaxThreeByteChar) {
*cursor += 1;
return kBadChar;
}
*cursor += 4;
- return l;
+ return code_point;
}
*cursor += 1;
return kBadChar;
@@ -823,7 +825,7 @@ bool ConnectorPunctuation::Is(uchar c) {
}
static const MultiCharacterSpecialCase<2> kToLowercaseMultiStrings0[2] = { // NOLINT
- {{105, 775}}, {{-1}} }; // NOLINT
+ {{105, 775}}, {{kSentinel}} }; // NOLINT
static const uint16_t kToLowercaseTable0Size = 463; // NOLINT
static const int32_t kToLowercaseTable0[926] = {
1073741889, 128, 90, 128, 1073742016, 128, 214, 128, 1073742040, 128, 222, 128, 256, 4, 258, 4, // NOLINT
@@ -886,7 +888,7 @@ static const int32_t kToLowercaseTable0[926] = {
8171, -448, 8172, -28, 1073750008, -512, 8185, -512, 1073750010, -504, 8187, -504, 8188, -36 }; // NOLINT
static const uint16_t kToLowercaseMultiStrings0Size = 2; // NOLINT
static const MultiCharacterSpecialCase<1> kToLowercaseMultiStrings1[1] = { // NOLINT
- {{-1}} }; // NOLINT
+ {{kSentinel}} }; // NOLINT
static const uint16_t kToLowercaseTable1Size = 69; // NOLINT
static const int32_t kToLowercaseTable1[138] = {
294, -30068, 298, -33532, 299, -33048, 306, 112, 1073742176, 64, 367, 64, 387, 4, 1073743030, 104, // NOLINT
@@ -900,7 +902,7 @@ static const int32_t kToLowercaseTable1[138] = {
3290, 4, 3292, 4, 3294, 4, 3296, 4, 3298, 4 }; // NOLINT
static const uint16_t kToLowercaseMultiStrings1Size = 1; // NOLINT
static const MultiCharacterSpecialCase<1> kToLowercaseMultiStrings7[1] = { // NOLINT
- {{-1}} }; // NOLINT
+ {{kSentinel}} }; // NOLINT
static const uint16_t kToLowercaseTable7Size = 2; // NOLINT
static const int32_t kToLowercaseTable7[4] = {
1073749793, 128, 7994, 128 }; // NOLINT
@@ -937,22 +939,22 @@ int ToLowercase::Convert(uchar c,
}
static const MultiCharacterSpecialCase<3> kToUppercaseMultiStrings0[62] = { // NOLINT
- {{83, 83, -1}}, {{700, 78, -1}}, {{74, 780, -1}}, {{921, 776, 769}}, // NOLINT
- {{933, 776, 769}}, {{1333, 1362, -1}}, {{72, 817, -1}}, {{84, 776, -1}}, // NOLINT
- {{87, 778, -1}}, {{89, 778, -1}}, {{65, 702, -1}}, {{933, 787, -1}}, // NOLINT
- {{933, 787, 768}}, {{933, 787, 769}}, {{933, 787, 834}}, {{7944, 921, -1}}, // NOLINT
- {{7945, 921, -1}}, {{7946, 921, -1}}, {{7947, 921, -1}}, {{7948, 921, -1}}, // NOLINT
- {{7949, 921, -1}}, {{7950, 921, -1}}, {{7951, 921, -1}}, {{7976, 921, -1}}, // NOLINT
- {{7977, 921, -1}}, {{7978, 921, -1}}, {{7979, 921, -1}}, {{7980, 921, -1}}, // NOLINT
- {{7981, 921, -1}}, {{7982, 921, -1}}, {{7983, 921, -1}}, {{8040, 921, -1}}, // NOLINT
- {{8041, 921, -1}}, {{8042, 921, -1}}, {{8043, 921, -1}}, {{8044, 921, -1}}, // NOLINT
- {{8045, 921, -1}}, {{8046, 921, -1}}, {{8047, 921, -1}}, {{8122, 921, -1}}, // NOLINT
- {{913, 921, -1}}, {{902, 921, -1}}, {{913, 834, -1}}, {{913, 834, 921}}, // NOLINT
- {{8138, 921, -1}}, {{919, 921, -1}}, {{905, 921, -1}}, {{919, 834, -1}}, // NOLINT
- {{919, 834, 921}}, {{921, 776, 768}}, {{921, 834, -1}}, {{921, 776, 834}}, // NOLINT
- {{933, 776, 768}}, {{929, 787, -1}}, {{933, 834, -1}}, {{933, 776, 834}}, // NOLINT
- {{8186, 921, -1}}, {{937, 921, -1}}, {{911, 921, -1}}, {{937, 834, -1}}, // NOLINT
- {{937, 834, 921}}, {{-1}} }; // NOLINT
+ {{83, 83, kSentinel}}, {{700, 78, kSentinel}}, {{74, 780, kSentinel}}, {{921, 776, 769}}, // NOLINT
+ {{933, 776, 769}}, {{1333, 1362, kSentinel}}, {{72, 817, kSentinel}}, {{84, 776, kSentinel}}, // NOLINT
+ {{87, 778, kSentinel}}, {{89, 778, kSentinel}}, {{65, 702, kSentinel}}, {{933, 787, kSentinel}}, // NOLINT
+ {{933, 787, 768}}, {{933, 787, 769}}, {{933, 787, 834}}, {{7944, 921, kSentinel}}, // NOLINT
+ {{7945, 921, kSentinel}}, {{7946, 921, kSentinel}}, {{7947, 921, kSentinel}}, {{7948, 921, kSentinel}}, // NOLINT
+ {{7949, 921, kSentinel}}, {{7950, 921, kSentinel}}, {{7951, 921, kSentinel}}, {{7976, 921, kSentinel}}, // NOLINT
+ {{7977, 921, kSentinel}}, {{7978, 921, kSentinel}}, {{7979, 921, kSentinel}}, {{7980, 921, kSentinel}}, // NOLINT
+ {{7981, 921, kSentinel}}, {{7982, 921, kSentinel}}, {{7983, 921, kSentinel}}, {{8040, 921, kSentinel}}, // NOLINT
+ {{8041, 921, kSentinel}}, {{8042, 921, kSentinel}}, {{8043, 921, kSentinel}}, {{8044, 921, kSentinel}}, // NOLINT
+ {{8045, 921, kSentinel}}, {{8046, 921, kSentinel}}, {{8047, 921, kSentinel}}, {{8122, 921, kSentinel}}, // NOLINT
+ {{913, 921, kSentinel}}, {{902, 921, kSentinel}}, {{913, 834, kSentinel}}, {{913, 834, 921}}, // NOLINT
+ {{8138, 921, kSentinel}}, {{919, 921, kSentinel}}, {{905, 921, kSentinel}}, {{919, 834, kSentinel}}, // NOLINT
+ {{919, 834, 921}}, {{921, 776, 768}}, {{921, 834, kSentinel}}, {{921, 776, 834}}, // NOLINT
+ {{933, 776, 768}}, {{929, 787, kSentinel}}, {{933, 834, kSentinel}}, {{933, 776, 834}}, // NOLINT
+ {{8186, 921, kSentinel}}, {{937, 921, kSentinel}}, {{911, 921, kSentinel}}, {{937, 834, kSentinel}}, // NOLINT
+ {{937, 834, 921}}, {{kSentinel}} }; // NOLINT
static const uint16_t kToUppercaseTable0Size = 554; // NOLINT
static const int32_t kToUppercaseTable0[1108] = {
1073741921, -128, 122, -128, 181, 2972, 223, 1, 1073742048, -128, 246, -128, 1073742072, -128, 254, -128, // NOLINT
@@ -1027,7 +1029,7 @@ static const int32_t kToUppercaseTable0[1108] = {
8183, 241, 8188, 229 }; // NOLINT
static const uint16_t kToUppercaseMultiStrings0Size = 62; // NOLINT
static const MultiCharacterSpecialCase<1> kToUppercaseMultiStrings1[1] = { // NOLINT
- {{-1}} }; // NOLINT
+ {{kSentinel}} }; // NOLINT
static const uint16_t kToUppercaseTable1Size = 67; // NOLINT
static const int32_t kToUppercaseTable1[134] = {
334, -112, 1073742192, -64, 383, -64, 388, -4, 1073743056, -104, 1257, -104, 1073744944, -192, 3166, -192, // NOLINT
@@ -1041,9 +1043,9 @@ static const int32_t kToUppercaseTable1[134] = {
3299, -4, 1073745152, -29056, 3365, -29056 }; // NOLINT
static const uint16_t kToUppercaseMultiStrings1Size = 1; // NOLINT
static const MultiCharacterSpecialCase<3> kToUppercaseMultiStrings7[12] = { // NOLINT
- {{70, 70, -1}}, {{70, 73, -1}}, {{70, 76, -1}}, {{70, 70, 73}}, // NOLINT
- {{70, 70, 76}}, {{83, 84, -1}}, {{1348, 1350, -1}}, {{1348, 1333, -1}}, // NOLINT
- {{1348, 1339, -1}}, {{1358, 1350, -1}}, {{1348, 1341, -1}}, {{-1}} }; // NOLINT
+ {{70, 70, kSentinel}}, {{70, 73, kSentinel}}, {{70, 76, kSentinel}}, {{70, 70, 73}}, // NOLINT
+ {{70, 70, 76}}, {{83, 84, kSentinel}}, {{1348, 1350, kSentinel}}, {{1348, 1333, kSentinel}}, // NOLINT
+ {{1348, 1339, kSentinel}}, {{1358, 1350, kSentinel}}, {{1348, 1341, kSentinel}}, {{kSentinel}} }; // NOLINT
static const uint16_t kToUppercaseTable7Size = 14; // NOLINT
static const int32_t kToUppercaseTable7[28] = {
6912, 1, 6913, 5, 6914, 9, 6915, 13, 6916, 17, 6917, 21, 6918, 21, 6931, 25, // NOLINT
@@ -1081,7 +1083,7 @@ int ToUppercase::Convert(uchar c,
}
static const MultiCharacterSpecialCase<1> kEcma262CanonicalizeMultiStrings0[1] = { // NOLINT
- {{-1}} }; // NOLINT
+ {{kSentinel}} }; // NOLINT
static const uint16_t kEcma262CanonicalizeTable0Size = 462; // NOLINT
static const int32_t kEcma262CanonicalizeTable0[924] = {
1073741921, -128, 122, -128, 181, 2972, 1073742048, -128, 246, -128, 1073742072, -128, 254, -128, 255, 484, // NOLINT
@@ -1144,7 +1146,7 @@ static const int32_t kEcma262CanonicalizeTable0[924] = {
8126, -28820, 1073749968, 32, 8145, 32, 1073749984, 32, 8161, 32, 8165, 28 }; // NOLINT
static const uint16_t kEcma262CanonicalizeMultiStrings0Size = 1; // NOLINT
static const MultiCharacterSpecialCase<1> kEcma262CanonicalizeMultiStrings1[1] = { // NOLINT
- {{-1}} }; // NOLINT
+ {{kSentinel}} }; // NOLINT
static const uint16_t kEcma262CanonicalizeTable1Size = 67; // NOLINT
static const int32_t kEcma262CanonicalizeTable1[134] = {
334, -112, 1073742192, -64, 383, -64, 388, -4, 1073743056, -104, 1257, -104, 1073744944, -192, 3166, -192, // NOLINT
@@ -1158,7 +1160,7 @@ static const int32_t kEcma262CanonicalizeTable1[134] = {
3299, -4, 1073745152, -29056, 3365, -29056 }; // NOLINT
static const uint16_t kEcma262CanonicalizeMultiStrings1Size = 1; // NOLINT
static const MultiCharacterSpecialCase<1> kEcma262CanonicalizeMultiStrings7[1] = { // NOLINT
- {{-1}} }; // NOLINT
+ {{kSentinel}} }; // NOLINT
static const uint16_t kEcma262CanonicalizeTable7Size = 2; // NOLINT
static const int32_t kEcma262CanonicalizeTable7[4] = {
1073749825, -128, 8026, -128 }; // NOLINT
@@ -1195,124 +1197,124 @@ int Ecma262Canonicalize::Convert(uchar c,
}
static const MultiCharacterSpecialCase<4> kEcma262UnCanonicalizeMultiStrings0[469] = { // NOLINT
- {{65, 97, -1}}, {{90, 122, -1}}, {{181, 924, 956, -1}}, {{192, 224, -1}}, // NOLINT
- {{214, 246, -1}}, {{216, 248, -1}}, {{222, 254, -1}}, {{255, 376, -1}}, // NOLINT
- {{256, 257, -1}}, {{258, 259, -1}}, {{260, 261, -1}}, {{262, 263, -1}}, // NOLINT
- {{264, 265, -1}}, {{266, 267, -1}}, {{268, 269, -1}}, {{270, 271, -1}}, // NOLINT
- {{272, 273, -1}}, {{274, 275, -1}}, {{276, 277, -1}}, {{278, 279, -1}}, // NOLINT
- {{280, 281, -1}}, {{282, 283, -1}}, {{284, 285, -1}}, {{286, 287, -1}}, // NOLINT
- {{288, 289, -1}}, {{290, 291, -1}}, {{292, 293, -1}}, {{294, 295, -1}}, // NOLINT
- {{296, 297, -1}}, {{298, 299, -1}}, {{300, 301, -1}}, {{302, 303, -1}}, // NOLINT
- {{306, 307, -1}}, {{308, 309, -1}}, {{310, 311, -1}}, {{313, 314, -1}}, // NOLINT
- {{315, 316, -1}}, {{317, 318, -1}}, {{319, 320, -1}}, {{321, 322, -1}}, // NOLINT
- {{323, 324, -1}}, {{325, 326, -1}}, {{327, 328, -1}}, {{330, 331, -1}}, // NOLINT
- {{332, 333, -1}}, {{334, 335, -1}}, {{336, 337, -1}}, {{338, 339, -1}}, // NOLINT
- {{340, 341, -1}}, {{342, 343, -1}}, {{344, 345, -1}}, {{346, 347, -1}}, // NOLINT
- {{348, 349, -1}}, {{350, 351, -1}}, {{352, 353, -1}}, {{354, 355, -1}}, // NOLINT
- {{356, 357, -1}}, {{358, 359, -1}}, {{360, 361, -1}}, {{362, 363, -1}}, // NOLINT
- {{364, 365, -1}}, {{366, 367, -1}}, {{368, 369, -1}}, {{370, 371, -1}}, // NOLINT
- {{372, 373, -1}}, {{374, 375, -1}}, {{377, 378, -1}}, {{379, 380, -1}}, // NOLINT
- {{381, 382, -1}}, {{384, 579, -1}}, {{385, 595, -1}}, {{386, 387, -1}}, // NOLINT
- {{388, 389, -1}}, {{390, 596, -1}}, {{391, 392, -1}}, {{393, 598, -1}}, // NOLINT
- {{394, 599, -1}}, {{395, 396, -1}}, {{398, 477, -1}}, {{399, 601, -1}}, // NOLINT
- {{400, 603, -1}}, {{401, 402, -1}}, {{403, 608, -1}}, {{404, 611, -1}}, // NOLINT
- {{405, 502, -1}}, {{406, 617, -1}}, {{407, 616, -1}}, {{408, 409, -1}}, // NOLINT
- {{410, 573, -1}}, {{412, 623, -1}}, {{413, 626, -1}}, {{414, 544, -1}}, // NOLINT
- {{415, 629, -1}}, {{416, 417, -1}}, {{418, 419, -1}}, {{420, 421, -1}}, // NOLINT
- {{422, 640, -1}}, {{423, 424, -1}}, {{425, 643, -1}}, {{428, 429, -1}}, // NOLINT
- {{430, 648, -1}}, {{431, 432, -1}}, {{433, 650, -1}}, {{434, 651, -1}}, // NOLINT
- {{435, 436, -1}}, {{437, 438, -1}}, {{439, 658, -1}}, {{440, 441, -1}}, // NOLINT
- {{444, 445, -1}}, {{447, 503, -1}}, {{452, 453, 454, -1}}, {{455, 456, 457, -1}}, // NOLINT
- {{458, 459, 460, -1}}, {{461, 462, -1}}, {{463, 464, -1}}, {{465, 466, -1}}, // NOLINT
- {{467, 468, -1}}, {{469, 470, -1}}, {{471, 472, -1}}, {{473, 474, -1}}, // NOLINT
- {{475, 476, -1}}, {{478, 479, -1}}, {{480, 481, -1}}, {{482, 483, -1}}, // NOLINT
- {{484, 485, -1}}, {{486, 487, -1}}, {{488, 489, -1}}, {{490, 491, -1}}, // NOLINT
- {{492, 493, -1}}, {{494, 495, -1}}, {{497, 498, 499, -1}}, {{500, 501, -1}}, // NOLINT
- {{504, 505, -1}}, {{506, 507, -1}}, {{508, 509, -1}}, {{510, 511, -1}}, // NOLINT
- {{512, 513, -1}}, {{514, 515, -1}}, {{516, 517, -1}}, {{518, 519, -1}}, // NOLINT
- {{520, 521, -1}}, {{522, 523, -1}}, {{524, 525, -1}}, {{526, 527, -1}}, // NOLINT
- {{528, 529, -1}}, {{530, 531, -1}}, {{532, 533, -1}}, {{534, 535, -1}}, // NOLINT
- {{536, 537, -1}}, {{538, 539, -1}}, {{540, 541, -1}}, {{542, 543, -1}}, // NOLINT
- {{546, 547, -1}}, {{548, 549, -1}}, {{550, 551, -1}}, {{552, 553, -1}}, // NOLINT
- {{554, 555, -1}}, {{556, 557, -1}}, {{558, 559, -1}}, {{560, 561, -1}}, // NOLINT
- {{562, 563, -1}}, {{570, 11365, -1}}, {{571, 572, -1}}, {{574, 11366, -1}}, // NOLINT
- {{577, 578, -1}}, {{580, 649, -1}}, {{581, 652, -1}}, {{582, 583, -1}}, // NOLINT
- {{584, 585, -1}}, {{586, 587, -1}}, {{588, 589, -1}}, {{590, 591, -1}}, // NOLINT
- {{619, 11362, -1}}, {{637, 11364, -1}}, {{837, 921, 953, 8126}}, {{891, 1021, -1}}, // NOLINT
- {{893, 1023, -1}}, {{902, 940, -1}}, {{904, 941, -1}}, {{906, 943, -1}}, // NOLINT
- {{908, 972, -1}}, {{910, 973, -1}}, {{911, 974, -1}}, {{913, 945, -1}}, // NOLINT
- {{914, 946, 976, -1}}, {{915, 947, -1}}, {{916, 948, -1}}, {{917, 949, 1013, -1}}, // NOLINT
- {{918, 950, -1}}, {{919, 951, -1}}, {{920, 952, 977, -1}}, {{922, 954, 1008, -1}}, // NOLINT
- {{923, 955, -1}}, {{925, 957, -1}}, {{927, 959, -1}}, {{928, 960, 982, -1}}, // NOLINT
- {{929, 961, 1009, -1}}, {{931, 962, 963, -1}}, {{932, 964, -1}}, {{933, 965, -1}}, // NOLINT
- {{934, 966, 981, -1}}, {{935, 967, -1}}, {{939, 971, -1}}, {{984, 985, -1}}, // NOLINT
- {{986, 987, -1}}, {{988, 989, -1}}, {{990, 991, -1}}, {{992, 993, -1}}, // NOLINT
- {{994, 995, -1}}, {{996, 997, -1}}, {{998, 999, -1}}, {{1000, 1001, -1}}, // NOLINT
- {{1002, 1003, -1}}, {{1004, 1005, -1}}, {{1006, 1007, -1}}, {{1010, 1017, -1}}, // NOLINT
- {{1015, 1016, -1}}, {{1018, 1019, -1}}, {{1024, 1104, -1}}, {{1039, 1119, -1}}, // NOLINT
- {{1040, 1072, -1}}, {{1071, 1103, -1}}, {{1120, 1121, -1}}, {{1122, 1123, -1}}, // NOLINT
- {{1124, 1125, -1}}, {{1126, 1127, -1}}, {{1128, 1129, -1}}, {{1130, 1131, -1}}, // NOLINT
- {{1132, 1133, -1}}, {{1134, 1135, -1}}, {{1136, 1137, -1}}, {{1138, 1139, -1}}, // NOLINT
- {{1140, 1141, -1}}, {{1142, 1143, -1}}, {{1144, 1145, -1}}, {{1146, 1147, -1}}, // NOLINT
- {{1148, 1149, -1}}, {{1150, 1151, -1}}, {{1152, 1153, -1}}, {{1162, 1163, -1}}, // NOLINT
- {{1164, 1165, -1}}, {{1166, 1167, -1}}, {{1168, 1169, -1}}, {{1170, 1171, -1}}, // NOLINT
- {{1172, 1173, -1}}, {{1174, 1175, -1}}, {{1176, 1177, -1}}, {{1178, 1179, -1}}, // NOLINT
- {{1180, 1181, -1}}, {{1182, 1183, -1}}, {{1184, 1185, -1}}, {{1186, 1187, -1}}, // NOLINT
- {{1188, 1189, -1}}, {{1190, 1191, -1}}, {{1192, 1193, -1}}, {{1194, 1195, -1}}, // NOLINT
- {{1196, 1197, -1}}, {{1198, 1199, -1}}, {{1200, 1201, -1}}, {{1202, 1203, -1}}, // NOLINT
- {{1204, 1205, -1}}, {{1206, 1207, -1}}, {{1208, 1209, -1}}, {{1210, 1211, -1}}, // NOLINT
- {{1212, 1213, -1}}, {{1214, 1215, -1}}, {{1216, 1231, -1}}, {{1217, 1218, -1}}, // NOLINT
- {{1219, 1220, -1}}, {{1221, 1222, -1}}, {{1223, 1224, -1}}, {{1225, 1226, -1}}, // NOLINT
- {{1227, 1228, -1}}, {{1229, 1230, -1}}, {{1232, 1233, -1}}, {{1234, 1235, -1}}, // NOLINT
- {{1236, 1237, -1}}, {{1238, 1239, -1}}, {{1240, 1241, -1}}, {{1242, 1243, -1}}, // NOLINT
- {{1244, 1245, -1}}, {{1246, 1247, -1}}, {{1248, 1249, -1}}, {{1250, 1251, -1}}, // NOLINT
- {{1252, 1253, -1}}, {{1254, 1255, -1}}, {{1256, 1257, -1}}, {{1258, 1259, -1}}, // NOLINT
- {{1260, 1261, -1}}, {{1262, 1263, -1}}, {{1264, 1265, -1}}, {{1266, 1267, -1}}, // NOLINT
- {{1268, 1269, -1}}, {{1270, 1271, -1}}, {{1272, 1273, -1}}, {{1274, 1275, -1}}, // NOLINT
- {{1276, 1277, -1}}, {{1278, 1279, -1}}, {{1280, 1281, -1}}, {{1282, 1283, -1}}, // NOLINT
- {{1284, 1285, -1}}, {{1286, 1287, -1}}, {{1288, 1289, -1}}, {{1290, 1291, -1}}, // NOLINT
- {{1292, 1293, -1}}, {{1294, 1295, -1}}, {{1296, 1297, -1}}, {{1298, 1299, -1}}, // NOLINT
- {{1329, 1377, -1}}, {{1366, 1414, -1}}, {{4256, 11520, -1}}, {{4293, 11557, -1}}, // NOLINT
- {{7549, 11363, -1}}, {{7680, 7681, -1}}, {{7682, 7683, -1}}, {{7684, 7685, -1}}, // NOLINT
- {{7686, 7687, -1}}, {{7688, 7689, -1}}, {{7690, 7691, -1}}, {{7692, 7693, -1}}, // NOLINT
- {{7694, 7695, -1}}, {{7696, 7697, -1}}, {{7698, 7699, -1}}, {{7700, 7701, -1}}, // NOLINT
- {{7702, 7703, -1}}, {{7704, 7705, -1}}, {{7706, 7707, -1}}, {{7708, 7709, -1}}, // NOLINT
- {{7710, 7711, -1}}, {{7712, 7713, -1}}, {{7714, 7715, -1}}, {{7716, 7717, -1}}, // NOLINT
- {{7718, 7719, -1}}, {{7720, 7721, -1}}, {{7722, 7723, -1}}, {{7724, 7725, -1}}, // NOLINT
- {{7726, 7727, -1}}, {{7728, 7729, -1}}, {{7730, 7731, -1}}, {{7732, 7733, -1}}, // NOLINT
- {{7734, 7735, -1}}, {{7736, 7737, -1}}, {{7738, 7739, -1}}, {{7740, 7741, -1}}, // NOLINT
- {{7742, 7743, -1}}, {{7744, 7745, -1}}, {{7746, 7747, -1}}, {{7748, 7749, -1}}, // NOLINT
- {{7750, 7751, -1}}, {{7752, 7753, -1}}, {{7754, 7755, -1}}, {{7756, 7757, -1}}, // NOLINT
- {{7758, 7759, -1}}, {{7760, 7761, -1}}, {{7762, 7763, -1}}, {{7764, 7765, -1}}, // NOLINT
- {{7766, 7767, -1}}, {{7768, 7769, -1}}, {{7770, 7771, -1}}, {{7772, 7773, -1}}, // NOLINT
- {{7774, 7775, -1}}, {{7776, 7777, 7835, -1}}, {{7778, 7779, -1}}, {{7780, 7781, -1}}, // NOLINT
- {{7782, 7783, -1}}, {{7784, 7785, -1}}, {{7786, 7787, -1}}, {{7788, 7789, -1}}, // NOLINT
- {{7790, 7791, -1}}, {{7792, 7793, -1}}, {{7794, 7795, -1}}, {{7796, 7797, -1}}, // NOLINT
- {{7798, 7799, -1}}, {{7800, 7801, -1}}, {{7802, 7803, -1}}, {{7804, 7805, -1}}, // NOLINT
- {{7806, 7807, -1}}, {{7808, 7809, -1}}, {{7810, 7811, -1}}, {{7812, 7813, -1}}, // NOLINT
- {{7814, 7815, -1}}, {{7816, 7817, -1}}, {{7818, 7819, -1}}, {{7820, 7821, -1}}, // NOLINT
- {{7822, 7823, -1}}, {{7824, 7825, -1}}, {{7826, 7827, -1}}, {{7828, 7829, -1}}, // NOLINT
- {{7840, 7841, -1}}, {{7842, 7843, -1}}, {{7844, 7845, -1}}, {{7846, 7847, -1}}, // NOLINT
- {{7848, 7849, -1}}, {{7850, 7851, -1}}, {{7852, 7853, -1}}, {{7854, 7855, -1}}, // NOLINT
- {{7856, 7857, -1}}, {{7858, 7859, -1}}, {{7860, 7861, -1}}, {{7862, 7863, -1}}, // NOLINT
- {{7864, 7865, -1}}, {{7866, 7867, -1}}, {{7868, 7869, -1}}, {{7870, 7871, -1}}, // NOLINT
- {{7872, 7873, -1}}, {{7874, 7875, -1}}, {{7876, 7877, -1}}, {{7878, 7879, -1}}, // NOLINT
- {{7880, 7881, -1}}, {{7882, 7883, -1}}, {{7884, 7885, -1}}, {{7886, 7887, -1}}, // NOLINT
- {{7888, 7889, -1}}, {{7890, 7891, -1}}, {{7892, 7893, -1}}, {{7894, 7895, -1}}, // NOLINT
- {{7896, 7897, -1}}, {{7898, 7899, -1}}, {{7900, 7901, -1}}, {{7902, 7903, -1}}, // NOLINT
- {{7904, 7905, -1}}, {{7906, 7907, -1}}, {{7908, 7909, -1}}, {{7910, 7911, -1}}, // NOLINT
- {{7912, 7913, -1}}, {{7914, 7915, -1}}, {{7916, 7917, -1}}, {{7918, 7919, -1}}, // NOLINT
- {{7920, 7921, -1}}, {{7922, 7923, -1}}, {{7924, 7925, -1}}, {{7926, 7927, -1}}, // NOLINT
- {{7928, 7929, -1}}, {{7936, 7944, -1}}, {{7943, 7951, -1}}, {{7952, 7960, -1}}, // NOLINT
- {{7957, 7965, -1}}, {{7968, 7976, -1}}, {{7975, 7983, -1}}, {{7984, 7992, -1}}, // NOLINT
- {{7991, 7999, -1}}, {{8000, 8008, -1}}, {{8005, 8013, -1}}, {{8017, 8025, -1}}, // NOLINT
- {{8019, 8027, -1}}, {{8021, 8029, -1}}, {{8023, 8031, -1}}, {{8032, 8040, -1}}, // NOLINT
- {{8039, 8047, -1}}, {{8048, 8122, -1}}, {{8049, 8123, -1}}, {{8050, 8136, -1}}, // NOLINT
- {{8053, 8139, -1}}, {{8054, 8154, -1}}, {{8055, 8155, -1}}, {{8056, 8184, -1}}, // NOLINT
- {{8057, 8185, -1}}, {{8058, 8170, -1}}, {{8059, 8171, -1}}, {{8060, 8186, -1}}, // NOLINT
- {{8061, 8187, -1}}, {{8112, 8120, -1}}, {{8113, 8121, -1}}, {{8144, 8152, -1}}, // NOLINT
- {{8145, 8153, -1}}, {{8160, 8168, -1}}, {{8161, 8169, -1}}, {{8165, 8172, -1}}, // NOLINT
- {{-1}} }; // NOLINT
+ {{65, 97, kSentinel}}, {{90, 122, kSentinel}}, {{181, 924, 956, kSentinel}}, {{192, 224, kSentinel}}, // NOLINT
+ {{214, 246, kSentinel}}, {{216, 248, kSentinel}}, {{222, 254, kSentinel}}, {{255, 376, kSentinel}}, // NOLINT
+ {{256, 257, kSentinel}}, {{258, 259, kSentinel}}, {{260, 261, kSentinel}}, {{262, 263, kSentinel}}, // NOLINT
+ {{264, 265, kSentinel}}, {{266, 267, kSentinel}}, {{268, 269, kSentinel}}, {{270, 271, kSentinel}}, // NOLINT
+ {{272, 273, kSentinel}}, {{274, 275, kSentinel}}, {{276, 277, kSentinel}}, {{278, 279, kSentinel}}, // NOLINT
+ {{280, 281, kSentinel}}, {{282, 283, kSentinel}}, {{284, 285, kSentinel}}, {{286, 287, kSentinel}}, // NOLINT
+ {{288, 289, kSentinel}}, {{290, 291, kSentinel}}, {{292, 293, kSentinel}}, {{294, 295, kSentinel}}, // NOLINT
+ {{296, 297, kSentinel}}, {{298, 299, kSentinel}}, {{300, 301, kSentinel}}, {{302, 303, kSentinel}}, // NOLINT
+ {{306, 307, kSentinel}}, {{308, 309, kSentinel}}, {{310, 311, kSentinel}}, {{313, 314, kSentinel}}, // NOLINT
+ {{315, 316, kSentinel}}, {{317, 318, kSentinel}}, {{319, 320, kSentinel}}, {{321, 322, kSentinel}}, // NOLINT
+ {{323, 324, kSentinel}}, {{325, 326, kSentinel}}, {{327, 328, kSentinel}}, {{330, 331, kSentinel}}, // NOLINT
+ {{332, 333, kSentinel}}, {{334, 335, kSentinel}}, {{336, 337, kSentinel}}, {{338, 339, kSentinel}}, // NOLINT
+ {{340, 341, kSentinel}}, {{342, 343, kSentinel}}, {{344, 345, kSentinel}}, {{346, 347, kSentinel}}, // NOLINT
+ {{348, 349, kSentinel}}, {{350, 351, kSentinel}}, {{352, 353, kSentinel}}, {{354, 355, kSentinel}}, // NOLINT
+ {{356, 357, kSentinel}}, {{358, 359, kSentinel}}, {{360, 361, kSentinel}}, {{362, 363, kSentinel}}, // NOLINT
+ {{364, 365, kSentinel}}, {{366, 367, kSentinel}}, {{368, 369, kSentinel}}, {{370, 371, kSentinel}}, // NOLINT
+ {{372, 373, kSentinel}}, {{374, 375, kSentinel}}, {{377, 378, kSentinel}}, {{379, 380, kSentinel}}, // NOLINT
+ {{381, 382, kSentinel}}, {{384, 579, kSentinel}}, {{385, 595, kSentinel}}, {{386, 387, kSentinel}}, // NOLINT
+ {{388, 389, kSentinel}}, {{390, 596, kSentinel}}, {{391, 392, kSentinel}}, {{393, 598, kSentinel}}, // NOLINT
+ {{394, 599, kSentinel}}, {{395, 396, kSentinel}}, {{398, 477, kSentinel}}, {{399, 601, kSentinel}}, // NOLINT
+ {{400, 603, kSentinel}}, {{401, 402, kSentinel}}, {{403, 608, kSentinel}}, {{404, 611, kSentinel}}, // NOLINT
+ {{405, 502, kSentinel}}, {{406, 617, kSentinel}}, {{407, 616, kSentinel}}, {{408, 409, kSentinel}}, // NOLINT
+ {{410, 573, kSentinel}}, {{412, 623, kSentinel}}, {{413, 626, kSentinel}}, {{414, 544, kSentinel}}, // NOLINT
+ {{415, 629, kSentinel}}, {{416, 417, kSentinel}}, {{418, 419, kSentinel}}, {{420, 421, kSentinel}}, // NOLINT
+ {{422, 640, kSentinel}}, {{423, 424, kSentinel}}, {{425, 643, kSentinel}}, {{428, 429, kSentinel}}, // NOLINT
+ {{430, 648, kSentinel}}, {{431, 432, kSentinel}}, {{433, 650, kSentinel}}, {{434, 651, kSentinel}}, // NOLINT
+ {{435, 436, kSentinel}}, {{437, 438, kSentinel}}, {{439, 658, kSentinel}}, {{440, 441, kSentinel}}, // NOLINT
+ {{444, 445, kSentinel}}, {{447, 503, kSentinel}}, {{452, 453, 454, kSentinel}}, {{455, 456, 457, kSentinel}}, // NOLINT
+ {{458, 459, 460, kSentinel}}, {{461, 462, kSentinel}}, {{463, 464, kSentinel}}, {{465, 466, kSentinel}}, // NOLINT
+ {{467, 468, kSentinel}}, {{469, 470, kSentinel}}, {{471, 472, kSentinel}}, {{473, 474, kSentinel}}, // NOLINT
+ {{475, 476, kSentinel}}, {{478, 479, kSentinel}}, {{480, 481, kSentinel}}, {{482, 483, kSentinel}}, // NOLINT
+ {{484, 485, kSentinel}}, {{486, 487, kSentinel}}, {{488, 489, kSentinel}}, {{490, 491, kSentinel}}, // NOLINT
+ {{492, 493, kSentinel}}, {{494, 495, kSentinel}}, {{497, 498, 499, kSentinel}}, {{500, 501, kSentinel}}, // NOLINT
+ {{504, 505, kSentinel}}, {{506, 507, kSentinel}}, {{508, 509, kSentinel}}, {{510, 511, kSentinel}}, // NOLINT
+ {{512, 513, kSentinel}}, {{514, 515, kSentinel}}, {{516, 517, kSentinel}}, {{518, 519, kSentinel}}, // NOLINT
+ {{520, 521, kSentinel}}, {{522, 523, kSentinel}}, {{524, 525, kSentinel}}, {{526, 527, kSentinel}}, // NOLINT
+ {{528, 529, kSentinel}}, {{530, 531, kSentinel}}, {{532, 533, kSentinel}}, {{534, 535, kSentinel}}, // NOLINT
+ {{536, 537, kSentinel}}, {{538, 539, kSentinel}}, {{540, 541, kSentinel}}, {{542, 543, kSentinel}}, // NOLINT
+ {{546, 547, kSentinel}}, {{548, 549, kSentinel}}, {{550, 551, kSentinel}}, {{552, 553, kSentinel}}, // NOLINT
+ {{554, 555, kSentinel}}, {{556, 557, kSentinel}}, {{558, 559, kSentinel}}, {{560, 561, kSentinel}}, // NOLINT
+ {{562, 563, kSentinel}}, {{570, 11365, kSentinel}}, {{571, 572, kSentinel}}, {{574, 11366, kSentinel}}, // NOLINT
+ {{577, 578, kSentinel}}, {{580, 649, kSentinel}}, {{581, 652, kSentinel}}, {{582, 583, kSentinel}}, // NOLINT
+ {{584, 585, kSentinel}}, {{586, 587, kSentinel}}, {{588, 589, kSentinel}}, {{590, 591, kSentinel}}, // NOLINT
+ {{619, 11362, kSentinel}}, {{637, 11364, kSentinel}}, {{837, 921, 953, 8126}}, {{891, 1021, kSentinel}}, // NOLINT
+ {{893, 1023, kSentinel}}, {{902, 940, kSentinel}}, {{904, 941, kSentinel}}, {{906, 943, kSentinel}}, // NOLINT
+ {{908, 972, kSentinel}}, {{910, 973, kSentinel}}, {{911, 974, kSentinel}}, {{913, 945, kSentinel}}, // NOLINT
+ {{914, 946, 976, kSentinel}}, {{915, 947, kSentinel}}, {{916, 948, kSentinel}}, {{917, 949, 1013, kSentinel}}, // NOLINT
+ {{918, 950, kSentinel}}, {{919, 951, kSentinel}}, {{920, 952, 977, kSentinel}}, {{922, 954, 1008, kSentinel}}, // NOLINT
+ {{923, 955, kSentinel}}, {{925, 957, kSentinel}}, {{927, 959, kSentinel}}, {{928, 960, 982, kSentinel}}, // NOLINT
+ {{929, 961, 1009, kSentinel}}, {{931, 962, 963, kSentinel}}, {{932, 964, kSentinel}}, {{933, 965, kSentinel}}, // NOLINT
+ {{934, 966, 981, kSentinel}}, {{935, 967, kSentinel}}, {{939, 971, kSentinel}}, {{984, 985, kSentinel}}, // NOLINT
+ {{986, 987, kSentinel}}, {{988, 989, kSentinel}}, {{990, 991, kSentinel}}, {{992, 993, kSentinel}}, // NOLINT
+ {{994, 995, kSentinel}}, {{996, 997, kSentinel}}, {{998, 999, kSentinel}}, {{1000, 1001, kSentinel}}, // NOLINT
+ {{1002, 1003, kSentinel}}, {{1004, 1005, kSentinel}}, {{1006, 1007, kSentinel}}, {{1010, 1017, kSentinel}}, // NOLINT
+ {{1015, 1016, kSentinel}}, {{1018, 1019, kSentinel}}, {{1024, 1104, kSentinel}}, {{1039, 1119, kSentinel}}, // NOLINT
+ {{1040, 1072, kSentinel}}, {{1071, 1103, kSentinel}}, {{1120, 1121, kSentinel}}, {{1122, 1123, kSentinel}}, // NOLINT
+ {{1124, 1125, kSentinel}}, {{1126, 1127, kSentinel}}, {{1128, 1129, kSentinel}}, {{1130, 1131, kSentinel}}, // NOLINT
+ {{1132, 1133, kSentinel}}, {{1134, 1135, kSentinel}}, {{1136, 1137, kSentinel}}, {{1138, 1139, kSentinel}}, // NOLINT
+ {{1140, 1141, kSentinel}}, {{1142, 1143, kSentinel}}, {{1144, 1145, kSentinel}}, {{1146, 1147, kSentinel}}, // NOLINT
+ {{1148, 1149, kSentinel}}, {{1150, 1151, kSentinel}}, {{1152, 1153, kSentinel}}, {{1162, 1163, kSentinel}}, // NOLINT
+ {{1164, 1165, kSentinel}}, {{1166, 1167, kSentinel}}, {{1168, 1169, kSentinel}}, {{1170, 1171, kSentinel}}, // NOLINT
+ {{1172, 1173, kSentinel}}, {{1174, 1175, kSentinel}}, {{1176, 1177, kSentinel}}, {{1178, 1179, kSentinel}}, // NOLINT
+ {{1180, 1181, kSentinel}}, {{1182, 1183, kSentinel}}, {{1184, 1185, kSentinel}}, {{1186, 1187, kSentinel}}, // NOLINT
+ {{1188, 1189, kSentinel}}, {{1190, 1191, kSentinel}}, {{1192, 1193, kSentinel}}, {{1194, 1195, kSentinel}}, // NOLINT
+ {{1196, 1197, kSentinel}}, {{1198, 1199, kSentinel}}, {{1200, 1201, kSentinel}}, {{1202, 1203, kSentinel}}, // NOLINT
+ {{1204, 1205, kSentinel}}, {{1206, 1207, kSentinel}}, {{1208, 1209, kSentinel}}, {{1210, 1211, kSentinel}}, // NOLINT
+ {{1212, 1213, kSentinel}}, {{1214, 1215, kSentinel}}, {{1216, 1231, kSentinel}}, {{1217, 1218, kSentinel}}, // NOLINT
+ {{1219, 1220, kSentinel}}, {{1221, 1222, kSentinel}}, {{1223, 1224, kSentinel}}, {{1225, 1226, kSentinel}}, // NOLINT
+ {{1227, 1228, kSentinel}}, {{1229, 1230, kSentinel}}, {{1232, 1233, kSentinel}}, {{1234, 1235, kSentinel}}, // NOLINT
+ {{1236, 1237, kSentinel}}, {{1238, 1239, kSentinel}}, {{1240, 1241, kSentinel}}, {{1242, 1243, kSentinel}}, // NOLINT
+ {{1244, 1245, kSentinel}}, {{1246, 1247, kSentinel}}, {{1248, 1249, kSentinel}}, {{1250, 1251, kSentinel}}, // NOLINT
+ {{1252, 1253, kSentinel}}, {{1254, 1255, kSentinel}}, {{1256, 1257, kSentinel}}, {{1258, 1259, kSentinel}}, // NOLINT
+ {{1260, 1261, kSentinel}}, {{1262, 1263, kSentinel}}, {{1264, 1265, kSentinel}}, {{1266, 1267, kSentinel}}, // NOLINT
+ {{1268, 1269, kSentinel}}, {{1270, 1271, kSentinel}}, {{1272, 1273, kSentinel}}, {{1274, 1275, kSentinel}}, // NOLINT
+ {{1276, 1277, kSentinel}}, {{1278, 1279, kSentinel}}, {{1280, 1281, kSentinel}}, {{1282, 1283, kSentinel}}, // NOLINT
+ {{1284, 1285, kSentinel}}, {{1286, 1287, kSentinel}}, {{1288, 1289, kSentinel}}, {{1290, 1291, kSentinel}}, // NOLINT
+ {{1292, 1293, kSentinel}}, {{1294, 1295, kSentinel}}, {{1296, 1297, kSentinel}}, {{1298, 1299, kSentinel}}, // NOLINT
+ {{1329, 1377, kSentinel}}, {{1366, 1414, kSentinel}}, {{4256, 11520, kSentinel}}, {{4293, 11557, kSentinel}}, // NOLINT
+ {{7549, 11363, kSentinel}}, {{7680, 7681, kSentinel}}, {{7682, 7683, kSentinel}}, {{7684, 7685, kSentinel}}, // NOLINT
+ {{7686, 7687, kSentinel}}, {{7688, 7689, kSentinel}}, {{7690, 7691, kSentinel}}, {{7692, 7693, kSentinel}}, // NOLINT
+ {{7694, 7695, kSentinel}}, {{7696, 7697, kSentinel}}, {{7698, 7699, kSentinel}}, {{7700, 7701, kSentinel}}, // NOLINT
+ {{7702, 7703, kSentinel}}, {{7704, 7705, kSentinel}}, {{7706, 7707, kSentinel}}, {{7708, 7709, kSentinel}}, // NOLINT
+ {{7710, 7711, kSentinel}}, {{7712, 7713, kSentinel}}, {{7714, 7715, kSentinel}}, {{7716, 7717, kSentinel}}, // NOLINT
+ {{7718, 7719, kSentinel}}, {{7720, 7721, kSentinel}}, {{7722, 7723, kSentinel}}, {{7724, 7725, kSentinel}}, // NOLINT
+ {{7726, 7727, kSentinel}}, {{7728, 7729, kSentinel}}, {{7730, 7731, kSentinel}}, {{7732, 7733, kSentinel}}, // NOLINT
+ {{7734, 7735, kSentinel}}, {{7736, 7737, kSentinel}}, {{7738, 7739, kSentinel}}, {{7740, 7741, kSentinel}}, // NOLINT
+ {{7742, 7743, kSentinel}}, {{7744, 7745, kSentinel}}, {{7746, 7747, kSentinel}}, {{7748, 7749, kSentinel}}, // NOLINT
+ {{7750, 7751, kSentinel}}, {{7752, 7753, kSentinel}}, {{7754, 7755, kSentinel}}, {{7756, 7757, kSentinel}}, // NOLINT
+ {{7758, 7759, kSentinel}}, {{7760, 7761, kSentinel}}, {{7762, 7763, kSentinel}}, {{7764, 7765, kSentinel}}, // NOLINT
+ {{7766, 7767, kSentinel}}, {{7768, 7769, kSentinel}}, {{7770, 7771, kSentinel}}, {{7772, 7773, kSentinel}}, // NOLINT
+ {{7774, 7775, kSentinel}}, {{7776, 7777, 7835, kSentinel}}, {{7778, 7779, kSentinel}}, {{7780, 7781, kSentinel}}, // NOLINT
+ {{7782, 7783, kSentinel}}, {{7784, 7785, kSentinel}}, {{7786, 7787, kSentinel}}, {{7788, 7789, kSentinel}}, // NOLINT
+ {{7790, 7791, kSentinel}}, {{7792, 7793, kSentinel}}, {{7794, 7795, kSentinel}}, {{7796, 7797, kSentinel}}, // NOLINT
+ {{7798, 7799, kSentinel}}, {{7800, 7801, kSentinel}}, {{7802, 7803, kSentinel}}, {{7804, 7805, kSentinel}}, // NOLINT
+ {{7806, 7807, kSentinel}}, {{7808, 7809, kSentinel}}, {{7810, 7811, kSentinel}}, {{7812, 7813, kSentinel}}, // NOLINT
+ {{7814, 7815, kSentinel}}, {{7816, 7817, kSentinel}}, {{7818, 7819, kSentinel}}, {{7820, 7821, kSentinel}}, // NOLINT
+ {{7822, 7823, kSentinel}}, {{7824, 7825, kSentinel}}, {{7826, 7827, kSentinel}}, {{7828, 7829, kSentinel}}, // NOLINT
+ {{7840, 7841, kSentinel}}, {{7842, 7843, kSentinel}}, {{7844, 7845, kSentinel}}, {{7846, 7847, kSentinel}}, // NOLINT
+ {{7848, 7849, kSentinel}}, {{7850, 7851, kSentinel}}, {{7852, 7853, kSentinel}}, {{7854, 7855, kSentinel}}, // NOLINT
+ {{7856, 7857, kSentinel}}, {{7858, 7859, kSentinel}}, {{7860, 7861, kSentinel}}, {{7862, 7863, kSentinel}}, // NOLINT
+ {{7864, 7865, kSentinel}}, {{7866, 7867, kSentinel}}, {{7868, 7869, kSentinel}}, {{7870, 7871, kSentinel}}, // NOLINT
+ {{7872, 7873, kSentinel}}, {{7874, 7875, kSentinel}}, {{7876, 7877, kSentinel}}, {{7878, 7879, kSentinel}}, // NOLINT
+ {{7880, 7881, kSentinel}}, {{7882, 7883, kSentinel}}, {{7884, 7885, kSentinel}}, {{7886, 7887, kSentinel}}, // NOLINT
+ {{7888, 7889, kSentinel}}, {{7890, 7891, kSentinel}}, {{7892, 7893, kSentinel}}, {{7894, 7895, kSentinel}}, // NOLINT
+ {{7896, 7897, kSentinel}}, {{7898, 7899, kSentinel}}, {{7900, 7901, kSentinel}}, {{7902, 7903, kSentinel}}, // NOLINT
+ {{7904, 7905, kSentinel}}, {{7906, 7907, kSentinel}}, {{7908, 7909, kSentinel}}, {{7910, 7911, kSentinel}}, // NOLINT
+ {{7912, 7913, kSentinel}}, {{7914, 7915, kSentinel}}, {{7916, 7917, kSentinel}}, {{7918, 7919, kSentinel}}, // NOLINT
+ {{7920, 7921, kSentinel}}, {{7922, 7923, kSentinel}}, {{7924, 7925, kSentinel}}, {{7926, 7927, kSentinel}}, // NOLINT
+ {{7928, 7929, kSentinel}}, {{7936, 7944, kSentinel}}, {{7943, 7951, kSentinel}}, {{7952, 7960, kSentinel}}, // NOLINT
+ {{7957, 7965, kSentinel}}, {{7968, 7976, kSentinel}}, {{7975, 7983, kSentinel}}, {{7984, 7992, kSentinel}}, // NOLINT
+ {{7991, 7999, kSentinel}}, {{8000, 8008, kSentinel}}, {{8005, 8013, kSentinel}}, {{8017, 8025, kSentinel}}, // NOLINT
+ {{8019, 8027, kSentinel}}, {{8021, 8029, kSentinel}}, {{8023, 8031, kSentinel}}, {{8032, 8040, kSentinel}}, // NOLINT
+ {{8039, 8047, kSentinel}}, {{8048, 8122, kSentinel}}, {{8049, 8123, kSentinel}}, {{8050, 8136, kSentinel}}, // NOLINT
+ {{8053, 8139, kSentinel}}, {{8054, 8154, kSentinel}}, {{8055, 8155, kSentinel}}, {{8056, 8184, kSentinel}}, // NOLINT
+ {{8057, 8185, kSentinel}}, {{8058, 8170, kSentinel}}, {{8059, 8171, kSentinel}}, {{8060, 8186, kSentinel}}, // NOLINT
+ {{8061, 8187, kSentinel}}, {{8112, 8120, kSentinel}}, {{8113, 8121, kSentinel}}, {{8144, 8152, kSentinel}}, // NOLINT
+ {{8145, 8153, kSentinel}}, {{8160, 8168, kSentinel}}, {{8161, 8169, kSentinel}}, {{8165, 8172, kSentinel}}, // NOLINT
+ {{kSentinel}} }; // NOLINT
static const uint16_t kEcma262UnCanonicalizeTable0Size = 945; // NOLINT
static const int32_t kEcma262UnCanonicalizeTable0[1890] = {
1073741889, 1, 90, 5, 1073741921, 1, 122, 5, 181, 9, 1073742016, 13, 214, 17, 1073742040, 21, // NOLINT
@@ -1453,7 +1455,7 @@ static const MultiCharacterSpecialCase<2> kEcma262UnCanonicalizeMultiStrings1[71
{{11468, 11469}}, {{11470, 11471}}, {{11472, 11473}}, {{11474, 11475}}, // NOLINT
{{11476, 11477}}, {{11478, 11479}}, {{11480, 11481}}, {{11482, 11483}}, // NOLINT
{{11484, 11485}}, {{11486, 11487}}, {{11488, 11489}}, {{11490, 11491}}, // NOLINT
- {{4256, 11520}}, {{4293, 11557}}, {{-1}} }; // NOLINT
+ {{4256, 11520}}, {{4293, 11557}}, {{kSentinel}} }; // NOLINT
static const uint16_t kEcma262UnCanonicalizeTable1Size = 133; // NOLINT
static const int32_t kEcma262UnCanonicalizeTable1[266] = {
306, 1, 334, 1, 1073742176, 5, 367, 9, 1073742192, 5, 383, 9, 387, 13, 388, 13, // NOLINT
@@ -1475,7 +1477,7 @@ static const int32_t kEcma262UnCanonicalizeTable1[266] = {
3297, 265, 3298, 269, 3299, 269, 1073745152, 273, 3365, 277 }; // NOLINT
static const uint16_t kEcma262UnCanonicalizeMultiStrings1Size = 71; // NOLINT
static const MultiCharacterSpecialCase<2> kEcma262UnCanonicalizeMultiStrings7[3] = { // NOLINT
- {{65313, 65345}}, {{65338, 65370}}, {{-1}} }; // NOLINT
+ {{65313, 65345}}, {{65338, 65370}}, {{kSentinel}} }; // NOLINT
static const uint16_t kEcma262UnCanonicalizeTable7Size = 4; // NOLINT
static const int32_t kEcma262UnCanonicalizeTable7[8] = {
1073749793, 1, 7994, 5, 1073749825, 1, 8026, 5 }; // NOLINT
@@ -1512,7 +1514,7 @@ int Ecma262UnCanonicalize::Convert(uchar c,
}
static const MultiCharacterSpecialCase<1> kCanonicalizationRangeMultiStrings0[1] = { // NOLINT
- {{-1}} }; // NOLINT
+ {{kSentinel}} }; // NOLINT
static const uint16_t kCanonicalizationRangeTable0Size = 70; // NOLINT
static const int32_t kCanonicalizationRangeTable0[140] = {
1073741889, 100, 90, 0, 1073741921, 100, 122, 0, 1073742016, 88, 214, 0, 1073742040, 24, 222, 0, // NOLINT
@@ -1526,14 +1528,14 @@ static const int32_t kCanonicalizationRangeTable0[140] = {
1073749864, 28, 8047, 0, 1073749874, 12, 8053, 0, 1073749960, 12, 8139, 0 }; // NOLINT
static const uint16_t kCanonicalizationRangeMultiStrings0Size = 1; // NOLINT
static const MultiCharacterSpecialCase<1> kCanonicalizationRangeMultiStrings1[1] = { // NOLINT
- {{-1}} }; // NOLINT
+ {{kSentinel}} }; // NOLINT
static const uint16_t kCanonicalizationRangeTable1Size = 14; // NOLINT
static const int32_t kCanonicalizationRangeTable1[28] = {
1073742176, 60, 367, 0, 1073742192, 60, 383, 0, 1073743030, 100, 1231, 0, 1073743056, 100, 1257, 0, // NOLINT
1073744896, 184, 3118, 0, 1073744944, 184, 3166, 0, 1073745152, 148, 3365, 0 }; // NOLINT
static const uint16_t kCanonicalizationRangeMultiStrings1Size = 1; // NOLINT
static const MultiCharacterSpecialCase<1> kCanonicalizationRangeMultiStrings7[1] = { // NOLINT
- {{-1}} }; // NOLINT
+ {{kSentinel}} }; // NOLINT
static const uint16_t kCanonicalizationRangeTable7Size = 4; // NOLINT
static const int32_t kCanonicalizationRangeTable7[8] = {
1073749793, 100, 7994, 0, 1073749825, 100, 8026, 0 }; // NOLINT
diff --git a/src/utils.h b/src/utils.h
index 62b8726b..21e70d75 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -530,6 +530,24 @@ class Collector {
}
+ // Add a contiguous block of elements and return a vector backed
+ // by the added block.
+ // A basic Collector will keep this vector valid as long as the Collector
+ // is alive.
+ inline Vector<T> AddBlock(Vector<const T> source) {
+ if (source.length() > current_chunk_.length() - index_) {
+ Grow(source.length());
+ }
+ T* position = current_chunk_.start() + index_;
+ index_ += source.length();
+ size_ += source.length();
+ for (int i = 0; i < source.length(); i++) {
+ position[i] = source[i];
+ }
+ return Vector<T>(position, source.length());
+ }
+
+
// Write the contents of the collector into the provided vector.
void WriteTo(Vector<T> destination) {
ASSERT(size_ <= destination.length());
diff --git a/src/v8threads.cc b/src/v8threads.cc
index b6e656d2..8a5fe690 100644
--- a/src/v8threads.cc
+++ b/src/v8threads.cc
@@ -380,7 +380,8 @@ ContextSwitcher* ContextSwitcher::singleton_ = NULL;
ContextSwitcher::ContextSwitcher(int every_n_ms)
- : keep_going_(true),
+ : Thread("v8:CtxtSwitcher"),
+ keep_going_(true),
sleep_ms_(every_n_ms) {
}
diff --git a/src/v8utils.h b/src/v8utils.h
index 87efbcfe..e9623be6 100644
--- a/src/v8utils.h
+++ b/src/v8utils.h
@@ -29,10 +29,7 @@
#define V8_V8UTILS_H_
#include "utils.h"
-#ifdef ANDROID
-// Cherry pick from r6346 to build on Android.
-#include "platform.h"
-#endif
+#include "platform.h" // For va_list on Solaris.
namespace v8 {
namespace internal {
diff --git a/src/version.cc b/src/version.cc
index d2c09605..008f7799 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 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:
@@ -34,7 +34,7 @@
// cannot be changed without changing the SCons build script.
#define MAJOR_VERSION 3
#define MINOR_VERSION 0
-#define BUILD_NUMBER 4
+#define BUILD_NUMBER 6
#define PATCH_LEVEL 1
#define CANDIDATE_VERSION false
diff --git a/src/x64/assembler-x64.cc b/src/x64/assembler-x64.cc
index 8f15f23b..36299677 100644
--- a/src/x64/assembler-x64.cc
+++ b/src/x64/assembler-x64.cc
@@ -74,7 +74,7 @@ void CpuFeatures::Probe(bool portable) {
__ xor_(rax, rdx); // Different if CPUID is supported.
__ j(not_zero, &cpuid);
- // CPUID not supported. Clear the supported features in edx:eax.
+ // CPUID not supported. Clear the supported features in rax.
__ xor_(rax, rax);
__ jmp(&done);
diff --git a/src/x64/assembler-x64.h b/src/x64/assembler-x64.h
index fde88df7..7bcc7c56 100644
--- a/src/x64/assembler-x64.h
+++ b/src/x64/assembler-x64.h
@@ -536,6 +536,8 @@ class Assembler : public Malloced {
// The debug break slot must be able to contain a call instruction.
static const int kDebugBreakSlotLength = kCallInstructionLength;
+ // One byte opcode for test eax,0xXXXXXXXX.
+ static const byte kTestEaxByte = 0xA9;
// ---------------------------------------------------------------------------
// Code generation
diff --git a/src/x64/builtins-x64.cc b/src/x64/builtins-x64.cc
index 456d0765..d738261a 100644
--- a/src/x64/builtins-x64.cc
+++ b/src/x64/builtins-x64.cc
@@ -422,7 +422,7 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
// [rsp+0x20] : argv
// Clear the context before we push it when entering the JS frame.
- __ xor_(rsi, rsi);
+ __ Set(rsi, 0);
__ EnterInternalFrame();
// Load the function context into rsi.
@@ -451,7 +451,7 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
// rdi : function
// Clear the context before we push it when entering the JS frame.
- __ xor_(rsi, rsi);
+ __ Set(rsi, 0);
// Enter an internal frame.
__ EnterInternalFrame();
@@ -479,7 +479,7 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
// Register rbx points to array of pointers to handle locations.
// Push the values of these handles.
Label loop, entry;
- __ xor_(rcx, rcx); // Set loop variable to 0.
+ __ Set(rcx, 0); // Set loop variable to 0.
__ jmp(&entry);
__ bind(&loop);
__ movq(kScratchRegister, Operand(rbx, rcx, times_pointer_size, 0));
@@ -668,7 +668,7 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
// become the receiver.
__ bind(&non_function);
__ movq(Operand(rsp, rax, times_pointer_size, 0), rdi);
- __ xor_(rdi, rdi);
+ __ Set(rdi, 0);
// 4. Shift arguments and return address one slot down on the stack
// (overwriting the original receiver). Adjust argument count to make
@@ -689,7 +689,7 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
{ Label function;
__ testq(rdi, rdi);
__ j(not_zero, &function);
- __ xor_(rbx, rbx);
+ __ Set(rbx, 0);
__ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION);
__ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)),
RelocInfo::CODE_TARGET);
diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc
index c3eb5bf4..60ec35d0 100644
--- a/src/x64/code-stubs-x64.cc
+++ b/src/x64/code-stubs-x64.cc
@@ -104,7 +104,7 @@ void FastNewContextStub::Generate(MacroAssembler* masm) {
__ Move(FieldOperand(rax, FixedArray::kLengthOffset), Smi::FromInt(length));
// Setup the fixed slots.
- __ xor_(rbx, rbx); // Set to NULL.
+ __ Set(rbx, 0); // Set to NULL.
__ movq(Operand(rax, Context::SlotOffset(Context::CLOSURE_INDEX)), rcx);
__ movq(Operand(rax, Context::SlotOffset(Context::FCONTEXT_INDEX)), rax);
__ movq(Operand(rax, Context::SlotOffset(Context::PREVIOUS_INDEX)), rbx);
@@ -250,7 +250,7 @@ void ToBooleanStub::Generate(MacroAssembler* masm) {
__ movq(rax, Immediate(1));
__ ret(1 * kPointerSize);
__ bind(&false_result);
- __ xor_(rax, rax);
+ __ Set(rax, 0);
__ ret(1 * kPointerSize);
}
@@ -2572,7 +2572,7 @@ void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) {
// Before returning we restore the context from the frame pointer if not NULL.
// The frame pointer is NULL in the exception handler of a JS entry frame.
- __ xor_(rsi, rsi); // tentatively set context pointer to NULL
+ __ Set(rsi, 0); // Tentatively set context pointer to NULL
NearLabel skip;
__ cmpq(rbp, Immediate(0));
__ j(equal, &skip);
@@ -2756,7 +2756,7 @@ void CEntryStub::GenerateThrowUncatchable(MacroAssembler* masm,
}
// Clear the context pointer.
- __ xor_(rsi, rsi);
+ __ Set(rsi, 0);
// Restore registers from handler.
STATIC_ASSERT(StackHandlerConstants::kNextOffset + kPointerSize ==
diff --git a/src/x64/code-stubs-x64.h b/src/x64/code-stubs-x64.h
index eb7ad267..0fe4f8ad 100644
--- a/src/x64/code-stubs-x64.h
+++ b/src/x64/code-stubs-x64.h
@@ -87,7 +87,7 @@ class GenericBinaryOpStub: public CodeStub {
ASSERT(OpBits::is_valid(Token::NUM_TOKENS));
}
- GenericBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info)
+ GenericBinaryOpStub(int key, BinaryOpIC::TypeInfo runtime_operands_type)
: op_(OpBits::decode(key)),
mode_(ModeBits::decode(key)),
flags_(FlagBits::decode(key)),
@@ -95,7 +95,7 @@ class GenericBinaryOpStub: public CodeStub {
args_reversed_(ArgsReversedBits::decode(key)),
static_operands_type_(TypeInfo::ExpandedRepresentation(
StaticTypeInfoBits::decode(key))),
- runtime_operands_type_(type_info),
+ runtime_operands_type_(runtime_operands_type),
name_(NULL) {
}
@@ -348,42 +348,6 @@ class NumberToStringStub: public CodeStub {
};
-class RecordWriteStub : public CodeStub {
- public:
- RecordWriteStub(Register object, Register addr, Register scratch)
- : object_(object), addr_(addr), scratch_(scratch) { }
-
- void Generate(MacroAssembler* masm);
-
- private:
- Register object_;
- Register addr_;
- Register scratch_;
-
-#ifdef DEBUG
- void Print() {
- PrintF("RecordWriteStub (object reg %d), (addr reg %d), (scratch reg %d)\n",
- object_.code(), addr_.code(), scratch_.code());
- }
-#endif
-
- // Minor key encoding in 12 bits. 4 bits for each of the three
- // registers (object, address and scratch) OOOOAAAASSSS.
- class ScratchBits : public BitField<uint32_t, 0, 4> {};
- class AddressBits : public BitField<uint32_t, 4, 4> {};
- class ObjectBits : public BitField<uint32_t, 8, 4> {};
-
- Major MajorKey() { return RecordWrite; }
-
- int MinorKey() {
- // Encode the registers.
- return ObjectBits::encode(object_.code()) |
- AddressBits::encode(addr_.code()) |
- ScratchBits::encode(scratch_.code());
- }
-};
-
-
} } // namespace v8::internal
#endif // V8_X64_CODE_STUBS_X64_H_
diff --git a/src/x64/codegen-x64.cc b/src/x64/codegen-x64.cc
index 9a255722..aa5d3357 100644
--- a/src/x64/codegen-x64.cc
+++ b/src/x64/codegen-x64.cc
@@ -6813,12 +6813,8 @@ void CodeGenerator::GenerateSwapElements(ZoneList<Expression*>* args) {
// (or them and test against Smi mask.)
__ movq(tmp2.reg(), tmp1.reg());
- RecordWriteStub recordWrite1(tmp2.reg(), index1.reg(), object.reg());
- __ CallStub(&recordWrite1);
-
- RecordWriteStub recordWrite2(tmp1.reg(), index2.reg(), object.reg());
- __ CallStub(&recordWrite2);
-
+ __ RecordWriteHelper(tmp1.reg(), index1.reg(), object.reg());
+ __ RecordWriteHelper(tmp2.reg(), index2.reg(), object.reg());
__ bind(&done);
deferred->BindExit();
@@ -8812,11 +8808,6 @@ ModuloFunction CreateModuloFunction() {
#undef __
-void RecordWriteStub::Generate(MacroAssembler* masm) {
- masm->RecordWriteHelper(object_, addr_, scratch_);
- masm->ret(0);
-}
-
} } // namespace v8::internal
#endif // V8_TARGET_ARCH_X64
diff --git a/src/x64/debug-x64.cc b/src/x64/debug-x64.cc
index 2c1056f5..4218647f 100644
--- a/src/x64/debug-x64.cc
+++ b/src/x64/debug-x64.cc
@@ -25,7 +25,6 @@
// (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"
#if defined(V8_TARGET_ARCH_X64)
@@ -39,13 +38,61 @@ namespace internal {
#ifdef ENABLE_DEBUGGER_SUPPORT
+bool BreakLocationIterator::IsDebugBreakAtReturn() {
+ return Debug::IsDebugBreakAtReturn(rinfo());
+}
+
+
+// Patch the JS frame exit code with a debug break call. See
+// CodeGenerator::VisitReturnStatement and VirtualFrame::Exit in codegen-x64.cc
+// for the precise return instructions sequence.
+void BreakLocationIterator::SetDebugBreakAtReturn() {
+ ASSERT(Assembler::kJSReturnSequenceLength >=
+ Assembler::kCallInstructionLength);
+ rinfo()->PatchCodeWithCall(Debug::debug_break_return()->entry(),
+ Assembler::kJSReturnSequenceLength - Assembler::kCallInstructionLength);
+}
+
+
+// Restore the JS frame exit code.
+void BreakLocationIterator::ClearDebugBreakAtReturn() {
+ rinfo()->PatchCode(original_rinfo()->pc(),
+ Assembler::kJSReturnSequenceLength);
+}
+
+
+// A debug break in the frame exit code is identified by the JS frame exit code
+// having been patched with a call instruction.
bool Debug::IsDebugBreakAtReturn(v8::internal::RelocInfo* rinfo) {
ASSERT(RelocInfo::IsJSReturn(rinfo->rmode()));
return rinfo->IsPatchedReturnSequence();
}
+
+bool BreakLocationIterator::IsDebugBreakAtSlot() {
+ ASSERT(IsDebugBreakSlot());
+ // Check whether the debug break slot instructions have been patched.
+ return !Assembler::IsNop(rinfo()->pc());
+}
+
+
+void BreakLocationIterator::SetDebugBreakAtSlot() {
+ ASSERT(IsDebugBreakSlot());
+ rinfo()->PatchCodeWithCall(
+ Debug::debug_break_slot()->entry(),
+ Assembler::kDebugBreakSlotLength - Assembler::kCallInstructionLength);
+}
+
+
+void BreakLocationIterator::ClearDebugBreakAtSlot() {
+ ASSERT(IsDebugBreakSlot());
+ rinfo()->PatchCode(original_rinfo()->pc(), Assembler::kDebugBreakSlotLength);
+}
+
+
#define __ ACCESS_MASM(masm)
+
static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
RegList object_regs,
RegList non_object_regs,
@@ -55,7 +102,7 @@ static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
// Store the registers containing live values on the expression stack to
// make sure that these are correctly updated during GC. Non object values
- // are stored as as two smi causing it to be untouched by GC.
+ // are stored as as two smis causing it to be untouched by GC.
ASSERT((object_regs & ~kJSCallerSaved) == 0);
ASSERT((non_object_regs & ~kJSCallerSaved) == 0);
ASSERT((object_regs & non_object_regs) == 0);
@@ -80,7 +127,7 @@ static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
#ifdef DEBUG
__ RecordComment("// Calling from debug break to runtime - come in - over");
#endif
- __ xor_(rax, rax); // No arguments (argc == 0).
+ __ Set(rax, 0); // No arguments (argc == 0).
__ movq(rbx, ExternalReference::debug_break());
CEntryStub ceb(1);
@@ -126,24 +173,25 @@ static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
}
-void Debug::GenerateCallICDebugBreak(MacroAssembler* masm) {
- // Register state for IC call call (from ic-x64.cc)
+void Debug::GenerateLoadICDebugBreak(MacroAssembler* masm) {
+ // Register state for IC load call (from ic-x64.cc).
// ----------- S t a t e -------------
- // -- rcx: function name
+ // -- rax : receiver
+ // -- rcx : name
// -----------------------------------
- Generate_DebugBreakCallHelper(masm, rcx.bit(), 0, false);
+ Generate_DebugBreakCallHelper(masm, rax.bit() | rcx.bit(), 0, false);
}
-void Debug::GenerateConstructCallDebugBreak(MacroAssembler* masm) {
- // Register state just before return from JS function (from codegen-x64.cc).
- // rax is the actual number of arguments not encoded as a smi, see comment
- // above IC call.
+void Debug::GenerateStoreICDebugBreak(MacroAssembler* masm) {
+ // Register state for IC store call (from ic-x64.cc).
// ----------- S t a t e -------------
- // -- rax: number of arguments
+ // -- rax : value
+ // -- rcx : name
+ // -- rdx : receiver
// -----------------------------------
- // The number of arguments in rax is not smi encoded.
- Generate_DebugBreakCallHelper(masm, rdi.bit(), rax.bit(), false);
+ Generate_DebugBreakCallHelper(
+ masm, rax.bit() | rcx.bit() | rdx.bit(), 0, false);
}
@@ -169,34 +217,33 @@ void Debug::GenerateKeyedStoreICDebugBreak(MacroAssembler* masm) {
}
-void Debug::GenerateLoadICDebugBreak(MacroAssembler* masm) {
- // Register state for IC load call (from ic-x64.cc).
+void Debug::GenerateCallICDebugBreak(MacroAssembler* masm) {
+ // Register state for IC call call (from ic-x64.cc)
// ----------- S t a t e -------------
- // -- rax : receiver
- // -- rcx : name
+ // -- rcx: function name
// -----------------------------------
- Generate_DebugBreakCallHelper(masm, rax.bit() | rcx.bit(), 0, false);
+ Generate_DebugBreakCallHelper(masm, rcx.bit(), 0, false);
}
-void Debug::GenerateReturnDebugBreak(MacroAssembler* masm) {
+void Debug::GenerateConstructCallDebugBreak(MacroAssembler* masm) {
// Register state just before return from JS function (from codegen-x64.cc).
+ // rax is the actual number of arguments not encoded as a smi, see comment
+ // above IC call.
// ----------- S t a t e -------------
- // -- rax: return value
+ // -- rax: number of arguments
// -----------------------------------
- Generate_DebugBreakCallHelper(masm, rax.bit(), 0, true);
+ // The number of arguments in rax is not smi encoded.
+ Generate_DebugBreakCallHelper(masm, rdi.bit(), rax.bit(), false);
}
-void Debug::GenerateStoreICDebugBreak(MacroAssembler* masm) {
- // Register state for IC store call (from ic-x64.cc).
+void Debug::GenerateReturnDebugBreak(MacroAssembler* masm) {
+ // Register state just before return from JS function (from codegen-x64.cc).
// ----------- S t a t e -------------
- // -- rax : value
- // -- rcx : name
- // -- rdx : receiver
+ // -- rax: return value
// -----------------------------------
- Generate_DebugBreakCallHelper(
- masm, rax.bit() | rcx.bit() | rdx.bit(), 0, false);
+ Generate_DebugBreakCallHelper(masm, rax.bit(), 0, true);
}
@@ -262,49 +309,6 @@ const bool Debug::kFrameDropperSupported = true;
#undef __
-
-
-
-void BreakLocationIterator::ClearDebugBreakAtReturn() {
- rinfo()->PatchCode(original_rinfo()->pc(),
- Assembler::kJSReturnSequenceLength);
-}
-
-
-bool BreakLocationIterator::IsDebugBreakAtReturn() {
- return Debug::IsDebugBreakAtReturn(rinfo());
-}
-
-
-void BreakLocationIterator::SetDebugBreakAtReturn() {
- ASSERT(Assembler::kJSReturnSequenceLength >=
- Assembler::kCallInstructionLength);
- rinfo()->PatchCodeWithCall(Debug::debug_break_return()->entry(),
- Assembler::kJSReturnSequenceLength - Assembler::kCallInstructionLength);
-}
-
-
-bool BreakLocationIterator::IsDebugBreakAtSlot() {
- ASSERT(IsDebugBreakSlot());
- // Check whether the debug break slot instructions have been patched.
- return !Assembler::IsNop(rinfo()->pc());
-}
-
-
-void BreakLocationIterator::SetDebugBreakAtSlot() {
- ASSERT(IsDebugBreakSlot());
- rinfo()->PatchCodeWithCall(
- Debug::debug_break_slot()->entry(),
- Assembler::kDebugBreakSlotLength - Assembler::kCallInstructionLength);
-}
-
-
-void BreakLocationIterator::ClearDebugBreakAtSlot() {
- ASSERT(IsDebugBreakSlot());
- rinfo()->PatchCode(original_rinfo()->pc(), Assembler::kDebugBreakSlotLength);
-}
-
-
#endif // ENABLE_DEBUGGER_SUPPORT
} } // namespace v8::internal
diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc
index dd28d4d8..66bc4ede 100644
--- a/src/x64/full-codegen-x64.cc
+++ b/src/x64/full-codegen-x64.cc
@@ -199,7 +199,7 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
void FullCodeGenerator::ClearAccumulator() {
- __ xor_(rax, rax);
+ __ Set(rax, 0);
}
diff --git a/src/x64/ic-x64.cc b/src/x64/ic-x64.cc
index aff778a5..29cbed05 100644
--- a/src/x64/ic-x64.cc
+++ b/src/x64/ic-x64.cc
@@ -378,81 +378,50 @@ static void GenerateNumberDictionaryLoad(MacroAssembler* masm,
}
-// One byte opcode for test rax,0xXXXXXXXX.
-static const byte kTestEaxByte = 0xA9;
-
-
-static bool PatchInlinedMapCheck(Address address, Object* map) {
- if (V8::UseCrankshaft()) return false;
-
- // Arguments are address of start of call sequence that called
- // the IC,
- Address test_instruction_address =
- address + Assembler::kCallTargetAddressOffset;
- // The keyed load has a fast inlined case if the IC call instruction
- // is immediately followed by a test instruction.
- if (*test_instruction_address != kTestEaxByte) return false;
-
- // Fetch the offset from the test instruction to the map compare
- // instructions (starting with the 64-bit immediate mov of the map
- // address). This offset is stored in the last 4 bytes of the 5
- // byte test instruction.
- Address delta_address = test_instruction_address + 1;
- int delta = *reinterpret_cast<int*>(delta_address);
- // Compute the map address. The map address is in the last 8 bytes
- // of the 10-byte immediate mov instruction (incl. REX prefix), so we add 2
- // to the offset to get the map address.
- Address map_address = test_instruction_address + delta + 2;
- // Patch the map check.
- *(reinterpret_cast<Object**>(map_address)) = map;
- return true;
-}
-
+// The offset from the inlined patch site to the start of the inlined
+// load instruction.
+const int LoadIC::kOffsetToLoadInstruction = 20;
-bool KeyedLoadIC::PatchInlinedLoad(Address address, Object* map) {
- return PatchInlinedMapCheck(address, map);
-}
+void LoadIC::GenerateArrayLength(MacroAssembler* masm) {
+ // ----------- S t a t e -------------
+ // -- rax : receiver
+ // -- rcx : name
+ // -- rsp[0] : return address
+ // -----------------------------------
+ Label miss;
-bool KeyedStoreIC::PatchInlinedStore(Address address, Object* map) {
- return PatchInlinedMapCheck(address, map);
+ StubCompiler::GenerateLoadArrayLength(masm, rax, rdx, &miss);
+ __ bind(&miss);
+ StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
}
-void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
+void LoadIC::GenerateStringLength(MacroAssembler* masm) {
// ----------- S t a t e -------------
- // -- rax : key
- // -- rdx : receiver
- // -- rsp[0] : return address
+ // -- rax : receiver
+ // -- rcx : name
+ // -- rsp[0] : return address
// -----------------------------------
+ Label miss;
- __ IncrementCounter(&Counters::keyed_load_miss, 1);
-
- __ pop(rbx);
- __ push(rdx); // receiver
- __ push(rax); // name
- __ push(rbx); // return address
-
- // Perform tail call to the entry.
- ExternalReference ref = ExternalReference(IC_Utility(kKeyedLoadIC_Miss));
- __ TailCallExternalReference(ref, 2, 1);
+ StubCompiler::GenerateLoadStringLength(masm, rax, rdx, rbx, &miss);
+ __ bind(&miss);
+ StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
}
-void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
+void LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) {
// ----------- S t a t e -------------
- // -- rax : key
- // -- rdx : receiver
- // -- rsp[0] : return address
+ // -- rax : receiver
+ // -- rcx : name
+ // -- rsp[0] : return address
// -----------------------------------
+ Label miss;
- __ pop(rbx);
- __ push(rdx); // receiver
- __ push(rax); // name
- __ push(rbx); // return address
-
- // Perform tail call to the entry.
- __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
+ StubCompiler::GenerateLoadFunctionPrototype(masm, rax, rdx, rbx, &miss);
+ __ bind(&miss);
+ StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
}
@@ -923,45 +892,6 @@ void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) {
}
-void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) {
- // ----------- S t a t e -------------
- // -- rax : value
- // -- rcx : key
- // -- rdx : receiver
- // -- rsp[0] : return address
- // -----------------------------------
-
- __ pop(rbx);
- __ push(rdx); // receiver
- __ push(rcx); // key
- __ push(rax); // value
- __ push(rbx); // return address
-
- // Do tail-call to runtime routine.
- ExternalReference ref = ExternalReference(IC_Utility(kKeyedStoreIC_Miss));
- __ TailCallExternalReference(ref, 3, 1);
-}
-
-
-void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm) {
- // ----------- S t a t e -------------
- // -- rax : value
- // -- rcx : key
- // -- rdx : receiver
- // -- rsp[0] : return address
- // -----------------------------------
-
- __ pop(rbx);
- __ push(rdx); // receiver
- __ push(rcx); // key
- __ push(rax); // value
- __ push(rbx); // return address
-
- // Do tail-call to runtime routine.
- __ TailCallRuntime(Runtime::kSetProperty, 3, 1);
-}
-
-
void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- rax : value
@@ -1236,71 +1166,6 @@ void KeyedStoreIC::GenerateExternalArray(MacroAssembler* masm,
}
-// Defined in ic.cc.
-Object* CallIC_Miss(Arguments args);
-
-
-static void GenerateCallMiss(MacroAssembler* masm, int argc, IC::UtilityId id) {
- // ----------- S t a t e -------------
- // rcx : function name
- // rsp[0] : return address
- // rsp[8] : argument argc
- // rsp[16] : argument argc - 1
- // ...
- // rsp[argc * 8] : argument 1
- // rsp[(argc + 1) * 8] : argument 0 = receiver
- // -----------------------------------
-
- if (id == IC::kCallIC_Miss) {
- __ IncrementCounter(&Counters::call_miss, 1);
- } else {
- __ IncrementCounter(&Counters::keyed_call_miss, 1);
- }
-
- // Get the receiver of the function from the stack; 1 ~ return address.
- __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
-
- // Enter an internal frame.
- __ EnterInternalFrame();
-
- // Push the receiver and the name of the function.
- __ push(rdx);
- __ push(rcx);
-
- // Call the entry.
- CEntryStub stub(1);
- __ movq(rax, Immediate(2));
- __ movq(rbx, ExternalReference(IC_Utility(id)));
- __ CallStub(&stub);
-
- // Move result to rdi and exit the internal frame.
- __ movq(rdi, rax);
- __ LeaveInternalFrame();
-
- // Check if the receiver is a global object of some sort.
- // This can happen only for regular CallIC but not KeyedCallIC.
- if (id == IC::kCallIC_Miss) {
- Label invoke, global;
- __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); // receiver
- __ JumpIfSmi(rdx, &invoke);
- __ CmpObjectType(rdx, JS_GLOBAL_OBJECT_TYPE, rcx);
- __ j(equal, &global);
- __ CmpInstanceType(rcx, JS_BUILTINS_OBJECT_TYPE);
- __ j(not_equal, &invoke);
-
- // Patch the receiver on the stack.
- __ bind(&global);
- __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
- __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx);
- __ bind(&invoke);
- }
-
- // Invoke the function.
- ParameterCount actual(argc);
- __ InvokeFunction(rdi, actual, JUMP_FUNCTION);
-}
-
-
// The generated code does not accept smi keys.
// The generated code falls through if both probes miss.
static void GenerateMonomorphicCacheProbe(MacroAssembler* masm,
@@ -1409,7 +1274,7 @@ static void GenerateCallNormal(MacroAssembler* masm, int argc) {
}
-void CallIC::GenerateMiss(MacroAssembler* masm, int argc) {
+static void GenerateCallMiss(MacroAssembler* masm, int argc, IC::UtilityId id) {
// ----------- S t a t e -------------
// rcx : function name
// rsp[0] : return address
@@ -1419,7 +1284,54 @@ void CallIC::GenerateMiss(MacroAssembler* masm, int argc) {
// rsp[argc * 8] : argument 1
// rsp[(argc + 1) * 8] : argument 0 = receiver
// -----------------------------------
- GenerateCallMiss(masm, argc, IC::kCallIC_Miss);
+
+ if (id == IC::kCallIC_Miss) {
+ __ IncrementCounter(&Counters::call_miss, 1);
+ } else {
+ __ IncrementCounter(&Counters::keyed_call_miss, 1);
+ }
+
+ // Get the receiver of the function from the stack; 1 ~ return address.
+ __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
+
+ // Enter an internal frame.
+ __ EnterInternalFrame();
+
+ // Push the receiver and the name of the function.
+ __ push(rdx);
+ __ push(rcx);
+
+ // Call the entry.
+ CEntryStub stub(1);
+ __ movq(rax, Immediate(2));
+ __ movq(rbx, ExternalReference(IC_Utility(id)));
+ __ CallStub(&stub);
+
+ // Move result to rdi and exit the internal frame.
+ __ movq(rdi, rax);
+ __ LeaveInternalFrame();
+
+ // Check if the receiver is a global object of some sort.
+ // This can happen only for regular CallIC but not KeyedCallIC.
+ if (id == IC::kCallIC_Miss) {
+ Label invoke, global;
+ __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); // receiver
+ __ JumpIfSmi(rdx, &invoke);
+ __ CmpObjectType(rdx, JS_GLOBAL_OBJECT_TYPE, rcx);
+ __ j(equal, &global);
+ __ CmpInstanceType(rcx, JS_BUILTINS_OBJECT_TYPE);
+ __ j(not_equal, &invoke);
+
+ // Patch the receiver on the stack.
+ __ bind(&global);
+ __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
+ __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx);
+ __ bind(&invoke);
+ }
+
+ // Invoke the function.
+ ParameterCount actual(argc);
+ __ InvokeFunction(rdi, actual, JUMP_FUNCTION);
}
@@ -1457,7 +1369,7 @@ void CallIC::GenerateNormal(MacroAssembler* masm, int argc) {
}
-void KeyedCallIC::GenerateMiss(MacroAssembler* masm, int argc) {
+void CallIC::GenerateMiss(MacroAssembler* masm, int argc) {
// ----------- S t a t e -------------
// rcx : function name
// rsp[0] : return address
@@ -1468,7 +1380,7 @@ void KeyedCallIC::GenerateMiss(MacroAssembler* masm, int argc) {
// rsp[(argc + 1) * 8] : argument 0 = receiver
// -----------------------------------
- GenerateCallMiss(masm, argc, IC::kKeyedCallIC_Miss);
+ GenerateCallMiss(masm, argc, IC::kCallIC_Miss);
}
@@ -1594,56 +1506,18 @@ void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) {
}
-// The offset from the inlined patch site to the start of the inlined
-// load instruction.
-const int LoadIC::kOffsetToLoadInstruction = 20;
-
-
-void LoadIC::GenerateMiss(MacroAssembler* masm) {
- // ----------- S t a t e -------------
- // -- rax : receiver
- // -- rcx : name
- // -- rsp[0] : return address
- // -----------------------------------
-
- __ IncrementCounter(&Counters::load_miss, 1);
-
- __ pop(rbx);
- __ push(rax); // receiver
- __ push(rcx); // name
- __ push(rbx); // return address
-
- // Perform tail call to the entry.
- ExternalReference ref = ExternalReference(IC_Utility(kLoadIC_Miss));
- __ TailCallExternalReference(ref, 2, 1);
-}
-
-
-void LoadIC::GenerateArrayLength(MacroAssembler* masm) {
- // ----------- S t a t e -------------
- // -- rax : receiver
- // -- rcx : name
- // -- rsp[0] : return address
- // -----------------------------------
- Label miss;
-
- StubCompiler::GenerateLoadArrayLength(masm, rax, rdx, &miss);
- __ bind(&miss);
- StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
-}
-
-
-void LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) {
+void KeyedCallIC::GenerateMiss(MacroAssembler* masm, int argc) {
// ----------- S t a t e -------------
- // -- rax : receiver
- // -- rcx : name
- // -- rsp[0] : return address
+ // rcx : function name
+ // rsp[0] : return address
+ // rsp[8] : argument argc
+ // rsp[16] : argument argc - 1
+ // ...
+ // rsp[argc * 8] : argument 1
+ // rsp[(argc + 1) * 8] : argument 0 = receiver
// -----------------------------------
- Label miss;
- StubCompiler::GenerateLoadFunctionPrototype(masm, rax, rdx, rbx, &miss);
- __ bind(&miss);
- StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
+ GenerateCallMiss(masm, argc, IC::kKeyedCallIC_Miss);
}
@@ -1686,17 +1560,23 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
}
-void LoadIC::GenerateStringLength(MacroAssembler* masm) {
+void LoadIC::GenerateMiss(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- rax : receiver
// -- rcx : name
// -- rsp[0] : return address
// -----------------------------------
- Label miss;
- StubCompiler::GenerateLoadStringLength(masm, rax, rdx, rbx, &miss);
- __ bind(&miss);
- StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
+ __ IncrementCounter(&Counters::load_miss, 1);
+
+ __ pop(rbx);
+ __ push(rax); // receiver
+ __ push(rcx); // name
+ __ push(rbx); // return address
+
+ // Perform tail call to the entry.
+ ExternalReference ref = ExternalReference(IC_Utility(kLoadIC_Miss));
+ __ TailCallExternalReference(ref, 2, 1);
}
@@ -1708,7 +1588,7 @@ bool LoadIC::PatchInlinedLoad(Address address, Object* map, int offset) {
address + Assembler::kCallTargetAddressOffset;
// If the instruction following the call is not a test rax, nothing
// was inlined.
- if (*test_instruction_address != kTestEaxByte) return false;
+ if (*test_instruction_address != Assembler::kTestEaxByte) return false;
Address delta_address = test_instruction_address + 1;
// The delta to the start of the map check instruction.
@@ -1739,11 +1619,6 @@ bool LoadIC::PatchInlinedContextualLoad(Address address,
}
-// The offset from the inlined patch site to the start of the inlined
-// store instruction.
-const int StoreIC::kOffsetToStoreInstruction = 20;
-
-
bool StoreIC::PatchInlinedStore(Address address, Object* map, int offset) {
if (V8::UseCrankshaft()) return false;
@@ -1753,7 +1628,7 @@ bool StoreIC::PatchInlinedStore(Address address, Object* map, int offset) {
// If the instruction following the call is not a test rax, nothing
// was inlined.
- if (*test_instruction_address != kTestEaxByte) return false;
+ if (*test_instruction_address != Assembler::kTestEaxByte) return false;
// Extract the encoded deltas from the test rax instruction.
Address encoded_offsets_address = test_instruction_address + 1;
@@ -1792,23 +1667,77 @@ bool StoreIC::PatchInlinedStore(Address address, Object* map, int offset) {
}
-void StoreIC::GenerateMiss(MacroAssembler* masm) {
+static bool PatchInlinedMapCheck(Address address, Object* map) {
+ if (V8::UseCrankshaft()) return false;
+
+ // Arguments are address of start of call sequence that called
+ // the IC,
+ Address test_instruction_address =
+ address + Assembler::kCallTargetAddressOffset;
+ // The keyed load has a fast inlined case if the IC call instruction
+ // is immediately followed by a test instruction.
+ if (*test_instruction_address != Assembler::kTestEaxByte) return false;
+
+ // Fetch the offset from the test instruction to the map compare
+ // instructions (starting with the 64-bit immediate mov of the map
+ // address). This offset is stored in the last 4 bytes of the 5
+ // byte test instruction.
+ Address delta_address = test_instruction_address + 1;
+ int delta = *reinterpret_cast<int*>(delta_address);
+ // Compute the map address. The map address is in the last 8 bytes
+ // of the 10-byte immediate mov instruction (incl. REX prefix), so we add 2
+ // to the offset to get the map address.
+ Address map_address = test_instruction_address + delta + 2;
+ // Patch the map check.
+ *(reinterpret_cast<Object**>(map_address)) = map;
+ return true;
+}
+
+
+bool KeyedLoadIC::PatchInlinedLoad(Address address, Object* map) {
+ return PatchInlinedMapCheck(address, map);
+}
+
+
+bool KeyedStoreIC::PatchInlinedStore(Address address, Object* map) {
+ return PatchInlinedMapCheck(address, map);
+}
+
+
+void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
// ----------- S t a t e -------------
- // -- rax : value
- // -- rcx : name
+ // -- rax : key
// -- rdx : receiver
- // -- rsp[0] : return address
+ // -- rsp[0] : return address
// -----------------------------------
+ __ IncrementCounter(&Counters::keyed_load_miss, 1);
+
__ pop(rbx);
__ push(rdx); // receiver
- __ push(rcx); // name
- __ push(rax); // value
+ __ push(rax); // name
__ push(rbx); // return address
// Perform tail call to the entry.
- ExternalReference ref = ExternalReference(IC_Utility(kStoreIC_Miss));
- __ TailCallExternalReference(ref, 3, 1);
+ ExternalReference ref = ExternalReference(IC_Utility(kKeyedLoadIC_Miss));
+ __ TailCallExternalReference(ref, 2, 1);
+}
+
+
+void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
+ // ----------- S t a t e -------------
+ // -- rax : key
+ // -- rdx : receiver
+ // -- rsp[0] : return address
+ // -----------------------------------
+
+ __ pop(rbx);
+ __ push(rdx); // receiver
+ __ push(rax); // name
+ __ push(rbx); // return address
+
+ // Perform tail call to the entry.
+ __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
}
@@ -1831,6 +1760,31 @@ void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
}
+void StoreIC::GenerateMiss(MacroAssembler* masm) {
+ // ----------- S t a t e -------------
+ // -- rax : value
+ // -- rcx : name
+ // -- rdx : receiver
+ // -- rsp[0] : return address
+ // -----------------------------------
+
+ __ pop(rbx);
+ __ push(rdx); // receiver
+ __ push(rcx); // name
+ __ push(rax); // value
+ __ push(rbx); // return address
+
+ // Perform tail call to the entry.
+ ExternalReference ref = ExternalReference(IC_Utility(kStoreIC_Miss));
+ __ TailCallExternalReference(ref, 3, 1);
+}
+
+
+// The offset from the inlined patch site to the start of the inlined
+// store instruction.
+const int StoreIC::kOffsetToStoreInstruction = 20;
+
+
void StoreIC::GenerateArrayLength(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- rax : value
@@ -1923,6 +1877,45 @@ void StoreIC::GenerateGlobalProxy(MacroAssembler* masm) {
}
+void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm) {
+ // ----------- S t a t e -------------
+ // -- rax : value
+ // -- rcx : key
+ // -- rdx : receiver
+ // -- rsp[0] : return address
+ // -----------------------------------
+
+ __ pop(rbx);
+ __ push(rdx); // receiver
+ __ push(rcx); // key
+ __ push(rax); // value
+ __ push(rbx); // return address
+
+ // Do tail-call to runtime routine.
+ __ TailCallRuntime(Runtime::kSetProperty, 3, 1);
+}
+
+
+void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) {
+ // ----------- S t a t e -------------
+ // -- rax : value
+ // -- rcx : key
+ // -- rdx : receiver
+ // -- rsp[0] : return address
+ // -----------------------------------
+
+ __ pop(rbx);
+ __ push(rdx); // receiver
+ __ push(rcx); // key
+ __ push(rax); // value
+ __ push(rbx); // return address
+
+ // Do tail-call to runtime routine.
+ ExternalReference ref = ExternalReference(IC_Utility(kKeyedStoreIC_Miss));
+ __ TailCallExternalReference(ref, 3, 1);
+}
+
+
#undef __
@@ -1976,6 +1969,7 @@ void PatchInlinedSmiCode(Address address) {
UNIMPLEMENTED();
}
+
} } // namespace v8::internal
#endif // V8_TARGET_ARCH_X64
diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc
index 1df9b475..70a3dab6 100644
--- a/src/x64/macro-assembler-x64.cc
+++ b/src/x64/macro-assembler-x64.cc
@@ -1110,7 +1110,7 @@ void MacroAssembler::SmiAnd(Register dst, Register src1, Register src2) {
void MacroAssembler::SmiAndConstant(Register dst, Register src, Smi* constant) {
if (constant->value() == 0) {
- xor_(dst, dst);
+ Set(dst, 0);
} else if (dst.is(src)) {
ASSERT(!dst.is(kScratchRegister));
Register constant_reg = GetSmiConstant(constant);
@@ -1605,7 +1605,7 @@ void MacroAssembler::DecrementCounter(StatsCounter* counter, int value) {
#ifdef ENABLE_DEBUGGER_SUPPORT
void MacroAssembler::DebugBreak() {
ASSERT(allow_stub_calls());
- xor_(rax, rax); // no arguments
+ Set(rax, 0); // No arguments.
movq(rbx, ExternalReference(Runtime::kDebugBreak));
CEntryStub ces(1);
Call(ces.GetCode(), RelocInfo::DEBUG_BREAK);
diff --git a/src/x64/macro-assembler-x64.h b/src/x64/macro-assembler-x64.h
index d8f2fba4..30b9ba51 100644
--- a/src/x64/macro-assembler-x64.h
+++ b/src/x64/macro-assembler-x64.h
@@ -1176,7 +1176,7 @@ void MacroAssembler::SmiMul(Register dst,
jmp(on_not_smi_result);
bind(&zero_correct_result);
- xor_(dst, dst);
+ Set(dst, 0);
bind(&correct_result);
} else {
diff --git a/src/x64/regexp-macro-assembler-x64.cc b/src/x64/regexp-macro-assembler-x64.cc
index 2cf85f11..27f3482a 100644
--- a/src/x64/regexp-macro-assembler-x64.cc
+++ b/src/x64/regexp-macro-assembler-x64.cc
@@ -223,9 +223,7 @@ void RegExpMacroAssemblerX64::CheckCharacters(Vector<const uc16> str,
// If input is ASCII, don't even bother calling here if the string to
// match contains a non-ascii character.
if (mode_ == ASCII) {
- for (int i = 0; i < str.length(); i++) {
- ASSERT(str[i] <= String::kMaxAsciiCharCodeU);
- }
+ ASSERT(String::IsAscii(str.start(), str.length()));
}
#endif
int byte_length = str.length() * char_size();
@@ -690,7 +688,7 @@ bool RegExpMacroAssemblerX64::CheckSpecialCharacterClass(uc16 type,
void RegExpMacroAssemblerX64::Fail() {
ASSERT(FAILURE == 0); // Return value for failure is zero.
- __ xor_(rax, rax); // zero rax.
+ __ Set(rax, 0);
__ jmp(&exit_label_);
}
diff --git a/src/x64/stub-cache-x64.cc b/src/x64/stub-cache-x64.cc
index 63e97695..57cba142 100644
--- a/src/x64/stub-cache-x64.cc
+++ b/src/x64/stub-cache-x64.cc
@@ -25,23 +25,17 @@
// (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"
#if defined(V8_TARGET_ARCH_X64)
#include "ic-inl.h"
-#include "code-stubs.h"
#include "codegen-inl.h"
#include "stub-cache.h"
-#include "macro-assembler.h"
namespace v8 {
namespace internal {
-//-----------------------------------------------------------------------------
-// StubCompiler static helper functions
-
#define __ ACCESS_MASM(masm)
@@ -182,92 +176,6 @@ static void GenerateDictionaryNegativeLookup(MacroAssembler* masm,
}
-void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
- ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC);
- Code* code = NULL;
- if (kind == Code::LOAD_IC) {
- code = Builtins::builtin(Builtins::LoadIC_Miss);
- } else {
- code = Builtins::builtin(Builtins::KeyedLoadIC_Miss);
- }
-
- Handle<Code> ic(code);
- __ Jump(ic, RelocInfo::CODE_TARGET);
-}
-
-
-void StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
- int index,
- Register prototype) {
- // Load the global or builtins object from the current context.
- __ movq(prototype,
- Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX)));
- // Load the global context from the global or builtins object.
- __ movq(prototype,
- FieldOperand(prototype, GlobalObject::kGlobalContextOffset));
- // Load the function from the global context.
- __ movq(prototype, Operand(prototype, Context::SlotOffset(index)));
- // Load the initial map. The global functions all have initial maps.
- __ movq(prototype,
- FieldOperand(prototype, JSFunction::kPrototypeOrInitialMapOffset));
- // Load the prototype from the initial map.
- __ movq(prototype, FieldOperand(prototype, Map::kPrototypeOffset));
-}
-
-
-void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype(
- MacroAssembler* masm, int index, Register prototype, Label* miss) {
- // Check we're still in the same context.
- __ Move(prototype, Top::global());
- __ cmpq(Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX)),
- prototype);
- __ j(not_equal, miss);
- // Get the global function with the given index.
- JSFunction* function = JSFunction::cast(Top::global_context()->get(index));
- // Load its initial map. The global functions all have initial maps.
- __ Move(prototype, Handle<Map>(function->initial_map()));
- // Load the prototype from the initial map.
- __ movq(prototype, FieldOperand(prototype, Map::kPrototypeOffset));
-}
-
-
-// Load a fast property out of a holder object (src). In-object properties
-// are loaded directly otherwise the property is loaded from the properties
-// fixed array.
-void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
- Register dst, Register src,
- JSObject* holder, int index) {
- // Adjust for the number of properties stored in the holder.
- index -= holder->map()->inobject_properties();
- if (index < 0) {
- // Get the property straight out of the holder.
- int offset = holder->map()->instance_size() + (index * kPointerSize);
- __ movq(dst, FieldOperand(src, offset));
- } else {
- // Calculate the offset into the properties array.
- int offset = index * kPointerSize + FixedArray::kHeaderSize;
- __ movq(dst, FieldOperand(src, JSObject::kPropertiesOffset));
- __ movq(dst, FieldOperand(dst, offset));
- }
-}
-
-
-static void PushInterceptorArguments(MacroAssembler* masm,
- Register receiver,
- Register holder,
- Register name,
- JSObject* holder_obj) {
- __ push(name);
- InterceptorInfo* interceptor = holder_obj->GetNamedInterceptor();
- ASSERT(!Heap::InNewSpace(interceptor));
- __ Move(kScratchRegister, Handle<Object>(interceptor));
- __ push(kScratchRegister);
- __ push(receiver);
- __ push(holder);
- __ push(FieldOperand(kScratchRegister, InterceptorInfo::kDataOffset));
-}
-
-
void StubCache::GenerateProbe(MacroAssembler* masm,
Code::Flags flags,
Register receiver,
@@ -324,83 +232,38 @@ void StubCache::GenerateProbe(MacroAssembler* masm,
}
-// Both name_reg and receiver_reg are preserved on jumps to miss_label,
-// but may be destroyed if store is successful.
-void StubCompiler::GenerateStoreField(MacroAssembler* masm,
- JSObject* object,
- int index,
- Map* transition,
- Register receiver_reg,
- Register name_reg,
- Register scratch,
- Label* miss_label) {
- // Check that the object isn't a smi.
- __ JumpIfSmi(receiver_reg, miss_label);
-
- // Check that the map of the object hasn't changed.
- __ Cmp(FieldOperand(receiver_reg, HeapObject::kMapOffset),
- Handle<Map>(object->map()));
- __ j(not_equal, miss_label);
-
- // Perform global security token check if needed.
- if (object->IsJSGlobalProxy()) {
- __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label);
- }
-
- // Stub never generated for non-global objects that require access
- // checks.
- ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
-
- // Perform map transition for the receiver if necessary.
- if ((transition != NULL) && (object->map()->unused_property_fields() == 0)) {
- // The properties must be extended before we can store the value.
- // We jump to a runtime call that extends the properties array.
- __ pop(scratch); // Return address.
- __ push(receiver_reg);
- __ Push(Handle<Map>(transition));
- __ push(rax);
- __ push(scratch);
- __ TailCallExternalReference(
- ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage)), 3, 1);
- return;
- }
-
- if (transition != NULL) {
- // Update the map of the object; no write barrier updating is
- // needed because the map is never in new space.
- __ Move(FieldOperand(receiver_reg, HeapObject::kMapOffset),
- Handle<Map>(transition));
- }
-
- // Adjust for the number of properties stored in the object. Even in the
- // face of a transition we can use the old map here because the size of the
- // object and the number of in-object properties is not going to change.
- index -= object->map()->inobject_properties();
-
- if (index < 0) {
- // Set the property straight into the object.
- int offset = object->map()->instance_size() + (index * kPointerSize);
- __ movq(FieldOperand(receiver_reg, offset), rax);
-
- // Update the write barrier for the array address.
- // Pass the value being stored in the now unused name_reg.
- __ movq(name_reg, rax);
- __ RecordWrite(receiver_reg, offset, name_reg, scratch);
- } else {
- // Write to the properties array.
- int offset = index * kPointerSize + FixedArray::kHeaderSize;
- // Get the properties array (optimistically).
- __ movq(scratch, FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
- __ movq(FieldOperand(scratch, offset), rax);
+void StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
+ int index,
+ Register prototype) {
+ // Load the global or builtins object from the current context.
+ __ movq(prototype,
+ Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX)));
+ // Load the global context from the global or builtins object.
+ __ movq(prototype,
+ FieldOperand(prototype, GlobalObject::kGlobalContextOffset));
+ // Load the function from the global context.
+ __ movq(prototype, Operand(prototype, Context::SlotOffset(index)));
+ // Load the initial map. The global functions all have initial maps.
+ __ movq(prototype,
+ FieldOperand(prototype, JSFunction::kPrototypeOrInitialMapOffset));
+ // Load the prototype from the initial map.
+ __ movq(prototype, FieldOperand(prototype, Map::kPrototypeOffset));
+}
- // Update the write barrier for the array address.
- // Pass the value being stored in the now unused name_reg.
- __ movq(name_reg, rax);
- __ RecordWrite(scratch, offset, name_reg, receiver_reg);
- }
- // Return the value (register rax).
- __ ret(0);
+void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype(
+ MacroAssembler* masm, int index, Register prototype, Label* miss) {
+ // Check we're still in the same context.
+ __ Move(prototype, Top::global());
+ __ cmpq(Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX)),
+ prototype);
+ __ j(not_equal, miss);
+ // Get the global function with the given index.
+ JSFunction* function = JSFunction::cast(Top::global_context()->get(index));
+ // Load its initial map. The global functions all have initial maps.
+ __ Move(prototype, Handle<Map>(function->initial_map()));
+ // Load the prototype from the initial map.
+ __ movq(prototype, FieldOperand(prototype, Map::kPrototypeOffset));
}
@@ -469,6 +332,54 @@ void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm,
}
+void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm,
+ Register receiver,
+ Register result,
+ Register scratch,
+ Label* miss_label) {
+ __ TryGetFunctionPrototype(receiver, result, miss_label);
+ if (!result.is(rax)) __ movq(rax, result);
+ __ ret(0);
+}
+
+
+// Load a fast property out of a holder object (src). In-object properties
+// are loaded directly otherwise the property is loaded from the properties
+// fixed array.
+void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
+ Register dst, Register src,
+ JSObject* holder, int index) {
+ // Adjust for the number of properties stored in the holder.
+ index -= holder->map()->inobject_properties();
+ if (index < 0) {
+ // Get the property straight out of the holder.
+ int offset = holder->map()->instance_size() + (index * kPointerSize);
+ __ movq(dst, FieldOperand(src, offset));
+ } else {
+ // Calculate the offset into the properties array.
+ int offset = index * kPointerSize + FixedArray::kHeaderSize;
+ __ movq(dst, FieldOperand(src, JSObject::kPropertiesOffset));
+ __ movq(dst, FieldOperand(dst, offset));
+ }
+}
+
+
+static void PushInterceptorArguments(MacroAssembler* masm,
+ Register receiver,
+ Register holder,
+ Register name,
+ JSObject* holder_obj) {
+ __ push(name);
+ InterceptorInfo* interceptor = holder_obj->GetNamedInterceptor();
+ ASSERT(!Heap::InNewSpace(interceptor));
+ __ Move(kScratchRegister, Handle<Object>(interceptor));
+ __ push(kScratchRegister);
+ __ push(receiver);
+ __ push(holder);
+ __ push(FieldOperand(kScratchRegister, InterceptorInfo::kDataOffset));
+}
+
+
static void CompileCallLoadPropertyWithInterceptor(MacroAssembler* masm,
Register receiver,
Register holder,
@@ -486,20 +397,10 @@ static void CompileCallLoadPropertyWithInterceptor(MacroAssembler* masm,
}
-
-void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm,
- Register receiver,
- Register result,
- Register scratch,
- Label* miss_label) {
- __ TryGetFunctionPrototype(receiver, result, miss_label);
- if (!result.is(rax)) __ movq(rax, result);
- __ ret(0);
-}
-
// Number of pointers to be reserved on stack for fast API call.
static const int kFastApiCallArguments = 3;
+
// Reserves space for the extra arguments to API function in the
// caller's frame.
//
@@ -553,7 +454,6 @@ static bool GenerateFastApiCall(MacroAssembler* masm,
// -- rsp[(argc + 3) * 8] : first argument
// -- rsp[(argc + 4) * 8] : receiver
// -----------------------------------
-
// Get the function and setup the context.
JSFunction* function = optimization.constant_function();
__ Move(rdi, Handle<JSFunction>(function));
@@ -833,6 +733,100 @@ class CallInterceptorCompiler BASE_EMBEDDED {
};
+void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
+ ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC);
+ Code* code = NULL;
+ if (kind == Code::LOAD_IC) {
+ code = Builtins::builtin(Builtins::LoadIC_Miss);
+ } else {
+ code = Builtins::builtin(Builtins::KeyedLoadIC_Miss);
+ }
+
+ Handle<Code> ic(code);
+ __ Jump(ic, RelocInfo::CODE_TARGET);
+}
+
+
+// Both name_reg and receiver_reg are preserved on jumps to miss_label,
+// but may be destroyed if store is successful.
+void StubCompiler::GenerateStoreField(MacroAssembler* masm,
+ JSObject* object,
+ int index,
+ Map* transition,
+ Register receiver_reg,
+ Register name_reg,
+ Register scratch,
+ Label* miss_label) {
+ // Check that the object isn't a smi.
+ __ JumpIfSmi(receiver_reg, miss_label);
+
+ // Check that the map of the object hasn't changed.
+ __ Cmp(FieldOperand(receiver_reg, HeapObject::kMapOffset),
+ Handle<Map>(object->map()));
+ __ j(not_equal, miss_label);
+
+ // Perform global security token check if needed.
+ if (object->IsJSGlobalProxy()) {
+ __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label);
+ }
+
+ // Stub never generated for non-global objects that require access
+ // checks.
+ ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
+
+ // Perform map transition for the receiver if necessary.
+ if ((transition != NULL) && (object->map()->unused_property_fields() == 0)) {
+ // The properties must be extended before we can store the value.
+ // We jump to a runtime call that extends the properties array.
+ __ pop(scratch); // Return address.
+ __ push(receiver_reg);
+ __ Push(Handle<Map>(transition));
+ __ push(rax);
+ __ push(scratch);
+ __ TailCallExternalReference(
+ ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage)), 3, 1);
+ return;
+ }
+
+ if (transition != NULL) {
+ // Update the map of the object; no write barrier updating is
+ // needed because the map is never in new space.
+ __ Move(FieldOperand(receiver_reg, HeapObject::kMapOffset),
+ Handle<Map>(transition));
+ }
+
+ // Adjust for the number of properties stored in the object. Even in the
+ // face of a transition we can use the old map here because the size of the
+ // object and the number of in-object properties is not going to change.
+ index -= object->map()->inobject_properties();
+
+ if (index < 0) {
+ // Set the property straight into the object.
+ int offset = object->map()->instance_size() + (index * kPointerSize);
+ __ movq(FieldOperand(receiver_reg, offset), rax);
+
+ // Update the write barrier for the array address.
+ // Pass the value being stored in the now unused name_reg.
+ __ movq(name_reg, rax);
+ __ RecordWrite(receiver_reg, offset, name_reg, scratch);
+ } else {
+ // Write to the properties array.
+ int offset = index * kPointerSize + FixedArray::kHeaderSize;
+ // Get the properties array (optimistically).
+ __ movq(scratch, FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
+ __ movq(FieldOperand(scratch, offset), rax);
+
+ // Update the write barrier for the array address.
+ // Pass the value being stored in the now unused name_reg.
+ __ movq(name_reg, rax);
+ __ RecordWrite(scratch, offset, name_reg, receiver_reg);
+ }
+
+ // Return the value (register rax).
+ __ ret(0);
+}
+
+
// Generate code to check that a global property cell is empty. Create
// the property cell at compilation time if no cell exists for the
// property.
@@ -857,10 +851,420 @@ MUST_USE_RESULT static MaybeObject* GenerateCheckPropertyCell(
#undef __
-
#define __ ACCESS_MASM((masm()))
+Register StubCompiler::CheckPrototypes(JSObject* object,
+ Register object_reg,
+ JSObject* holder,
+ Register holder_reg,
+ Register scratch1,
+ Register scratch2,
+ String* name,
+ int save_at_depth,
+ Label* miss) {
+ // Make sure there's no overlap between holder and object registers.
+ ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg));
+ ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg)
+ && !scratch2.is(scratch1));
+
+ // Keep track of the current object in register reg. On the first
+ // iteration, reg is an alias for object_reg, on later iterations,
+ // it is an alias for holder_reg.
+ Register reg = object_reg;
+ int depth = 0;
+
+ if (save_at_depth == depth) {
+ __ movq(Operand(rsp, kPointerSize), object_reg);
+ }
+
+ // Check the maps in the prototype chain.
+ // Traverse the prototype chain from the object and do map checks.
+ JSObject* current = object;
+ while (current != holder) {
+ depth++;
+
+ // Only global objects and objects that do not require access
+ // checks are allowed in stubs.
+ ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded());
+
+ JSObject* prototype = JSObject::cast(current->GetPrototype());
+ if (!current->HasFastProperties() &&
+ !current->IsJSGlobalObject() &&
+ !current->IsJSGlobalProxy()) {
+ if (!name->IsSymbol()) {
+ MaybeObject* lookup_result = Heap::LookupSymbol(name);
+ if (lookup_result->IsFailure()) {
+ set_failure(Failure::cast(lookup_result));
+ return reg;
+ } else {
+ name = String::cast(lookup_result->ToObjectUnchecked());
+ }
+ }
+ ASSERT(current->property_dictionary()->FindEntry(name) ==
+ StringDictionary::kNotFound);
+
+ GenerateDictionaryNegativeLookup(masm(),
+ miss,
+ reg,
+ name,
+ scratch1,
+ scratch2);
+ __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
+ reg = holder_reg; // from now the object is in holder_reg
+ __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
+ } else if (Heap::InNewSpace(prototype)) {
+ // Get the map of the current object.
+ __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
+ __ Cmp(scratch1, Handle<Map>(current->map()));
+ // Branch on the result of the map check.
+ __ j(not_equal, miss);
+ // Check access rights to the global object. This has to happen
+ // after the map check so that we know that the object is
+ // actually a global object.
+ if (current->IsJSGlobalProxy()) {
+ __ CheckAccessGlobalProxy(reg, scratch1, miss);
+
+ // Restore scratch register to be the map of the object.
+ // We load the prototype from the map in the scratch register.
+ __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
+ }
+ // The prototype is in new space; we cannot store a reference
+ // to it in the code. Load it from the map.
+ reg = holder_reg; // from now the object is in holder_reg
+ __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
+
+ } else {
+ // Check the map of the current object.
+ __ Cmp(FieldOperand(reg, HeapObject::kMapOffset),
+ Handle<Map>(current->map()));
+ // Branch on the result of the map check.
+ __ j(not_equal, miss);
+ // Check access rights to the global object. This has to happen
+ // after the map check so that we know that the object is
+ // actually a global object.
+ if (current->IsJSGlobalProxy()) {
+ __ CheckAccessGlobalProxy(reg, scratch1, miss);
+ }
+ // The prototype is in old space; load it directly.
+ reg = holder_reg; // from now the object is in holder_reg
+ __ Move(reg, Handle<JSObject>(prototype));
+ }
+
+ if (save_at_depth == depth) {
+ __ movq(Operand(rsp, kPointerSize), reg);
+ }
+
+ // Go to the next object in the prototype chain.
+ current = prototype;
+ }
+
+ // Check the holder map.
+ __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), Handle<Map>(holder->map()));
+ __ j(not_equal, miss);
+
+ // Log the check depth.
+ LOG(IntEvent("check-maps-depth", depth + 1));
+
+ // Perform security check for access to the global object and return
+ // the holder register.
+ ASSERT(current == holder);
+ ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded());
+ if (current->IsJSGlobalProxy()) {
+ __ CheckAccessGlobalProxy(reg, scratch1, miss);
+ }
+
+ // If we've skipped any global objects, it's not enough to verify
+ // that their maps haven't changed. We also need to check that the
+ // property cell for the property is still empty.
+ current = object;
+ while (current != holder) {
+ if (current->IsGlobalObject()) {
+ MaybeObject* cell = GenerateCheckPropertyCell(masm(),
+ GlobalObject::cast(current),
+ name,
+ scratch1,
+ miss);
+ if (cell->IsFailure()) {
+ set_failure(Failure::cast(cell));
+ return reg;
+ }
+ }
+ current = JSObject::cast(current->GetPrototype());
+ }
+
+ // Return the register containing the holder.
+ return reg;
+}
+
+
+void StubCompiler::GenerateLoadField(JSObject* object,
+ JSObject* holder,
+ Register receiver,
+ Register scratch1,
+ Register scratch2,
+ Register scratch3,
+ int index,
+ String* name,
+ Label* miss) {
+ // Check that the receiver isn't a smi.
+ __ JumpIfSmi(receiver, miss);
+
+ // Check the prototype chain.
+ Register reg =
+ CheckPrototypes(object, receiver, holder,
+ scratch1, scratch2, scratch3, name, miss);
+
+ // Get the value from the properties.
+ GenerateFastPropertyLoad(masm(), rax, reg, holder, index);
+ __ ret(0);
+}
+
+
+bool StubCompiler::GenerateLoadCallback(JSObject* object,
+ JSObject* holder,
+ Register receiver,
+ Register name_reg,
+ Register scratch1,
+ Register scratch2,
+ Register scratch3,
+ AccessorInfo* callback,
+ String* name,
+ Label* miss,
+ Failure** failure) {
+ // Check that the receiver isn't a smi.
+ __ JumpIfSmi(receiver, miss);
+
+ // Check that the maps haven't changed.
+ Register reg =
+ CheckPrototypes(object, receiver, holder, scratch1,
+ scratch2, scratch3, name, miss);
+
+ Handle<AccessorInfo> callback_handle(callback);
+
+ // Insert additional parameters into the stack frame above return address.
+ ASSERT(!scratch2.is(reg));
+ __ pop(scratch2); // Get return address to place it below.
+
+ __ push(receiver); // receiver
+ __ push(reg); // holder
+ if (Heap::InNewSpace(callback_handle->data())) {
+ __ Move(scratch1, callback_handle);
+ __ push(FieldOperand(scratch1, AccessorInfo::kDataOffset)); // data
+ } else {
+ __ Push(Handle<Object>(callback_handle->data()));
+ }
+ __ 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.
+
+#ifdef _WIN64
+ // Win64 uses first register--rcx--for returned value.
+ Register accessor_info_arg = r8;
+ Register name_arg = rdx;
+#else
+ Register accessor_info_arg = rsi;
+ Register name_arg = rdi;
+#endif
+
+ ASSERT(!name_arg.is(scratch2));
+ __ movq(name_arg, rsp);
+ __ push(scratch2); // Restore return address.
+
+ // Do call through the api.
+ Address getter_address = v8::ToCData<Address>(callback->getter());
+ ApiFunction fun(getter_address);
+
+ // 3 elements array for v8::Agruments::values_ and handler for name.
+ const int kStackSpace = 4;
+
+ // Allocate v8::AccessorInfo in non-GCed stack space.
+ const int kArgStackSpace = 1;
+
+ __ PrepareCallApiFunction(kArgStackSpace);
+ __ lea(rax, Operand(name_arg, 3 * kPointerSize));
+
+ // v8::AccessorInfo::args_.
+ __ movq(StackSpaceOperand(0), rax);
+
+ // The context register (rsi) has been saved in PrepareCallApiFunction and
+ // could be used to pass arguments.
+ __ lea(accessor_info_arg, StackSpaceOperand(0));
+
+ // 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()->TryCallApiFunctionAndReturn(&fun, kStackSpace);
+ if (result->IsFailure()) {
+ *failure = Failure::cast(result);
+ return false;
+ }
+ return true;
+}
+
+
+void StubCompiler::GenerateLoadConstant(JSObject* object,
+ JSObject* holder,
+ Register receiver,
+ Register scratch1,
+ Register scratch2,
+ Register scratch3,
+ Object* value,
+ String* name,
+ Label* miss) {
+ // Check that the receiver isn't a smi.
+ __ JumpIfSmi(receiver, miss);
+
+ // Check that the maps haven't changed.
+ Register reg =
+ CheckPrototypes(object, receiver, holder,
+ scratch1, scratch2, scratch3, name, miss);
+
+ // Return the constant value.
+ __ Move(rax, Handle<Object>(value));
+ __ ret(0);
+}
+
+
+void StubCompiler::GenerateLoadInterceptor(JSObject* object,
+ JSObject* interceptor_holder,
+ LookupResult* lookup,
+ Register receiver,
+ Register name_reg,
+ Register scratch1,
+ Register scratch2,
+ Register scratch3,
+ String* name,
+ Label* miss) {
+ ASSERT(interceptor_holder->HasNamedInterceptor());
+ ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined());
+
+ // Check that the receiver isn't a smi.
+ __ JumpIfSmi(receiver, miss);
+
+ // So far the most popular follow ups for interceptor loads are FIELD
+ // and CALLBACKS, so inline only them, other cases may be added
+ // later.
+ bool compile_followup_inline = false;
+ if (lookup->IsProperty() && lookup->IsCacheable()) {
+ if (lookup->type() == FIELD) {
+ compile_followup_inline = true;
+ } else if (lookup->type() == CALLBACKS &&
+ lookup->GetCallbackObject()->IsAccessorInfo() &&
+ AccessorInfo::cast(lookup->GetCallbackObject())->getter() != NULL) {
+ compile_followup_inline = true;
+ }
+ }
+
+ if (compile_followup_inline) {
+ // Compile the interceptor call, followed by inline code to load the
+ // property from further up the prototype chain if the call fails.
+ // Check that the maps haven't changed.
+ Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder,
+ scratch1, scratch2, scratch3,
+ name, miss);
+ ASSERT(holder_reg.is(receiver) || holder_reg.is(scratch1));
+
+ // Save necessary data before invoking an interceptor.
+ // Requires a frame to make GC aware of pushed pointers.
+ __ EnterInternalFrame();
+
+ if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) {
+ // CALLBACKS case needs a receiver to be passed into C++ callback.
+ __ push(receiver);
+ }
+ __ push(holder_reg);
+ __ push(name_reg);
+
+ // Invoke an interceptor. Note: map checks from receiver to
+ // interceptor's holder has been compiled before (see a caller
+ // of this method.)
+ CompileCallLoadPropertyWithInterceptor(masm(),
+ receiver,
+ holder_reg,
+ name_reg,
+ interceptor_holder);
+
+ // Check if interceptor provided a value for property. If it's
+ // the case, return immediately.
+ Label interceptor_failed;
+ __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex);
+ __ j(equal, &interceptor_failed);
+ __ LeaveInternalFrame();
+ __ ret(0);
+
+ __ bind(&interceptor_failed);
+ __ pop(name_reg);
+ __ pop(holder_reg);
+ if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) {
+ __ pop(receiver);
+ }
+
+ __ LeaveInternalFrame();
+
+ // Check that the maps from interceptor's holder to lookup's holder
+ // haven't changed. And load lookup's holder into |holder| register.
+ if (interceptor_holder != lookup->holder()) {
+ holder_reg = CheckPrototypes(interceptor_holder,
+ holder_reg,
+ lookup->holder(),
+ scratch1,
+ scratch2,
+ scratch3,
+ name,
+ miss);
+ }
+
+ if (lookup->type() == FIELD) {
+ // We found FIELD property in prototype chain of interceptor's holder.
+ // Retrieve a field from field's holder.
+ GenerateFastPropertyLoad(masm(), rax, holder_reg,
+ lookup->holder(), lookup->GetFieldIndex());
+ __ ret(0);
+ } else {
+ // We found CALLBACKS property in prototype chain of interceptor's
+ // holder.
+ ASSERT(lookup->type() == CALLBACKS);
+ ASSERT(lookup->GetCallbackObject()->IsAccessorInfo());
+ AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject());
+ ASSERT(callback != NULL);
+ ASSERT(callback->getter() != NULL);
+
+ // Tail call to runtime.
+ // Important invariant in CALLBACKS case: the code above must be
+ // structured to never clobber |receiver| register.
+ __ pop(scratch2); // return address
+ __ push(receiver);
+ __ push(holder_reg);
+ __ Move(holder_reg, Handle<AccessorInfo>(callback));
+ __ push(FieldOperand(holder_reg, AccessorInfo::kDataOffset));
+ __ push(holder_reg);
+ __ push(name_reg);
+ __ push(scratch2); // restore return address
+
+ ExternalReference ref =
+ ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
+ __ TailCallExternalReference(ref, 5, 1);
+ }
+ } else { // !compile_followup_inline
+ // Call the runtime system to load the interceptor.
+ // Check that the maps haven't changed.
+ Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder,
+ scratch1, scratch2, scratch3,
+ name, miss);
+ __ pop(scratch2); // save old return address
+ PushInterceptorArguments(masm(), receiver, holder_reg,
+ name_reg, interceptor_holder);
+ __ push(scratch2); // restore old return address
+
+ ExternalReference ref = ExternalReference(
+ IC_Utility(IC::kLoadPropertyWithInterceptorForLoad));
+ __ TailCallExternalReference(ref, 5, 1);
+ }
+}
+
+
void CallStubCompiler::GenerateNameCheck(String* name, Label* miss) {
if (kind_ == Code::KEYED_CALL_IC) {
__ Cmp(rcx, Handle<String>(name));
@@ -932,177 +1336,6 @@ MaybeObject* CallStubCompiler::GenerateMissBranch() {
}
-MaybeObject* CallStubCompiler::CompileCallConstant(Object* object,
- JSObject* holder,
- JSFunction* function,
- String* name,
- CheckType check) {
- // ----------- S t a t e -------------
- // rcx : function name
- // rsp[0] : return address
- // rsp[8] : argument argc
- // rsp[16] : argument argc - 1
- // ...
- // rsp[argc * 8] : argument 1
- // rsp[(argc + 1) * 8] : argument 0 = receiver
- // -----------------------------------
-
- SharedFunctionInfo* function_info = function->shared();
- if (function_info->HasBuiltinFunctionId()) {
- BuiltinFunctionId id = function_info->builtin_function_id();
- MaybeObject* maybe_result = CompileCustomCall(
- id, object, holder, NULL, function, name);
- Object* result;
- if (!maybe_result->ToObject(&result)) return maybe_result;
- // undefined means bail out to regular compiler.
- if (!result->IsUndefined()) return result;
- }
-
- Label miss_in_smi_check;
-
- GenerateNameCheck(name, &miss_in_smi_check);
-
- // Get the receiver from the stack.
- const int argc = arguments().immediate();
- __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
-
- // Check that the receiver isn't a smi.
- if (check != NUMBER_CHECK) {
- __ JumpIfSmi(rdx, &miss_in_smi_check);
- }
-
- // Make sure that it's okay not to patch the on stack receiver
- // unless we're doing a receiver map check.
- ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
-
- CallOptimization optimization(function);
- int depth = kInvalidProtoDepth;
- Label miss;
-
- switch (check) {
- case RECEIVER_MAP_CHECK:
- __ IncrementCounter(&Counters::call_const, 1);
-
- if (optimization.is_simple_api_call() && !object->IsGlobalObject()) {
- depth = optimization.GetPrototypeDepthOfExpectedType(
- JSObject::cast(object), holder);
- }
-
- if (depth != kInvalidProtoDepth) {
- __ IncrementCounter(&Counters::call_const_fast_api, 1);
- // Allocate space for v8::Arguments implicit values. Must be initialized
- // before to call any runtime function.
- __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize));
- }
-
- // Check that the maps haven't changed.
- CheckPrototypes(JSObject::cast(object), rdx, holder,
- rbx, rax, rdi, name, depth, &miss);
-
- // Patch the receiver on the stack with the global proxy if
- // necessary.
- if (object->IsGlobalObject()) {
- ASSERT(depth == kInvalidProtoDepth);
- __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
- __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx);
- }
- break;
-
- case STRING_CHECK:
- if (!function->IsBuiltin()) {
- // Calling non-builtins with a value as receiver requires boxing.
- __ jmp(&miss);
- } else {
- // Check that the object is a two-byte string or a symbol.
- __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, rax);
- __ j(above_equal, &miss);
- // Check that the maps starting from the prototype haven't changed.
- GenerateDirectLoadGlobalFunctionPrototype(
- masm(), Context::STRING_FUNCTION_INDEX, rax, &miss);
- CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder,
- rbx, rdx, rdi, name, &miss);
- }
- break;
-
- case NUMBER_CHECK: {
- if (!function->IsBuiltin()) {
- // Calling non-builtins with a value as receiver requires boxing.
- __ jmp(&miss);
- } else {
- Label fast;
- // Check that the object is a smi or a heap number.
- __ JumpIfSmi(rdx, &fast);
- __ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rax);
- __ j(not_equal, &miss);
- __ bind(&fast);
- // Check that the maps starting from the prototype haven't changed.
- GenerateDirectLoadGlobalFunctionPrototype(
- masm(), Context::NUMBER_FUNCTION_INDEX, rax, &miss);
- CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder,
- rbx, rdx, rdi, name, &miss);
- }
- break;
- }
-
- case BOOLEAN_CHECK: {
- if (!function->IsBuiltin()) {
- // Calling non-builtins with a value as receiver requires boxing.
- __ jmp(&miss);
- } else {
- Label fast;
- // Check that the object is a boolean.
- __ CompareRoot(rdx, Heap::kTrueValueRootIndex);
- __ j(equal, &fast);
- __ CompareRoot(rdx, Heap::kFalseValueRootIndex);
- __ j(not_equal, &miss);
- __ bind(&fast);
- // Check that the maps starting from the prototype haven't changed.
- GenerateDirectLoadGlobalFunctionPrototype(
- masm(), Context::BOOLEAN_FUNCTION_INDEX, rax, &miss);
- CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder,
- rbx, rdx, rdi, name, &miss);
- }
- break;
- }
-
- default:
- UNREACHABLE();
- }
-
- if (depth != kInvalidProtoDepth) {
- Failure* failure;
- // Move the return address on top of the stack.
- __ movq(rax, Operand(rsp, 3 * kPointerSize));
- __ movq(Operand(rsp, 0 * kPointerSize), rax);
-
- // rsp[2 * kPointerSize] is uninitialized, rsp[3 * kPointerSize] contains
- // duplicate of return address and will be overwritten.
- bool success = GenerateFastApiCall(masm(), optimization, argc, &failure);
- if (!success) {
- return failure;
- }
- } else {
- __ InvokeFunction(function, arguments(), JUMP_FUNCTION);
- }
-
- // Handle call cache miss.
- __ bind(&miss);
- if (depth != kInvalidProtoDepth) {
- __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize));
- }
-
- // Handle call cache miss.
- __ bind(&miss_in_smi_check);
- Object* obj;
- { MaybeObject* maybe_obj = GenerateMissBranch();
- if (!maybe_obj->ToObject(&obj)) return maybe_obj;
- }
-
- // Return the generated code.
- return GetCode(function);
-}
-
-
MaybeObject* CallStubCompiler::CompileCallField(JSObject* object,
JSObject* holder,
int index,
@@ -1248,8 +1481,7 @@ MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object,
__ InNewSpace(rbx, rcx, equal, &exit);
- RecordWriteStub stub(rbx, rdx, rcx);
- __ CallStub(&stub);
+ __ RecordWriteHelper(rbx, rdx, rcx);
__ ret((argc + 1) * kPointerSize);
@@ -1408,7 +1640,7 @@ MaybeObject* CallStubCompiler::CompileArrayPopCall(Object* object,
}
-MaybeObject* CallStubCompiler::CompileStringCharAtCall(
+MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall(
Object* object,
JSObject* holder,
JSGlobalPropertyCell* cell,
@@ -1441,10 +1673,9 @@ MaybeObject* CallStubCompiler::CompileStringCharAtCall(
CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder,
rbx, rdx, rdi, name, &miss);
- Register receiver = rax;
+ Register receiver = rbx;
Register index = rdi;
- Register scratch1 = rbx;
- Register scratch2 = rdx;
+ Register scratch = rdx;
Register result = rax;
__ movq(receiver, Operand(rsp, (argc + 1) * kPointerSize));
if (argc > 0) {
@@ -1453,23 +1684,22 @@ MaybeObject* CallStubCompiler::CompileStringCharAtCall(
__ LoadRoot(index, Heap::kUndefinedValueRootIndex);
}
- StringCharAtGenerator char_at_generator(receiver,
- index,
- scratch1,
- scratch2,
- result,
- &miss, // When not a string.
- &miss, // When not a number.
- &index_out_of_range,
- STRING_INDEX_IS_NUMBER);
- char_at_generator.GenerateFast(masm());
+ StringCharCodeAtGenerator char_code_at_generator(receiver,
+ index,
+ scratch,
+ result,
+ &miss, // When not a string.
+ &miss, // When not a number.
+ &index_out_of_range,
+ STRING_INDEX_IS_NUMBER);
+ char_code_at_generator.GenerateFast(masm());
__ ret((argc + 1) * kPointerSize);
StubRuntimeCallHelper call_helper;
- char_at_generator.GenerateSlow(masm(), call_helper);
+ char_code_at_generator.GenerateSlow(masm(), call_helper);
__ bind(&index_out_of_range);
- __ LoadRoot(rax, Heap::kEmptyStringRootIndex);
+ __ LoadRoot(rax, Heap::kNanValueRootIndex);
__ ret((argc + 1) * kPointerSize);
__ bind(&miss);
@@ -1483,7 +1713,7 @@ MaybeObject* CallStubCompiler::CompileStringCharAtCall(
}
-MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall(
+MaybeObject* CallStubCompiler::CompileStringCharAtCall(
Object* object,
JSObject* holder,
JSGlobalPropertyCell* cell,
@@ -1504,6 +1734,7 @@ MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall(
Label miss;
Label index_out_of_range;
+
GenerateNameCheck(name, &miss);
// Check that the maps starting from the prototype haven't changed.
@@ -1515,9 +1746,10 @@ MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall(
CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder,
rbx, rdx, rdi, name, &miss);
- Register receiver = rbx;
+ Register receiver = rax;
Register index = rdi;
- Register scratch = rdx;
+ Register scratch1 = rbx;
+ Register scratch2 = rdx;
Register result = rax;
__ movq(receiver, Operand(rsp, (argc + 1) * kPointerSize));
if (argc > 0) {
@@ -1526,22 +1758,23 @@ MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall(
__ LoadRoot(index, Heap::kUndefinedValueRootIndex);
}
- StringCharCodeAtGenerator char_code_at_generator(receiver,
- index,
- scratch,
- result,
- &miss, // When not a string.
- &miss, // When not a number.
- &index_out_of_range,
- STRING_INDEX_IS_NUMBER);
- char_code_at_generator.GenerateFast(masm());
+ StringCharAtGenerator char_at_generator(receiver,
+ index,
+ scratch1,
+ scratch2,
+ result,
+ &miss, // When not a string.
+ &miss, // When not a number.
+ &index_out_of_range,
+ STRING_INDEX_IS_NUMBER);
+ char_at_generator.GenerateFast(masm());
__ ret((argc + 1) * kPointerSize);
StubRuntimeCallHelper call_helper;
- char_code_at_generator.GenerateSlow(masm(), call_helper);
+ char_at_generator.GenerateSlow(masm(), call_helper);
__ bind(&index_out_of_range);
- __ LoadRoot(rax, Heap::kNanValueRootIndex);
+ __ LoadRoot(rax, Heap::kEmptyStringRootIndex);
__ ret((argc + 1) * kPointerSize);
__ bind(&miss);
@@ -1741,6 +1974,178 @@ MaybeObject* CallStubCompiler::CompileMathAbsCall(Object* object,
}
+MaybeObject* CallStubCompiler::CompileCallConstant(Object* object,
+ JSObject* holder,
+ JSFunction* function,
+ String* name,
+ CheckType check) {
+ // ----------- S t a t e -------------
+ // rcx : function name
+ // rsp[0] : return address
+ // rsp[8] : argument argc
+ // rsp[16] : argument argc - 1
+ // ...
+ // rsp[argc * 8] : argument 1
+ // rsp[(argc + 1) * 8] : argument 0 = receiver
+ // -----------------------------------
+
+ SharedFunctionInfo* function_info = function->shared();
+ if (function_info->HasBuiltinFunctionId()) {
+ BuiltinFunctionId id = function_info->builtin_function_id();
+ MaybeObject* maybe_result = CompileCustomCall(
+ id, object, holder, NULL, function, name);
+ Object* result;
+ if (!maybe_result->ToObject(&result)) return maybe_result;
+ // undefined means bail out to regular compiler.
+ if (!result->IsUndefined()) return result;
+ }
+
+ Label miss_in_smi_check;
+
+ GenerateNameCheck(name, &miss_in_smi_check);
+
+ // Get the receiver from the stack.
+ const int argc = arguments().immediate();
+ __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
+
+ // Check that the receiver isn't a smi.
+ if (check != NUMBER_CHECK) {
+ __ JumpIfSmi(rdx, &miss_in_smi_check);
+ }
+
+ // Make sure that it's okay not to patch the on stack receiver
+ // unless we're doing a receiver map check.
+ ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
+
+ CallOptimization optimization(function);
+ int depth = kInvalidProtoDepth;
+ Label miss;
+
+ switch (check) {
+ case RECEIVER_MAP_CHECK:
+ __ IncrementCounter(&Counters::call_const, 1);
+
+ if (optimization.is_simple_api_call() && !object->IsGlobalObject()) {
+ depth = optimization.GetPrototypeDepthOfExpectedType(
+ JSObject::cast(object), holder);
+ }
+
+ if (depth != kInvalidProtoDepth) {
+ __ IncrementCounter(&Counters::call_const_fast_api, 1);
+
+ // Allocate space for v8::Arguments implicit values. Must be initialized
+ // before to call any runtime function.
+ __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize));
+ }
+
+ // Check that the maps haven't changed.
+ CheckPrototypes(JSObject::cast(object), rdx, holder,
+ rbx, rax, rdi, name, depth, &miss);
+
+ // Patch the receiver on the stack with the global proxy if
+ // necessary.
+ if (object->IsGlobalObject()) {
+ ASSERT(depth == kInvalidProtoDepth);
+ __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
+ __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx);
+ }
+ break;
+
+ case STRING_CHECK:
+ if (!function->IsBuiltin()) {
+ // Calling non-builtins with a value as receiver requires boxing.
+ __ jmp(&miss);
+ } else {
+ // Check that the object is a two-byte string or a symbol.
+ __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, rax);
+ __ j(above_equal, &miss);
+ // Check that the maps starting from the prototype haven't changed.
+ GenerateDirectLoadGlobalFunctionPrototype(
+ masm(), Context::STRING_FUNCTION_INDEX, rax, &miss);
+ CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder,
+ rbx, rdx, rdi, name, &miss);
+ }
+ break;
+
+ case NUMBER_CHECK: {
+ if (!function->IsBuiltin()) {
+ // Calling non-builtins with a value as receiver requires boxing.
+ __ jmp(&miss);
+ } else {
+ Label fast;
+ // Check that the object is a smi or a heap number.
+ __ JumpIfSmi(rdx, &fast);
+ __ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rax);
+ __ j(not_equal, &miss);
+ __ bind(&fast);
+ // Check that the maps starting from the prototype haven't changed.
+ GenerateDirectLoadGlobalFunctionPrototype(
+ masm(), Context::NUMBER_FUNCTION_INDEX, rax, &miss);
+ CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder,
+ rbx, rdx, rdi, name, &miss);
+ }
+ break;
+ }
+
+ case BOOLEAN_CHECK: {
+ if (!function->IsBuiltin()) {
+ // Calling non-builtins with a value as receiver requires boxing.
+ __ jmp(&miss);
+ } else {
+ Label fast;
+ // Check that the object is a boolean.
+ __ CompareRoot(rdx, Heap::kTrueValueRootIndex);
+ __ j(equal, &fast);
+ __ CompareRoot(rdx, Heap::kFalseValueRootIndex);
+ __ j(not_equal, &miss);
+ __ bind(&fast);
+ // Check that the maps starting from the prototype haven't changed.
+ GenerateDirectLoadGlobalFunctionPrototype(
+ masm(), Context::BOOLEAN_FUNCTION_INDEX, rax, &miss);
+ CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder,
+ rbx, rdx, rdi, name, &miss);
+ }
+ break;
+ }
+
+ default:
+ UNREACHABLE();
+ }
+
+ if (depth != kInvalidProtoDepth) {
+ Failure* failure;
+ // Move the return address on top of the stack.
+ __ movq(rax, Operand(rsp, 3 * kPointerSize));
+ __ movq(Operand(rsp, 0 * kPointerSize), rax);
+
+ // rsp[2 * kPointerSize] is uninitialized, rsp[3 * kPointerSize] contains
+ // duplicate of return address and will be overwritten.
+ bool success = GenerateFastApiCall(masm(), optimization, argc, &failure);
+ if (!success) {
+ return failure;
+ }
+ } else {
+ __ InvokeFunction(function, arguments(), JUMP_FUNCTION);
+ }
+
+ // Handle call cache miss.
+ __ bind(&miss);
+ if (depth != kInvalidProtoDepth) {
+ __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize));
+ }
+
+ // Handle call cache miss.
+ __ bind(&miss_in_smi_check);
+ Object* obj;
+ { MaybeObject* maybe_obj = GenerateMissBranch();
+ if (!maybe_obj->ToObject(&obj)) return maybe_obj;
+ }
+
+ // Return the generated code.
+ return GetCode(function);
+}
+
+
MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object,
JSObject* holder,
String* name) {
@@ -1881,50 +2286,260 @@ MaybeObject* CallStubCompiler::CompileCallGlobal(JSObject* object,
}
-MaybeObject* LoadStubCompiler::CompileLoadCallback(String* name,
- JSObject* object,
- JSObject* holder,
- AccessorInfo* callback) {
+MaybeObject* StoreStubCompiler::CompileStoreField(JSObject* object,
+ int index,
+ Map* transition,
+ String* name) {
// ----------- S t a t e -------------
- // -- rax : receiver
+ // -- rax : value
// -- rcx : name
+ // -- rdx : receiver
// -- rsp[0] : return address
// -----------------------------------
Label miss;
- Failure* failure = Failure::InternalError();
- bool success = GenerateLoadCallback(object, holder, rax, rcx, rdx, rbx, rdi,
- callback, name, &miss, &failure);
- if (!success) {
- miss.Unuse();
- return failure;
+ // Generate store field code. Preserves receiver and name on jump to miss.
+ GenerateStoreField(masm(),
+ object,
+ index,
+ transition,
+ rdx, rcx, rbx,
+ &miss);
+
+ // Handle store cache miss.
+ __ bind(&miss);
+ Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
+ __ Jump(ic, RelocInfo::CODE_TARGET);
+
+ // Return the generated code.
+ return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name);
+}
+
+
+MaybeObject* StoreStubCompiler::CompileStoreCallback(JSObject* object,
+ AccessorInfo* callback,
+ String* name) {
+ // ----------- S t a t e -------------
+ // -- rax : value
+ // -- rcx : name
+ // -- rdx : receiver
+ // -- rsp[0] : return address
+ // -----------------------------------
+ Label miss;
+
+ // Check that the object isn't a smi.
+ __ JumpIfSmi(rdx, &miss);
+
+ // Check that the map of the object hasn't changed.
+ __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset),
+ Handle<Map>(object->map()));
+ __ j(not_equal, &miss);
+
+ // Perform global security token check if needed.
+ if (object->IsJSGlobalProxy()) {
+ __ CheckAccessGlobalProxy(rdx, rbx, &miss);
}
+ // Stub never generated for non-global objects that require access
+ // checks.
+ ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
+
+ __ pop(rbx); // remove the return address
+ __ push(rdx); // receiver
+ __ Push(Handle<AccessorInfo>(callback)); // callback info
+ __ push(rcx); // name
+ __ push(rax); // value
+ __ push(rbx); // restore return address
+
+ // Do tail-call to the runtime system.
+ ExternalReference store_callback_property =
+ ExternalReference(IC_Utility(IC::kStoreCallbackProperty));
+ __ TailCallExternalReference(store_callback_property, 4, 1);
+
+ // Handle store cache miss.
__ bind(&miss);
- GenerateLoadMiss(masm(), Code::LOAD_IC);
+ Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
+ __ Jump(ic, RelocInfo::CODE_TARGET);
// Return the generated code.
return GetCode(CALLBACKS, name);
}
-MaybeObject* LoadStubCompiler::CompileLoadConstant(JSObject* object,
- JSObject* holder,
- Object* value,
+MaybeObject* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver,
+ String* name) {
+ // ----------- S t a t e -------------
+ // -- rax : value
+ // -- rcx : name
+ // -- rdx : receiver
+ // -- rsp[0] : return address
+ // -----------------------------------
+ Label miss;
+
+ // Check that the object isn't a smi.
+ __ JumpIfSmi(rdx, &miss);
+
+ // Check that the map of the object hasn't changed.
+ __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset),
+ Handle<Map>(receiver->map()));
+ __ j(not_equal, &miss);
+
+ // Perform global security token check if needed.
+ if (receiver->IsJSGlobalProxy()) {
+ __ CheckAccessGlobalProxy(rdx, rbx, &miss);
+ }
+
+ // Stub never generated for non-global objects that require access
+ // checks.
+ ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded());
+
+ __ pop(rbx); // remove the return address
+ __ push(rdx); // receiver
+ __ push(rcx); // name
+ __ push(rax); // value
+ __ push(rbx); // restore return address
+
+ // Do tail-call to the runtime system.
+ ExternalReference store_ic_property =
+ ExternalReference(IC_Utility(IC::kStoreInterceptorProperty));
+ __ TailCallExternalReference(store_ic_property, 3, 1);
+
+ // Handle store cache miss.
+ __ bind(&miss);
+ Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
+ __ Jump(ic, RelocInfo::CODE_TARGET);
+
+ // Return the generated code.
+ return GetCode(INTERCEPTOR, name);
+}
+
+
+MaybeObject* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object,
+ JSGlobalPropertyCell* cell,
String* name) {
// ----------- S t a t e -------------
- // -- rax : receiver
+ // -- rax : value
// -- rcx : name
+ // -- rdx : receiver
// -- rsp[0] : return address
// -----------------------------------
Label miss;
- GenerateLoadConstant(object, holder, rax, rbx, rdx, rdi, value, name, &miss);
+ // Check that the map of the global has not changed.
+ __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset),
+ Handle<Map>(object->map()));
+ __ j(not_equal, &miss);
+
+ // Store the value in the cell.
+ __ Move(rcx, Handle<JSGlobalPropertyCell>(cell));
+ __ movq(FieldOperand(rcx, JSGlobalPropertyCell::kValueOffset), rax);
+
+ // Return the value (register rax).
+ __ IncrementCounter(&Counters::named_store_global_inline, 1);
+ __ ret(0);
+
+ // Handle store cache miss.
__ bind(&miss);
- GenerateLoadMiss(masm(), Code::LOAD_IC);
+ __ IncrementCounter(&Counters::named_store_global_inline_miss, 1);
+ Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
+ __ Jump(ic, RelocInfo::CODE_TARGET);
// Return the generated code.
- return GetCode(CONSTANT_FUNCTION, name);
+ return GetCode(NORMAL, name);
+}
+
+
+MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object,
+ int index,
+ Map* transition,
+ String* name) {
+ // ----------- S t a t e -------------
+ // -- rax : value
+ // -- rcx : key
+ // -- rdx : receiver
+ // -- rsp[0] : return address
+ // -----------------------------------
+ Label miss;
+
+ __ IncrementCounter(&Counters::keyed_store_field, 1);
+
+ // Check that the name has not changed.
+ __ Cmp(rcx, Handle<String>(name));
+ __ j(not_equal, &miss);
+
+ // Generate store field code. Preserves receiver and name on jump to miss.
+ GenerateStoreField(masm(),
+ object,
+ index,
+ transition,
+ rdx, rcx, rbx,
+ &miss);
+
+ // Handle store cache miss.
+ __ bind(&miss);
+ __ DecrementCounter(&Counters::keyed_store_field, 1);
+ Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
+ __ Jump(ic, RelocInfo::CODE_TARGET);
+
+ // Return the generated code.
+ return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name);
+}
+
+
+MaybeObject* KeyedStoreStubCompiler::CompileStoreSpecialized(
+ JSObject* receiver) {
+ // ----------- S t a t e -------------
+ // -- rax : value
+ // -- rcx : key
+ // -- rdx : receiver
+ // -- rsp[0] : return address
+ // -----------------------------------
+ Label miss;
+
+ // Check that the receiver isn't a smi.
+ __ JumpIfSmi(rdx, &miss);
+
+ // Check that the map matches.
+ __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset),
+ Handle<Map>(receiver->map()));
+ __ j(not_equal, &miss);
+
+ // Check that the key is a smi.
+ __ JumpIfNotSmi(rcx, &miss);
+
+ // Get the elements array and make sure it is a fast element array, not 'cow'.
+ __ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset));
+ __ Cmp(FieldOperand(rdi, HeapObject::kMapOffset),
+ Factory::fixed_array_map());
+ __ j(not_equal, &miss);
+
+ // Check that the key is within bounds.
+ if (receiver->IsJSArray()) {
+ __ SmiCompare(rcx, FieldOperand(rdx, JSArray::kLengthOffset));
+ __ j(above_equal, &miss);
+ } else {
+ __ SmiCompare(rcx, FieldOperand(rdi, FixedArray::kLengthOffset));
+ __ j(above_equal, &miss);
+ }
+
+ // Do the store and update the write barrier. Make sure to preserve
+ // the value in register eax.
+ __ movq(rdx, rax);
+ __ SmiToInteger32(rcx, rcx);
+ __ movq(FieldOperand(rdi, rcx, times_pointer_size, FixedArray::kHeaderSize),
+ rax);
+ __ RecordWrite(rdi, 0, rdx, rcx);
+
+ // Done.
+ __ ret(0);
+
+ // Handle store cache miss.
+ __ bind(&miss);
+ Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
+ __ jmp(ic, RelocInfo::CODE_TARGET);
+
+ // Return the generated code.
+ return GetCode(NORMAL, NULL);
}
@@ -1993,6 +2608,53 @@ MaybeObject* LoadStubCompiler::CompileLoadField(JSObject* object,
}
+MaybeObject* LoadStubCompiler::CompileLoadCallback(String* name,
+ JSObject* object,
+ JSObject* holder,
+ AccessorInfo* callback) {
+ // ----------- S t a t e -------------
+ // -- rax : receiver
+ // -- rcx : name
+ // -- rsp[0] : return address
+ // -----------------------------------
+ Label miss;
+
+ Failure* failure = Failure::InternalError();
+ bool success = GenerateLoadCallback(object, holder, rax, rcx, rdx, rbx, rdi,
+ callback, name, &miss, &failure);
+ if (!success) {
+ miss.Unuse();
+ return failure;
+ }
+
+ __ bind(&miss);
+ GenerateLoadMiss(masm(), Code::LOAD_IC);
+
+ // Return the generated code.
+ return GetCode(CALLBACKS, name);
+}
+
+
+MaybeObject* LoadStubCompiler::CompileLoadConstant(JSObject* object,
+ JSObject* holder,
+ Object* value,
+ String* name) {
+ // ----------- S t a t e -------------
+ // -- rax : receiver
+ // -- rcx : name
+ // -- rsp[0] : return address
+ // -----------------------------------
+ Label miss;
+
+ GenerateLoadConstant(object, holder, rax, rbx, rdx, rdi, value, name, &miss);
+ __ bind(&miss);
+ GenerateLoadMiss(masm(), Code::LOAD_IC);
+
+ // Return the generated code.
+ return GetCode(CONSTANT_FUNCTION, name);
+}
+
+
MaybeObject* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
JSObject* holder,
String* name) {
@@ -2075,11 +2737,10 @@ MaybeObject* LoadStubCompiler::CompileLoadGlobal(JSObject* object,
}
-MaybeObject* KeyedLoadStubCompiler::CompileLoadCallback(
- String* name,
- JSObject* receiver,
- JSObject* holder,
- AccessorInfo* callback) {
+MaybeObject* KeyedLoadStubCompiler::CompileLoadField(String* name,
+ JSObject* receiver,
+ JSObject* holder,
+ int index) {
// ----------- S t a t e -------------
// -- rax : key
// -- rdx : receiver
@@ -2087,46 +2748,52 @@ MaybeObject* KeyedLoadStubCompiler::CompileLoadCallback(
// -----------------------------------
Label miss;
- __ IncrementCounter(&Counters::keyed_load_callback, 1);
+ __ IncrementCounter(&Counters::keyed_load_field, 1);
// Check that the name has not changed.
__ Cmp(rax, Handle<String>(name));
__ j(not_equal, &miss);
- Failure* failure = Failure::InternalError();
- bool success = GenerateLoadCallback(receiver, holder, rdx, rax, rbx, rcx, rdi,
- callback, name, &miss, &failure);
- if (!success) {
- miss.Unuse();
- return failure;
- }
+ GenerateLoadField(receiver, holder, rdx, rbx, rcx, rdi, index, name, &miss);
__ bind(&miss);
- __ DecrementCounter(&Counters::keyed_load_callback, 1);
+ __ DecrementCounter(&Counters::keyed_load_field, 1);
GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
// Return the generated code.
- return GetCode(CALLBACKS, name);
+ return GetCode(FIELD, name);
}
-MaybeObject* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) {
+MaybeObject* KeyedLoadStubCompiler::CompileLoadCallback(
+ String* name,
+ JSObject* receiver,
+ JSObject* holder,
+ AccessorInfo* callback) {
// ----------- S t a t e -------------
- // -- rax : key
- // -- rdx : receiver
+ // -- rax : key
+ // -- rdx : receiver
// -- rsp[0] : return address
// -----------------------------------
Label miss;
- __ IncrementCounter(&Counters::keyed_load_array_length, 1);
+ __ IncrementCounter(&Counters::keyed_load_callback, 1);
// Check that the name has not changed.
__ Cmp(rax, Handle<String>(name));
__ j(not_equal, &miss);
- GenerateLoadArrayLength(masm(), rdx, rcx, &miss);
+ Failure* failure = Failure::InternalError();
+ bool success = GenerateLoadCallback(receiver, holder, rdx, rax, rbx, rcx, rdi,
+ callback, name, &miss, &failure);
+ if (!success) {
+ miss.Unuse();
+ return failure;
+ }
+
__ bind(&miss);
- __ DecrementCounter(&Counters::keyed_load_array_length, 1);
+
+ __ DecrementCounter(&Counters::keyed_load_callback, 1);
GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
// Return the generated code.
@@ -2162,30 +2829,6 @@ MaybeObject* KeyedLoadStubCompiler::CompileLoadConstant(String* name,
}
-MaybeObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
- // ----------- S t a t e -------------
- // -- rax : key
- // -- rdx : receiver
- // -- rsp[0] : return address
- // -----------------------------------
- Label miss;
-
- __ IncrementCounter(&Counters::keyed_load_function_prototype, 1);
-
- // Check that the name has not changed.
- __ Cmp(rax, Handle<String>(name));
- __ j(not_equal, &miss);
-
- GenerateLoadFunctionPrototype(masm(), rdx, rcx, rbx, &miss);
- __ bind(&miss);
- __ DecrementCounter(&Counters::keyed_load_function_prototype, 1);
- GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
-
- // Return the generated code.
- return GetCode(CALLBACKS, name);
-}
-
-
MaybeObject* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
JSObject* holder,
String* name) {
@@ -2223,23 +2866,23 @@ MaybeObject* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
}
-MaybeObject* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) {
+MaybeObject* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) {
// ----------- S t a t e -------------
// -- rax : key
// -- rdx : receiver
- // -- rsp[0] : return address
+ // -- rsp[0] : return address
// -----------------------------------
Label miss;
- __ IncrementCounter(&Counters::keyed_load_string_length, 1);
+ __ IncrementCounter(&Counters::keyed_load_array_length, 1);
// Check that the name has not changed.
__ Cmp(rax, Handle<String>(name));
__ j(not_equal, &miss);
- GenerateLoadStringLength(masm(), rdx, rcx, rbx, &miss);
+ GenerateLoadArrayLength(masm(), rdx, rcx, &miss);
__ bind(&miss);
- __ DecrementCounter(&Counters::keyed_load_string_length, 1);
+ __ DecrementCounter(&Counters::keyed_load_array_length, 1);
GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
// Return the generated code.
@@ -2247,287 +2890,59 @@ MaybeObject* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) {
}
-MaybeObject* KeyedLoadStubCompiler::CompileLoadSpecialized(JSObject* receiver) {
+MaybeObject* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) {
// ----------- S t a t e -------------
// -- rax : key
// -- rdx : receiver
- // -- esp[0] : return address
- // -----------------------------------
- Label miss;
-
- // Check that the receiver isn't a smi.
- __ JumpIfSmi(rdx, &miss);
-
- // Check that the map matches.
- __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset),
- Handle<Map>(receiver->map()));
- __ j(not_equal, &miss);
-
- // Check that the key is a smi.
- __ JumpIfNotSmi(rax, &miss);
-
- // Get the elements array.
- __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset));
- __ AssertFastElements(rcx);
-
- // Check that the key is within bounds.
- __ SmiCompare(rax, FieldOperand(rcx, FixedArray::kLengthOffset));
- __ j(above_equal, &miss);
-
- // Load the result and make sure it's not the hole.
- SmiIndex index = masm()->SmiToIndex(rbx, rax, kPointerSizeLog2);
- __ movq(rbx, FieldOperand(rcx,
- index.reg,
- index.scale,
- FixedArray::kHeaderSize));
- __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex);
- __ j(equal, &miss);
- __ movq(rax, rbx);
- __ ret(0);
-
- __ bind(&miss);
- GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
-
- // Return the generated code.
- return GetCode(NORMAL, NULL);
-}
-
-
-MaybeObject* StoreStubCompiler::CompileStoreCallback(JSObject* object,
- AccessorInfo* callback,
- String* name) {
- // ----------- S t a t e -------------
- // -- rax : value
- // -- rcx : name
- // -- rdx : receiver
// -- rsp[0] : return address
// -----------------------------------
Label miss;
- // Check that the object isn't a smi.
- __ JumpIfSmi(rdx, &miss);
+ __ IncrementCounter(&Counters::keyed_load_string_length, 1);
- // Check that the map of the object hasn't changed.
- __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset),
- Handle<Map>(object->map()));
+ // Check that the name has not changed.
+ __ Cmp(rax, Handle<String>(name));
__ j(not_equal, &miss);
- // Perform global security token check if needed.
- if (object->IsJSGlobalProxy()) {
- __ CheckAccessGlobalProxy(rdx, rbx, &miss);
- }
-
- // Stub never generated for non-global objects that require access
- // checks.
- ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
-
- __ pop(rbx); // remove the return address
- __ push(rdx); // receiver
- __ Push(Handle<AccessorInfo>(callback)); // callback info
- __ push(rcx); // name
- __ push(rax); // value
- __ push(rbx); // restore return address
-
- // Do tail-call to the runtime system.
- ExternalReference store_callback_property =
- ExternalReference(IC_Utility(IC::kStoreCallbackProperty));
- __ TailCallExternalReference(store_callback_property, 4, 1);
-
- // Handle store cache miss.
+ GenerateLoadStringLength(masm(), rdx, rcx, rbx, &miss);
__ bind(&miss);
- Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
- __ Jump(ic, RelocInfo::CODE_TARGET);
+ __ DecrementCounter(&Counters::keyed_load_string_length, 1);
+ GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
// Return the generated code.
return GetCode(CALLBACKS, name);
}
-MaybeObject* StoreStubCompiler::CompileStoreField(JSObject* object,
- int index,
- Map* transition,
- String* name) {
- // ----------- S t a t e -------------
- // -- rax : value
- // -- rcx : name
- // -- rdx : receiver
- // -- rsp[0] : return address
- // -----------------------------------
- Label miss;
-
- // Generate store field code. Preserves receiver and name on jump to miss.
- GenerateStoreField(masm(),
- object,
- index,
- transition,
- rdx, rcx, rbx,
- &miss);
-
- // Handle store cache miss.
- __ bind(&miss);
- Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
- __ Jump(ic, RelocInfo::CODE_TARGET);
-
- // Return the generated code.
- return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name);
-}
-
-
-MaybeObject* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver,
- String* name) {
- // ----------- S t a t e -------------
- // -- rax : value
- // -- rcx : name
- // -- rdx : receiver
- // -- rsp[0] : return address
- // -----------------------------------
- Label miss;
-
- // Check that the object isn't a smi.
- __ JumpIfSmi(rdx, &miss);
-
- // Check that the map of the object hasn't changed.
- __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset),
- Handle<Map>(receiver->map()));
- __ j(not_equal, &miss);
-
- // Perform global security token check if needed.
- if (receiver->IsJSGlobalProxy()) {
- __ CheckAccessGlobalProxy(rdx, rbx, &miss);
- }
-
- // Stub never generated for non-global objects that require access
- // checks.
- ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded());
-
- __ pop(rbx); // remove the return address
- __ push(rdx); // receiver
- __ push(rcx); // name
- __ push(rax); // value
- __ push(rbx); // restore return address
-
- // Do tail-call to the runtime system.
- ExternalReference store_ic_property =
- ExternalReference(IC_Utility(IC::kStoreInterceptorProperty));
- __ TailCallExternalReference(store_ic_property, 3, 1);
-
- // Handle store cache miss.
- __ bind(&miss);
- Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
- __ Jump(ic, RelocInfo::CODE_TARGET);
-
- // Return the generated code.
- return GetCode(INTERCEPTOR, name);
-}
-
-
-MaybeObject* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object,
- JSGlobalPropertyCell* cell,
- String* name) {
+MaybeObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
// ----------- S t a t e -------------
- // -- rax : value
- // -- rcx : name
+ // -- rax : key
// -- rdx : receiver
- // -- rsp[0] : return address
- // -----------------------------------
- Label miss;
-
- // Check that the map of the global has not changed.
- __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset),
- Handle<Map>(object->map()));
- __ j(not_equal, &miss);
-
- // Store the value in the cell.
- __ Move(rcx, Handle<JSGlobalPropertyCell>(cell));
- __ movq(FieldOperand(rcx, JSGlobalPropertyCell::kValueOffset), rax);
-
- // Return the value (register rax).
- __ IncrementCounter(&Counters::named_store_global_inline, 1);
- __ ret(0);
-
- // Handle store cache miss.
- __ bind(&miss);
- __ IncrementCounter(&Counters::named_store_global_inline_miss, 1);
- Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
- __ Jump(ic, RelocInfo::CODE_TARGET);
-
- // Return the generated code.
- return GetCode(NORMAL, name);
-}
-
-
-MaybeObject* KeyedLoadStubCompiler::CompileLoadField(String* name,
- JSObject* receiver,
- JSObject* holder,
- int index) {
- // ----------- S t a t e -------------
- // -- rax : key
- // -- rdx : receiver
// -- rsp[0] : return address
// -----------------------------------
Label miss;
- __ IncrementCounter(&Counters::keyed_load_field, 1);
+ __ IncrementCounter(&Counters::keyed_load_function_prototype, 1);
// Check that the name has not changed.
__ Cmp(rax, Handle<String>(name));
__ j(not_equal, &miss);
- GenerateLoadField(receiver, holder, rdx, rbx, rcx, rdi, index, name, &miss);
-
+ GenerateLoadFunctionPrototype(masm(), rdx, rcx, rbx, &miss);
__ bind(&miss);
- __ DecrementCounter(&Counters::keyed_load_field, 1);
+ __ DecrementCounter(&Counters::keyed_load_function_prototype, 1);
GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
// Return the generated code.
- return GetCode(FIELD, name);
-}
-
-
-MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object,
- int index,
- Map* transition,
- String* name) {
- // ----------- S t a t e -------------
- // -- rax : value
- // -- rcx : key
- // -- rdx : receiver
- // -- rsp[0] : return address
- // -----------------------------------
- Label miss;
-
- __ IncrementCounter(&Counters::keyed_store_field, 1);
-
- // Check that the name has not changed.
- __ Cmp(rcx, Handle<String>(name));
- __ j(not_equal, &miss);
-
- // Generate store field code. Preserves receiver and name on jump to miss.
- GenerateStoreField(masm(),
- object,
- index,
- transition,
- rdx, rcx, rbx,
- &miss);
-
- // Handle store cache miss.
- __ bind(&miss);
- __ DecrementCounter(&Counters::keyed_store_field, 1);
- Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
- __ Jump(ic, RelocInfo::CODE_TARGET);
-
- // Return the generated code.
- return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name);
+ return GetCode(CALLBACKS, name);
}
-MaybeObject* KeyedStoreStubCompiler::CompileStoreSpecialized(
- JSObject* receiver) {
+MaybeObject* KeyedLoadStubCompiler::CompileLoadSpecialized(JSObject* receiver) {
// ----------- S t a t e -------------
- // -- rax : value
- // -- rcx : key
+ // -- rax : key
// -- rdx : receiver
- // -- rsp[0] : return address
+ // -- esp[0] : return address
// -----------------------------------
Label miss;
@@ -2540,455 +2955,35 @@ MaybeObject* KeyedStoreStubCompiler::CompileStoreSpecialized(
__ j(not_equal, &miss);
// Check that the key is a smi.
- __ JumpIfNotSmi(rcx, &miss);
+ __ JumpIfNotSmi(rax, &miss);
- // Get the elements array and make sure it is a fast element array, not 'cow'.
- __ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset));
- __ Cmp(FieldOperand(rdi, HeapObject::kMapOffset),
- Factory::fixed_array_map());
- __ j(not_equal, &miss);
+ // Get the elements array.
+ __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset));
+ __ AssertFastElements(rcx);
// Check that the key is within bounds.
- if (receiver->IsJSArray()) {
- __ SmiCompare(rcx, FieldOperand(rdx, JSArray::kLengthOffset));
- __ j(above_equal, &miss);
- } else {
- __ SmiCompare(rcx, FieldOperand(rdi, FixedArray::kLengthOffset));
- __ j(above_equal, &miss);
- }
-
- // Do the store and update the write barrier. Make sure to preserve
- // the value in register eax.
- __ movq(rdx, rax);
- __ SmiToInteger32(rcx, rcx);
- __ movq(FieldOperand(rdi, rcx, times_pointer_size, FixedArray::kHeaderSize),
- rax);
- __ RecordWrite(rdi, 0, rdx, rcx);
+ __ SmiCompare(rax, FieldOperand(rcx, FixedArray::kLengthOffset));
+ __ j(above_equal, &miss);
- // Done.
+ // Load the result and make sure it's not the hole.
+ SmiIndex index = masm()->SmiToIndex(rbx, rax, kPointerSizeLog2);
+ __ movq(rbx, FieldOperand(rcx,
+ index.reg,
+ index.scale,
+ FixedArray::kHeaderSize));
+ __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex);
+ __ j(equal, &miss);
+ __ movq(rax, rbx);
__ ret(0);
- // Handle store cache miss.
__ bind(&miss);
- Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
- __ jmp(ic, RelocInfo::CODE_TARGET);
+ GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
// Return the generated code.
return GetCode(NORMAL, NULL);
}
-void StubCompiler::GenerateLoadInterceptor(JSObject* object,
- JSObject* interceptor_holder,
- LookupResult* lookup,
- Register receiver,
- Register name_reg,
- Register scratch1,
- Register scratch2,
- Register scratch3,
- String* name,
- Label* miss) {
- ASSERT(interceptor_holder->HasNamedInterceptor());
- ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined());
-
- // Check that the receiver isn't a smi.
- __ JumpIfSmi(receiver, miss);
-
- // So far the most popular follow ups for interceptor loads are FIELD
- // and CALLBACKS, so inline only them, other cases may be added
- // later.
- bool compile_followup_inline = false;
- if (lookup->IsProperty() && lookup->IsCacheable()) {
- if (lookup->type() == FIELD) {
- compile_followup_inline = true;
- } else if (lookup->type() == CALLBACKS &&
- lookup->GetCallbackObject()->IsAccessorInfo() &&
- AccessorInfo::cast(lookup->GetCallbackObject())->getter() != NULL) {
- compile_followup_inline = true;
- }
- }
-
- if (compile_followup_inline) {
- // Compile the interceptor call, followed by inline code to load the
- // property from further up the prototype chain if the call fails.
- // Check that the maps haven't changed.
- Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder,
- scratch1, scratch2, scratch3,
- name, miss);
- ASSERT(holder_reg.is(receiver) || holder_reg.is(scratch1));
-
- // Save necessary data before invoking an interceptor.
- // Requires a frame to make GC aware of pushed pointers.
- __ EnterInternalFrame();
-
- if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) {
- // CALLBACKS case needs a receiver to be passed into C++ callback.
- __ push(receiver);
- }
- __ push(holder_reg);
- __ push(name_reg);
-
- // Invoke an interceptor. Note: map checks from receiver to
- // interceptor's holder has been compiled before (see a caller
- // of this method.)
- CompileCallLoadPropertyWithInterceptor(masm(),
- receiver,
- holder_reg,
- name_reg,
- interceptor_holder);
-
- // Check if interceptor provided a value for property. If it's
- // the case, return immediately.
- Label interceptor_failed;
- __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex);
- __ j(equal, &interceptor_failed);
- __ LeaveInternalFrame();
- __ ret(0);
-
- __ bind(&interceptor_failed);
- __ pop(name_reg);
- __ pop(holder_reg);
- if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) {
- __ pop(receiver);
- }
-
- __ LeaveInternalFrame();
-
- // Check that the maps from interceptor's holder to lookup's holder
- // haven't changed. And load lookup's holder into |holder| register.
- if (interceptor_holder != lookup->holder()) {
- holder_reg = CheckPrototypes(interceptor_holder,
- holder_reg,
- lookup->holder(),
- scratch1,
- scratch2,
- scratch3,
- name,
- miss);
- }
-
- if (lookup->type() == FIELD) {
- // We found FIELD property in prototype chain of interceptor's holder.
- // Retrieve a field from field's holder.
- GenerateFastPropertyLoad(masm(), rax, holder_reg,
- lookup->holder(), lookup->GetFieldIndex());
- __ ret(0);
- } else {
- // We found CALLBACKS property in prototype chain of interceptor's
- // holder.
- ASSERT(lookup->type() == CALLBACKS);
- ASSERT(lookup->GetCallbackObject()->IsAccessorInfo());
- AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject());
- ASSERT(callback != NULL);
- ASSERT(callback->getter() != NULL);
-
- // Tail call to runtime.
- // Important invariant in CALLBACKS case: the code above must be
- // structured to never clobber |receiver| register.
- __ pop(scratch2); // return address
- __ push(receiver);
- __ push(holder_reg);
- __ Move(holder_reg, Handle<AccessorInfo>(callback));
- __ push(FieldOperand(holder_reg, AccessorInfo::kDataOffset));
- __ push(holder_reg);
- __ push(name_reg);
- __ push(scratch2); // restore return address
-
- ExternalReference ref =
- ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
- __ TailCallExternalReference(ref, 5, 1);
- }
- } else { // !compile_followup_inline
- // Call the runtime system to load the interceptor.
- // Check that the maps haven't changed.
- Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder,
- scratch1, scratch2, scratch3,
- name, miss);
- __ pop(scratch2); // save old return address
- PushInterceptorArguments(masm(), receiver, holder_reg,
- name_reg, interceptor_holder);
- __ push(scratch2); // restore old return address
-
- ExternalReference ref = ExternalReference(
- IC_Utility(IC::kLoadPropertyWithInterceptorForLoad));
- __ TailCallExternalReference(ref, 5, 1);
- }
-}
-
-
-bool StubCompiler::GenerateLoadCallback(JSObject* object,
- JSObject* holder,
- Register receiver,
- Register name_reg,
- Register scratch1,
- Register scratch2,
- Register scratch3,
- AccessorInfo* callback,
- String* name,
- Label* miss,
- Failure** failure) {
- // Check that the receiver isn't a smi.
- __ JumpIfSmi(receiver, miss);
-
- // Check that the maps haven't changed.
- Register reg =
- CheckPrototypes(object, receiver, holder, scratch1,
- scratch2, scratch3, name, miss);
-
- Handle<AccessorInfo> callback_handle(callback);
-
- // Insert additional parameters into the stack frame above return address.
- ASSERT(!scratch2.is(reg));
- __ pop(scratch2); // Get return address to place it below.
-
- __ push(receiver); // receiver
- __ push(reg); // holder
- if (Heap::InNewSpace(callback_handle->data())) {
- __ Move(scratch1, callback_handle);
- __ push(FieldOperand(scratch1, AccessorInfo::kDataOffset)); // data
- } else {
- __ Push(Handle<Object>(callback_handle->data()));
- }
- __ 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.
-
-#ifdef _WIN64
- // Win64 uses first register--rcx--for returned value.
- Register accessor_info_arg = r8;
- Register name_arg = rdx;
-#else
- Register accessor_info_arg = rsi;
- Register name_arg = rdi;
-#endif
-
- ASSERT(!name_arg.is(scratch2));
- __ movq(name_arg, rsp);
- __ push(scratch2); // Restore return address.
-
- // Do call through the api.
- Address getter_address = v8::ToCData<Address>(callback->getter());
- ApiFunction fun(getter_address);
-
- // 3 elements array for v8::Agruments::values_ and handler for name.
- const int kStackSpace = 4;
-
- // Allocate v8::AccessorInfo in non-GCed stack space.
- const int kArgStackSpace = 1;
-
- __ PrepareCallApiFunction(kArgStackSpace);
- __ lea(rax, Operand(name_arg, 3 * kPointerSize));
-
- // v8::AccessorInfo::args_.
- __ movq(StackSpaceOperand(0), rax);
-
- // The context register (rsi) has been saved in PrepareCallApiFunction and
- // could be used to pass arguments.
- __ lea(accessor_info_arg, StackSpaceOperand(0));
-
- // 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()->TryCallApiFunctionAndReturn(&fun, kStackSpace);
- if (result->IsFailure()) {
- *failure = Failure::cast(result);
- return false;
- }
- return true;
-}
-
-
-Register StubCompiler::CheckPrototypes(JSObject* object,
- Register object_reg,
- JSObject* holder,
- Register holder_reg,
- Register scratch1,
- Register scratch2,
- String* name,
- int save_at_depth,
- Label* miss) {
- // Make sure there's no overlap between holder and object registers.
- ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg));
- ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg)
- && !scratch2.is(scratch1));
-
- // Keep track of the current object in register reg. On the first
- // iteration, reg is an alias for object_reg, on later iterations,
- // it is an alias for holder_reg.
- Register reg = object_reg;
- int depth = 0;
-
- if (save_at_depth == depth) {
- __ movq(Operand(rsp, kPointerSize), object_reg);
- }
-
- // Check the maps in the prototype chain.
- // Traverse the prototype chain from the object and do map checks.
- JSObject* current = object;
- while (current != holder) {
- depth++;
-
- // Only global objects and objects that do not require access
- // checks are allowed in stubs.
- ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded());
-
- JSObject* prototype = JSObject::cast(current->GetPrototype());
- if (!current->HasFastProperties() &&
- !current->IsJSGlobalObject() &&
- !current->IsJSGlobalProxy()) {
- if (!name->IsSymbol()) {
- MaybeObject* lookup_result = Heap::LookupSymbol(name);
- if (lookup_result->IsFailure()) {
- set_failure(Failure::cast(lookup_result));
- return reg;
- } else {
- name = String::cast(lookup_result->ToObjectUnchecked());
- }
- }
- ASSERT(current->property_dictionary()->FindEntry(name) ==
- StringDictionary::kNotFound);
-
- GenerateDictionaryNegativeLookup(masm(),
- miss,
- reg,
- name,
- scratch1,
- scratch2);
- __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
- reg = holder_reg; // from now the object is in holder_reg
- __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
- } else if (Heap::InNewSpace(prototype)) {
- // Get the map of the current object.
- __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
- __ Cmp(scratch1, Handle<Map>(current->map()));
- // Branch on the result of the map check.
- __ j(not_equal, miss);
- // Check access rights to the global object. This has to happen
- // after the map check so that we know that the object is
- // actually a global object.
- if (current->IsJSGlobalProxy()) {
- __ CheckAccessGlobalProxy(reg, scratch1, miss);
-
- // Restore scratch register to be the map of the object.
- // We load the prototype from the map in the scratch register.
- __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
- }
- // The prototype is in new space; we cannot store a reference
- // to it in the code. Load it from the map.
- reg = holder_reg; // from now the object is in holder_reg
- __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
-
- } else {
- // Check the map of the current object.
- __ Cmp(FieldOperand(reg, HeapObject::kMapOffset),
- Handle<Map>(current->map()));
- // Branch on the result of the map check.
- __ j(not_equal, miss);
- // Check access rights to the global object. This has to happen
- // after the map check so that we know that the object is
- // actually a global object.
- if (current->IsJSGlobalProxy()) {
- __ CheckAccessGlobalProxy(reg, scratch1, miss);
- }
- // The prototype is in old space; load it directly.
- reg = holder_reg; // from now the object is in holder_reg
- __ Move(reg, Handle<JSObject>(prototype));
- }
-
- if (save_at_depth == depth) {
- __ movq(Operand(rsp, kPointerSize), reg);
- }
-
- // Go to the next object in the prototype chain.
- current = prototype;
- }
-
- // Check the holder map.
- __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), Handle<Map>(holder->map()));
- __ j(not_equal, miss);
-
- // Log the check depth.
- LOG(IntEvent("check-maps-depth", depth + 1));
-
- // Perform security check for access to the global object and return
- // the holder register.
- ASSERT(current == holder);
- ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded());
- if (current->IsJSGlobalProxy()) {
- __ CheckAccessGlobalProxy(reg, scratch1, miss);
- }
-
- // If we've skipped any global objects, it's not enough to verify
- // that their maps haven't changed. We also need to check that the
- // property cell for the property is still empty.
- current = object;
- while (current != holder) {
- if (current->IsGlobalObject()) {
- MaybeObject* cell = GenerateCheckPropertyCell(masm(),
- GlobalObject::cast(current),
- name,
- scratch1,
- miss);
- if (cell->IsFailure()) {
- set_failure(Failure::cast(cell));
- return reg;
- }
- }
- current = JSObject::cast(current->GetPrototype());
- }
-
- // Return the register containing the holder.
- return reg;
-}
-
-
-void StubCompiler::GenerateLoadField(JSObject* object,
- JSObject* holder,
- Register receiver,
- Register scratch1,
- Register scratch2,
- Register scratch3,
- int index,
- String* name,
- Label* miss) {
- // Check that the receiver isn't a smi.
- __ JumpIfSmi(receiver, miss);
-
- // Check the prototype chain.
- Register reg =
- CheckPrototypes(object, receiver, holder,
- scratch1, scratch2, scratch3, name, miss);
-
- // Get the value from the properties.
- GenerateFastPropertyLoad(masm(), rax, reg, holder, index);
- __ ret(0);
-}
-
-
-void StubCompiler::GenerateLoadConstant(JSObject* object,
- JSObject* holder,
- Register receiver,
- Register scratch1,
- Register scratch2,
- Register scratch3,
- Object* value,
- String* name,
- Label* miss) {
- // Check that the receiver isn't a smi.
- __ JumpIfSmi(receiver, miss);
-
- // Check that the maps haven't changed.
- Register reg =
- CheckPrototypes(object, receiver, holder,
- scratch1, scratch2, scratch3, name, miss);
-
- // Return the constant value.
- __ Move(rax, Handle<Object>(value));
- __ ret(0);
-}
-
-
// Specialized stub for constructing objects from functions which only have only
// simple assignments of the form this.x = ...; in their body.
MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) {
diff --git a/test/cctest/test-assembler-ia32.cc b/test/cctest/test-assembler-ia32.cc
index 40232ef5..14692ff1 100644
--- a/test/cctest/test-assembler-ia32.cc
+++ b/test/cctest/test-assembler-ia32.cc
@@ -74,7 +74,7 @@ TEST(AssemblerIa320) {
Handle<Object>(Heap::undefined_value()))->
ToObjectChecked();
CHECK(code->IsCode());
-#ifdef DEBUG
+#ifdef OBJECT_PRINT
Code::cast(code)->Print();
#endif
F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
@@ -112,7 +112,7 @@ TEST(AssemblerIa321) {
Handle<Object>(Heap::undefined_value()))->
ToObjectChecked();
CHECK(code->IsCode());
-#ifdef DEBUG
+#ifdef OBJECT_PRINT
Code::cast(code)->Print();
#endif
F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
@@ -155,7 +155,7 @@ TEST(AssemblerIa322) {
Handle<Object>(Heap::undefined_value()))->ToObjectChecked();
CHECK(code->IsCode());
-#ifdef DEBUG
+#ifdef OBJECT_PRINT
Code::cast(code)->Print();
#endif
F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
@@ -329,7 +329,7 @@ TEST(AssemblerIa328) {
Code::ComputeFlags(Code::STUB),
Handle<Object>(Heap::undefined_value()))->ToObjectChecked());
CHECK(code->IsCode());
-#ifdef DEBUG
+#ifdef OBJECT_PRINT
Code::cast(code)->Print();
#endif
F6 f = FUNCTION_CAST<F6>(Code::cast(code)->entry());
@@ -384,7 +384,7 @@ TEST(AssemblerIa329) {
Code::ComputeFlags(Code::STUB),
Handle<Object>(Heap::undefined_value()))->ToObjectChecked());
CHECK(code->IsCode());
-#ifdef DEBUG
+#ifdef OBJECT_PRINT
Code::cast(code)->Print();
#endif
diff --git a/test/cctest/test-disasm-ia32.cc b/test/cctest/test-disasm-ia32.cc
index 5cd56acf..b563f8fc 100644
--- a/test/cctest/test-disasm-ia32.cc
+++ b/test/cctest/test-disasm-ia32.cc
@@ -443,7 +443,7 @@ TEST(DisasmIa320) {
Code::ComputeFlags(Code::STUB),
Handle<Object>(Heap::undefined_value()))->ToObjectChecked();
CHECK(code->IsCode());
-#ifdef DEBUG
+#ifdef OBJECT_PRINT
Code::cast(code)->Print();
byte* begin = Code::cast(code)->instruction_start();
byte* end = begin + Code::cast(code)->instruction_size();
diff --git a/test/cctest/test-parsing.cc b/test/cctest/test-parsing.cc
index e642d1b6..da5d771d 100755
--- a/test/cctest/test-parsing.cc
+++ b/test/cctest/test-parsing.cc
@@ -573,7 +573,7 @@ void TestStreamScanner(i::UC16CharacterStream* stream,
int skip_pos = 0, // Zero means not skipping.
int skip_to = 0) {
i::V8JavaScriptScanner scanner;
- scanner.Initialize(stream, i::JavaScriptScanner::kAllLiterals);
+ scanner.Initialize(stream);
int i = 0;
do {
diff --git a/test/mjsunit/bugs/bug-1015.js b/test/mjsunit/bugs/bug-1015.js
new file mode 100644
index 00000000..9e4406a9
--- /dev/null
+++ b/test/mjsunit/bugs/bug-1015.js
@@ -0,0 +1,66 @@
+// 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.
+
+// See: http://code.google.com/p/v8/issues/detail?id=1015
+
+// Object and array literals should be created using DefineOwnProperty, and
+// therefore not hit setters in the prototype.
+
+function mkFail(message) {
+ return function () { assertUnreachable(message); }
+}
+
+Object.defineProperty(Object.prototype, "foo",
+ {get: mkFail("oget"), set: mkFail("oset")});
+Object.defineProperty(Array.prototype, "2",
+ {get: mkFail("aget"), set: mkFail("aset")});
+
+function inFunction() {
+ for (var i = 0; i < 10; i++) {
+ // in loop.
+ var ja = JSON.parse('[1,2,3,4]');
+ var jo = JSON.parse('{"bar": 10, "foo": 20}')
+ var jop = JSON.parse('{"bar": 10, "__proto__": { }, "foo": 20}')
+ var a = [1,2,3,4];
+ var o = { bar: 10, foo: 20 };
+ var op = { __proto__: { set bar(v) { assertUnreachable("bset"); } },
+ bar: 10 };
+ }
+}
+
+for (var i = 0; i < 10; i++) {
+ // In global scope.
+ var ja = JSON.parse('[1,2,3,4]');
+ var jo = JSON.parse('{"bar": 10, "foo": 20}')
+ var jop = JSON.parse('{"bar": 10, "__proto__": { }, "foo": 20}')
+ var a = [1,2,3,4];
+ var o = { bar: 10, foo: 20 };
+ var op = { __proto__: { set bar(v) { assertUnreachable("bset"); } },
+ bar: 10 };
+ // In function scope.
+ inFunction();
+}
diff --git a/test/mjsunit/indexed-accessors.js b/test/mjsunit/indexed-accessors.js
index 395f2ab3..16348570 100644
--- a/test/mjsunit/indexed-accessors.js
+++ b/test/mjsunit/indexed-accessors.js
@@ -81,19 +81,6 @@ testArray();
expected[0] = 111;
testArray();
-// The functionality is not implemented for arrays due to performance issues.
-var a = [ 1 ];
-a.__defineGetter__('2', function() { return 7; });
-assertEquals(undefined, a[2]);
-assertEquals(1, a.length);
-var b = 0;
-a.__defineSetter__('5', function(y) { b = y; });
-assertEquals(1, a.length);
-a[5] = 42;
-assertEquals(0, b);
-assertEquals(42, a[5]);
-assertEquals(6, a.length);
-
// Using a setter where only a getter is defined throws an exception.
var q = {};
q.__defineGetter__('0', function() { return 42; });
diff --git a/test/mjsunit/regress/regress-1017.js b/test/mjsunit/regress/regress-1017.js
new file mode 100644
index 00000000..3daf5428
--- /dev/null
+++ b/test/mjsunit/regress/regress-1017.js
@@ -0,0 +1,36 @@
+// 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.
+
+// See: http://code.google.com/p/v8/issues/detail?id=1017
+
+// 32 ASCII-characters followed by a non-ASCII character.
+// This causes an internal buffer to first expand to 64 bytes, then expand the
+// 32 ASCII characters to 64 bytes of UC16 characters, leaving no room
+// to store the 33rd character. This fails an ASSERT in debug mode.
+
+assertEquals(33, "12345678901234567890123456789012\u2028".length);
+
diff --git a/test/mjsunit/regress/regress-900.js b/test/mjsunit/regress/regress-900.js
new file mode 100644
index 00000000..9f94348d
--- /dev/null
+++ b/test/mjsunit/regress/regress-900.js
@@ -0,0 +1,46 @@
+// Copyright 2011 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.
+
+// Check that we allow accessors on JSArray elements.
+
+var a = [];
+var b = {}
+Object.defineProperty(a, "1", {get: function() {return "foo";}});
+Object.defineProperty(
+ b, "1", {get: function() {return "bar";}, set: function() {this.x = 42;}});
+assertEquals(a[1], 'foo');
+assertEquals(b[1], 'bar');
+// Make sure we can't overwrite an accessor, but that the setter is
+// instead called.
+b[1] = 'foobar';
+assertEquals(b[1], 'bar');
+assertEquals(b.x, 42);
+
+var desc = Object.getOwnPropertyDescriptor(b, "1");
+assertEquals(desc['writable'], undefined);
+assertFalse(desc['enumerable']);
+assertFalse(desc['configurable']);
diff --git a/test/mozilla/mozilla.status b/test/mozilla/mozilla.status
index 1f9e6eb4..5688cf8d 100644
--- a/test/mozilla/mozilla.status
+++ b/test/mozilla/mozilla.status
@@ -653,8 +653,6 @@ js1_5/extensions/regress-336409-1: FAIL_OK
js1_5/extensions/regress-336409-2: FAIL_OK
js1_5/extensions/regress-336410-2: FAIL_OK
js1_5/extensions/regress-341956-01: FAIL_OK
-js1_5/extensions/regress-341956-02: FAIL_OK
-js1_5/extensions/regress-341956-03: FAIL_OK
js1_5/extensions/regress-345967: FAIL_OK
js1_5/extensions/regress-346494-01: FAIL_OK
js1_5/extensions/regress-346494: FAIL_OK
diff --git a/tools/gyp/v8.gyp b/tools/gyp/v8.gyp
index 6af6611d..365e6503 100644
--- a/tools/gyp/v8.gyp
+++ b/tools/gyp/v8.gyp
@@ -27,792 +27,819 @@
{
'variables': {
+ 'use_system_v8%': 0,
'msvs_use_common_release': 0,
'gcc_version%': 'unknown',
'v8_target_arch%': '<(target_arch)',
'v8_use_snapshot%': 'true',
},
- 'target_defaults': {
- 'defines': [
- 'ENABLE_LOGGING_AND_PROFILING',
- 'ENABLE_DEBUGGER_SUPPORT',
- 'ENABLE_VMSTATE_TRACKING',
- ],
- 'conditions': [
- ['OS!="mac"', {
- # TODO(mark): The OS!="mac" conditional is temporary. It can be
- # removed once the Mac Chromium build stops setting target_arch to
- # ia32 and instead sets it to mac. Other checks in this file for
- # OS=="mac" can be removed at that time as well. This can be cleaned
- # up once http://crbug.com/44205 is fixed.
- 'conditions': [
- ['v8_target_arch=="arm"', {
- 'defines': [
- 'V8_TARGET_ARCH_ARM',
- ],
- }],
- ['v8_target_arch=="ia32"', {
- 'defines': [
- 'V8_TARGET_ARCH_IA32',
- ],
- }],
- ['v8_target_arch=="x64"', {
- 'defines': [
- 'V8_TARGET_ARCH_X64',
- ],
- }],
- ],
- }],
- ],
- 'configurations': {
- 'Debug': {
+ 'conditions': [
+ ['use_system_v8==0', {
+ 'target_defaults': {
'defines': [
- 'DEBUG',
- '_DEBUG',
- 'ENABLE_DISASSEMBLER',
- 'V8_ENABLE_CHECKS',
- 'OBJECT_PRINT',
+ 'ENABLE_LOGGING_AND_PROFILING',
+ 'ENABLE_DEBUGGER_SUPPORT',
+ 'ENABLE_VMSTATE_TRACKING',
],
- 'msvs_settings': {
- 'VCCLCompilerTool': {
- 'Optimization': '0',
-
- 'conditions': [
- ['OS=="win" and component=="shared_library"', {
- 'RuntimeLibrary': '3', # /MDd
- }, {
- 'RuntimeLibrary': '1', # /MTd
- }],
- ],
- },
- 'VCLinkerTool': {
- 'LinkIncremental': '2',
- },
- },
'conditions': [
- ['OS=="freebsd" or OS=="openbsd"', {
- 'cflags': [ '-I/usr/local/include' ],
- }],
- ],
- },
- 'Release': {
- 'conditions': [
- ['OS=="linux" or OS=="freebsd" or OS=="openbsd"', {
- 'cflags!': [
- '-O2',
- '-Os',
- ],
- 'cflags': [
- '-fomit-frame-pointer',
- '-O3',
- ],
+ ['OS!="mac"', {
+ # TODO(mark): The OS!="mac" conditional is temporary. It can be
+ # removed once the Mac Chromium build stops setting target_arch to
+ # ia32 and instead sets it to mac. Other checks in this file for
+ # OS=="mac" can be removed at that time as well. This can be cleaned
+ # up once http://crbug.com/44205 is fixed.
'conditions': [
- [ 'gcc_version==44', {
- 'cflags': [
- # Avoid crashes with gcc 4.4 in the v8 test suite.
- '-fno-tree-vrp',
+ ['v8_target_arch=="arm"', {
+ 'defines': [
+ 'V8_TARGET_ARCH_ARM',
+ ],
+ }],
+ ['v8_target_arch=="ia32"', {
+ 'defines': [
+ 'V8_TARGET_ARCH_IA32',
+ ],
+ }],
+ ['v8_target_arch=="x64"', {
+ 'defines': [
+ 'V8_TARGET_ARCH_X64',
],
}],
],
}],
- ['OS=="freebsd" or OS=="openbsd"', {
- 'cflags': [ '-I/usr/local/include' ],
- }],
- ['OS=="mac"', {
- 'xcode_settings': {
- 'GCC_OPTIMIZATION_LEVEL': '3', # -O3
- 'GCC_STRICT_ALIASING': 'YES', # -fstrict-aliasing. Mainline gcc
- # enables this at -O2 and above,
- # but Apple gcc does not unless it
- # is specified explicitly.
- },
- }],
- ['OS=="win"', {
- 'msvs_configuration_attributes': {
- 'OutputDirectory': '$(SolutionDir)$(ConfigurationName)',
- 'IntermediateDirectory': '$(OutDir)\\obj\\$(ProjectName)',
- 'CharacterSet': '1',
- },
+ ],
+ 'configurations': {
+ 'Debug': {
+ 'defines': [
+ 'DEBUG',
+ '_DEBUG',
+ 'ENABLE_DISASSEMBLER',
+ 'V8_ENABLE_CHECKS',
+ 'OBJECT_PRINT',
+ ],
'msvs_settings': {
'VCCLCompilerTool': {
- 'Optimization': '2',
- 'InlineFunctionExpansion': '2',
- 'EnableIntrinsicFunctions': 'true',
- 'FavorSizeOrSpeed': '0',
- 'OmitFramePointers': 'true',
- 'StringPooling': 'true',
-
+ 'Optimization': '0',
+
'conditions': [
['OS=="win" and component=="shared_library"', {
- 'RuntimeLibrary': '2', #/MD
+ 'RuntimeLibrary': '3', # /MDd
}, {
- 'RuntimeLibrary': '0', #/MT
+ 'RuntimeLibrary': '1', # /MTd
}],
],
},
'VCLinkerTool': {
- 'LinkIncremental': '1',
- 'OptimizeReferences': '2',
- 'OptimizeForWindows98': '1',
- 'EnableCOMDATFolding': '2',
+ 'LinkIncremental': '2',
},
},
- }],
- ],
- },
- },
- },
- 'targets': [
- {
- 'target_name': 'v8',
- 'conditions': [
- ['v8_use_snapshot=="true"', {
- 'dependencies': ['v8_snapshot'],
+ 'conditions': [
+ ['OS=="freebsd" or OS=="openbsd"', {
+ 'cflags': [ '-I/usr/local/include' ],
+ }],
+ ],
+ },
+ 'Release': {
+ 'conditions': [
+ ['OS=="linux" or OS=="freebsd" or OS=="openbsd"', {
+ 'cflags!': [
+ '-O2',
+ '-Os',
+ ],
+ 'cflags': [
+ '-fomit-frame-pointer',
+ '-O3',
+ ],
+ 'conditions': [
+ [ 'gcc_version==44', {
+ 'cflags': [
+ # Avoid crashes with gcc 4.4 in the v8 test suite.
+ '-fno-tree-vrp',
+ ],
+ }],
+ ],
+ }],
+ ['OS=="freebsd" or OS=="openbsd"', {
+ 'cflags': [ '-I/usr/local/include' ],
+ }],
+ ['OS=="mac"', {
+ 'xcode_settings': {
+ 'GCC_OPTIMIZATION_LEVEL': '3', # -O3
+
+ # -fstrict-aliasing. Mainline gcc
+ # enables this at -O2 and above,
+ # but Apple gcc does not unless it
+ # is specified explicitly.
+ 'GCC_STRICT_ALIASING': 'YES',
+ },
+ }],
+ ['OS=="win"', {
+ 'msvs_configuration_attributes': {
+ 'OutputDirectory': '$(SolutionDir)$(ConfigurationName)',
+ 'IntermediateDirectory': '$(OutDir)\\obj\\$(ProjectName)',
+ 'CharacterSet': '1',
+ },
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'Optimization': '2',
+ 'InlineFunctionExpansion': '2',
+ 'EnableIntrinsicFunctions': 'true',
+ 'FavorSizeOrSpeed': '0',
+ 'OmitFramePointers': 'true',
+ 'StringPooling': 'true',
+
+ 'conditions': [
+ ['OS=="win" and component=="shared_library"', {
+ 'RuntimeLibrary': '2', #/MD
+ }, {
+ 'RuntimeLibrary': '0', #/MT
+ }],
+ ],
+ },
+ 'VCLinkerTool': {
+ 'LinkIncremental': '1',
+ 'OptimizeReferences': '2',
+ 'OptimizeForWindows98': '1',
+ 'EnableCOMDATFolding': '2',
+ },
+ },
+ }],
+ ],
+ },
},
+ },
+ 'targets': [
{
- 'dependencies': ['v8_nosnapshot'],
- }],
- ['OS=="win" and component=="shared_library"', {
- 'type': '<(component)',
- 'sources': [
- '../../src/v8dll-main.cc',
- ],
- 'defines': [
- 'BUILDING_V8_SHARED'
+ 'target_name': 'v8',
+ 'conditions': [
+ ['v8_use_snapshot=="true"', {
+ 'dependencies': ['v8_snapshot'],
+ },
+ {
+ 'dependencies': ['v8_nosnapshot'],
+ }],
+ ['OS=="win" and component=="shared_library"', {
+ 'type': '<(component)',
+ 'sources': [
+ '../../src/v8dll-main.cc',
+ ],
+ 'defines': [
+ 'BUILDING_V8_SHARED'
+ ],
+ 'direct_dependent_settings': {
+ 'defines': [
+ 'USING_V8_SHARED',
+ ],
+ },
+ },
+ {
+ 'type': 'none',
+ }],
],
'direct_dependent_settings': {
- 'defines': [
- 'USING_V8_SHARED',
+ 'include_dirs': [
+ '../../include',
],
},
},
{
- 'type': 'none',
- }],
- ],
- 'direct_dependent_settings': {
- 'include_dirs': [
- '../../include',
- ],
- },
- },
- {
- 'target_name': 'v8_preparser',
- 'include_dirs': [
- '../../include',
- '../../src',
- ],
- 'sources': [
- '../../src/allocation.cc',
- '../../src/hashmap.cc',
- '../../src/preparse-data.cc',
- '../../src/preparser.cc',
- '../../src/preparser-api.cc',
- '../../src/scanner-base.cc',
- '../../src/token.cc',
- '../../src/unicode.cc',
- ],
- 'conditions': [
- ['OS=="win" and component=="shared_library"', {
- 'sources': [ '../../src/v8preparserdll-main.cc' ],
- 'defines': [ 'BUILDING_V8_SHARED' ],
- 'direct_dependent_settings': {
- 'defines': [ 'USING_V8_SHARED' ]
- },
- 'type': '<(component)',
- } , {
- 'type': 'none'
- }],
- ['OS!="win"', {
- 'type': '<(library)'
- }],
- ]
- },
- {
- 'target_name': 'v8_snapshot',
- 'type': '<(library)',
- 'conditions': [
- ['OS=="win" and component=="shared_library"', {
- 'defines': [
- 'BUILDING_V8_SHARED',
+ 'target_name': 'v8_preparser',
+ 'include_dirs': [
+ '../../include',
+ '../../src',
],
- }],
- ],
- 'dependencies': [
- 'mksnapshot#host',
- 'js2c#host',
- 'v8_base',
- ],
- 'include_dirs+': [
- '../../src',
- ],
- 'sources': [
- '<(SHARED_INTERMEDIATE_DIR)/libraries-empty.cc',
- '<(INTERMEDIATE_DIR)/snapshot.cc',
- ],
- 'actions': [
+ 'sources': [
+ '../../src/allocation.cc',
+ '../../src/hashmap.cc',
+ '../../src/preparse-data.cc',
+ '../../src/preparser.cc',
+ '../../src/preparser-api.cc',
+ '../../src/scanner-base.cc',
+ '../../src/token.cc',
+ '../../src/unicode.cc',
+ ],
+ 'conditions': [
+ ['OS=="win" and component=="shared_library"', {
+ 'sources': [ '../../src/v8preparserdll-main.cc' ],
+ 'defines': [ 'BUILDING_V8_SHARED' ],
+ 'direct_dependent_settings': {
+ 'defines': [ 'USING_V8_SHARED' ]
+ },
+ 'type': '<(component)',
+ } , {
+ 'type': 'none'
+ }],
+ ['OS!="win"', {
+ 'type': '<(library)'
+ }],
+ ]
+ },
{
- 'action_name': 'run_mksnapshot',
- 'inputs': [
- '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)mksnapshot<(EXECUTABLE_SUFFIX)',
+ 'target_name': 'v8_snapshot',
+ 'type': '<(library)',
+ 'conditions': [
+ ['OS=="win" and component=="shared_library"', {
+ 'defines': [
+ 'BUILDING_V8_SHARED',
+ ],
+ }],
+ ],
+ 'dependencies': [
+ 'mksnapshot#host',
+ 'js2c#host',
+ 'v8_base',
+ ],
+ 'include_dirs+': [
+ '../../src',
],
- 'outputs': [
+ 'sources': [
+ '<(SHARED_INTERMEDIATE_DIR)/libraries-empty.cc',
'<(INTERMEDIATE_DIR)/snapshot.cc',
],
- 'action': ['<@(_inputs)', '<@(_outputs)'],
+ 'actions': [
+ {
+ 'action_name': 'run_mksnapshot',
+ 'inputs': [
+ '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)mksnapshot<(EXECUTABLE_SUFFIX)',
+ ],
+ 'outputs': [
+ '<(INTERMEDIATE_DIR)/snapshot.cc',
+ ],
+ 'action': ['<@(_inputs)', '<@(_outputs)'],
+ },
+ ],
},
- ],
- },
- {
- 'target_name': 'v8_nosnapshot',
- 'type': '<(library)',
- 'toolsets': ['host', 'target'],
- 'dependencies': [
- 'js2c#host',
- 'v8_base',
- ],
- 'include_dirs+': [
- '../../src',
- ],
- 'sources': [
- '<(SHARED_INTERMEDIATE_DIR)/libraries.cc',
- '../../src/snapshot-empty.cc',
- ],
- 'conditions': [
- # The ARM assembler assumes the host is 32 bits, so force building
- # 32-bit host tools.
- ['v8_target_arch=="arm" and host_arch=="x64" and _toolset=="host"', {
- 'cflags': ['-m32'],
- 'ldflags': ['-m32'],
- }],
- ['OS=="win" and component=="shared_library"', {
- 'defines': [
- 'BUILDING_V8_SHARED',
+ {
+ 'target_name': 'v8_nosnapshot',
+ 'type': '<(library)',
+ 'toolsets': ['host', 'target'],
+ 'dependencies': [
+ 'js2c#host',
+ 'v8_base',
],
- }],
- ]
- },
- {
- 'target_name': 'v8_base',
- 'type': '<(library)',
- 'toolsets': ['host', 'target'],
- 'include_dirs+': [
- '../../src',
- ],
- 'sources': [
- '../../src/accessors.cc',
- '../../src/accessors.h',
- '../../src/allocation.cc',
- '../../src/allocation.h',
- '../../src/api.cc',
- '../../src/api.h',
- '../../src/apiutils.h',
- '../../src/arguments.h',
- '../../src/assembler.cc',
- '../../src/assembler.h',
- '../../src/ast.cc',
- '../../src/ast-inl.h',
- '../../src/ast.h',
- '../../src/atomicops_internals_x86_gcc.cc',
- '../../src/bignum.cc',
- '../../src/bignum.h',
- '../../src/bignum-dtoa.cc',
- '../../src/bignum-dtoa.h',
- '../../src/bootstrapper.cc',
- '../../src/bootstrapper.h',
- '../../src/builtins.cc',
- '../../src/builtins.h',
- '../../src/bytecodes-irregexp.h',
- '../../src/cached-powers.cc',
- '../../src/cached-powers.h',
- '../../src/char-predicates-inl.h',
- '../../src/char-predicates.h',
- '../../src/checks.cc',
- '../../src/checks.h',
- '../../src/circular-queue-inl.h',
- '../../src/circular-queue.cc',
- '../../src/circular-queue.h',
- '../../src/code-stubs.cc',
- '../../src/code-stubs.h',
- '../../src/code.h',
- '../../src/codegen-inl.h',
- '../../src/codegen.cc',
- '../../src/codegen.h',
- '../../src/compilation-cache.cc',
- '../../src/compilation-cache.h',
- '../../src/compiler.cc',
- '../../src/compiler.h',
- '../../src/contexts.cc',
- '../../src/contexts.h',
- '../../src/conversions-inl.h',
- '../../src/conversions.cc',
- '../../src/conversions.h',
- '../../src/counters.cc',
- '../../src/counters.h',
- '../../src/cpu.h',
- '../../src/cpu-profiler-inl.h',
- '../../src/cpu-profiler.cc',
- '../../src/cpu-profiler.h',
- '../../src/data-flow.cc',
- '../../src/data-flow.h',
- '../../src/dateparser.cc',
- '../../src/dateparser.h',
- '../../src/dateparser-inl.h',
- '../../src/debug.cc',
- '../../src/debug.h',
- '../../src/debug-agent.cc',
- '../../src/debug-agent.h',
- '../../src/deoptimizer.cc',
- '../../src/deoptimizer.h',
- '../../src/disasm.h',
- '../../src/disassembler.cc',
- '../../src/disassembler.h',
- '../../src/dtoa.cc',
- '../../src/dtoa.h',
- '../../src/diy-fp.cc',
- '../../src/diy-fp.h',
- '../../src/double.h',
- '../../src/execution.cc',
- '../../src/execution.h',
- '../../src/factory.cc',
- '../../src/factory.h',
- '../../src/fast-dtoa.cc',
- '../../src/fast-dtoa.h',
- '../../src/flag-definitions.h',
- '../../src/fixed-dtoa.cc',
- '../../src/fixed-dtoa.h',
- '../../src/flags.cc',
- '../../src/flags.h',
- '../../src/frame-element.cc',
- '../../src/frame-element.h',
- '../../src/frames-inl.h',
- '../../src/frames.cc',
- '../../src/frames.h',
- '../../src/full-codegen.cc',
- '../../src/full-codegen.h',
- '../../src/func-name-inferrer.cc',
- '../../src/func-name-inferrer.h',
- '../../src/global-handles.cc',
- '../../src/global-handles.h',
- '../../src/globals.h',
- '../../src/handles-inl.h',
- '../../src/handles.cc',
- '../../src/handles.h',
- '../../src/hashmap.cc',
- '../../src/hashmap.h',
- '../../src/heap-inl.h',
- '../../src/heap.cc',
- '../../src/heap.h',
- '../../src/heap-profiler.cc',
- '../../src/heap-profiler.h',
- '../../src/hydrogen.cc',
- '../../src/hydrogen.h',
- '../../src/hydrogen-instructions.cc',
- '../../src/hydrogen-instructions.h',
- '../../src/ic-inl.h',
- '../../src/ic.cc',
- '../../src/ic.h',
- '../../src/interpreter-irregexp.cc',
- '../../src/interpreter-irregexp.h',
- '../../src/jump-target-inl.h',
- '../../src/jump-target.cc',
- '../../src/jump-target.h',
- '../../src/jsregexp.cc',
- '../../src/jsregexp.h',
- '../../src/list-inl.h',
- '../../src/list.h',
- '../../src/lithium-allocator.cc',
- '../../src/lithium-allocator.h',
- '../../src/liveedit.cc',
- '../../src/liveedit.h',
- '../../src/log-inl.h',
- '../../src/log-utils.cc',
- '../../src/log-utils.h',
- '../../src/log.cc',
- '../../src/log.h',
- '../../src/macro-assembler.h',
- '../../src/mark-compact.cc',
- '../../src/mark-compact.h',
- '../../src/memory.h',
- '../../src/messages.cc',
- '../../src/messages.h',
- '../../src/natives.h',
- '../../src/objects-debug.cc',
- '../../src/objects-inl.h',
- '../../src/objects-visiting.cc',
- '../../src/objects-visiting.h',
- '../../src/objects.cc',
- '../../src/objects.h',
- '../../src/oprofile-agent.h',
- '../../src/oprofile-agent.cc',
- '../../src/parser.cc',
- '../../src/parser.h',
- '../../src/platform.h',
- '../../src/preparse-data.cc',
- '../../src/preparse-data.h',
- '../../src/preparser.cc',
- '../../src/preparser.h',
- '../../src/prettyprinter.cc',
- '../../src/prettyprinter.h',
- '../../src/property.cc',
- '../../src/property.h',
- '../../src/profile-generator-inl.h',
- '../../src/profile-generator.cc',
- '../../src/profile-generator.h',
- '../../src/regexp-macro-assembler-irregexp-inl.h',
- '../../src/regexp-macro-assembler-irregexp.cc',
- '../../src/regexp-macro-assembler-irregexp.h',
- '../../src/regexp-macro-assembler-tracer.cc',
- '../../src/regexp-macro-assembler-tracer.h',
- '../../src/regexp-macro-assembler.cc',
- '../../src/regexp-macro-assembler.h',
- '../../src/regexp-stack.cc',
- '../../src/regexp-stack.h',
- '../../src/register-allocator.h',
- '../../src/register-allocator-inl.h',
- '../../src/register-allocator.cc',
- '../../src/rewriter.cc',
- '../../src/rewriter.h',
- '../../src/runtime.cc',
- '../../src/runtime.h',
- '../../src/runtime-profiler.cc',
- '../../src/runtime-profiler.h',
- '../../src/safepoint-table.cc',
- '../../src/safepoint-table.h',
- '../../src/scanner-base.cc',
- '../../src/scanner-base.h',
- '../../src/scanner.cc',
- '../../src/scanner.h',
- '../../src/scopeinfo.cc',
- '../../src/scopeinfo.h',
- '../../src/scopes.cc',
- '../../src/scopes.h',
- '../../src/serialize.cc',
- '../../src/serialize.h',
- '../../src/shell.h',
- '../../src/smart-pointer.h',
- '../../src/snapshot-common.cc',
- '../../src/snapshot.h',
- '../../src/spaces-inl.h',
- '../../src/spaces.cc',
- '../../src/spaces.h',
- '../../src/string-search.cc',
- '../../src/string-search.h',
- '../../src/string-stream.cc',
- '../../src/string-stream.h',
- '../../src/strtod.cc',
- '../../src/strtod.h',
- '../../src/stub-cache.cc',
- '../../src/stub-cache.h',
- '../../src/token.cc',
- '../../src/token.h',
- '../../src/top.cc',
- '../../src/top.h',
- '../../src/type-info.cc',
- '../../src/type-info.h',
- '../../src/unbound-queue-inl.h',
- '../../src/unbound-queue.h',
- '../../src/unicode-inl.h',
- '../../src/unicode.cc',
- '../../src/unicode.h',
- '../../src/utils.cc',
- '../../src/utils.h',
- '../../src/v8-counters.cc',
- '../../src/v8-counters.h',
- '../../src/v8.cc',
- '../../src/v8.h',
- '../../src/v8checks.h',
- '../../src/v8globals.h',
- '../../src/v8threads.cc',
- '../../src/v8threads.h',
- '../../src/v8utils.h',
- '../../src/variables.cc',
- '../../src/variables.h',
- '../../src/version.cc',
- '../../src/version.h',
- '../../src/virtual-frame-inl.h',
- '../../src/virtual-frame.cc',
- '../../src/virtual-frame.h',
- '../../src/vm-state-inl.h',
- '../../src/vm-state.h',
- '../../src/zone-inl.h',
- '../../src/zone.cc',
- '../../src/zone.h',
- '../../src/extensions/externalize-string-extension.cc',
- '../../src/extensions/externalize-string-extension.h',
- '../../src/extensions/gc-extension.cc',
- '../../src/extensions/gc-extension.h',
- ],
- 'conditions': [
- ['v8_target_arch=="arm"', {
'include_dirs+': [
- '../../src/arm',
+ '../../src',
],
'sources': [
- '../../src/jump-target-light.h',
- '../../src/jump-target-light-inl.h',
- '../../src/jump-target-light.cc',
- '../../src/virtual-frame-light-inl.h',
- '../../src/virtual-frame-light.cc',
- '../../src/arm/assembler-arm-inl.h',
- '../../src/arm/assembler-arm.cc',
- '../../src/arm/assembler-arm.h',
- '../../src/arm/builtins-arm.cc',
- '../../src/arm/code-stubs-arm.cc',
- '../../src/arm/code-stubs-arm.h',
- '../../src/arm/codegen-arm.cc',
- '../../src/arm/codegen-arm.h',
- '../../src/arm/constants-arm.h',
- '../../src/arm/constants-arm.cc',
- '../../src/arm/cpu-arm.cc',
- '../../src/arm/debug-arm.cc',
- '../../src/arm/deoptimizer-arm.cc',
- '../../src/arm/disasm-arm.cc',
- '../../src/arm/frames-arm.cc',
- '../../src/arm/frames-arm.h',
- '../../src/arm/full-codegen-arm.cc',
- '../../src/arm/ic-arm.cc',
- '../../src/arm/jump-target-arm.cc',
- '../../src/arm/lithium-codegen-arm.cc',
- '../../src/arm/lithium-codegen-arm.h',
- '../../src/arm/lithium-arm.cc',
- '../../src/arm/lithium-arm.h',
- '../../src/arm/macro-assembler-arm.cc',
- '../../src/arm/macro-assembler-arm.h',
- '../../src/arm/regexp-macro-assembler-arm.cc',
- '../../src/arm/regexp-macro-assembler-arm.h',
- '../../src/arm/register-allocator-arm.cc',
- '../../src/arm/simulator-arm.cc',
- '../../src/arm/stub-cache-arm.cc',
- '../../src/arm/virtual-frame-arm-inl.h',
- '../../src/arm/virtual-frame-arm.cc',
- '../../src/arm/virtual-frame-arm.h',
+ '<(SHARED_INTERMEDIATE_DIR)/libraries.cc',
+ '../../src/snapshot-empty.cc',
],
'conditions': [
# The ARM assembler assumes the host is 32 bits, so force building
# 32-bit host tools.
- ['host_arch=="x64" and _toolset=="host"', {
+ ['v8_target_arch=="arm" and host_arch=="x64" and _toolset=="host"', {
'cflags': ['-m32'],
'ldflags': ['-m32'],
- }]
+ }],
+ ['OS=="win" and component=="shared_library"', {
+ 'defines': [
+ 'BUILDING_V8_SHARED',
+ ],
+ }],
]
- }],
- ['v8_target_arch=="ia32" or v8_target_arch=="mac" or OS=="mac"', {
- 'include_dirs+': [
- '../../src/ia32',
- ],
- 'sources': [
- '../../src/jump-target-heavy.h',
- '../../src/jump-target-heavy-inl.h',
- '../../src/jump-target-heavy.cc',
- '../../src/virtual-frame-heavy-inl.h',
- '../../src/virtual-frame-heavy.cc',
- '../../src/ia32/assembler-ia32-inl.h',
- '../../src/ia32/assembler-ia32.cc',
- '../../src/ia32/assembler-ia32.h',
- '../../src/ia32/builtins-ia32.cc',
- '../../src/ia32/code-stubs-ia32.cc',
- '../../src/ia32/code-stubs-ia32.h',
- '../../src/ia32/codegen-ia32.cc',
- '../../src/ia32/codegen-ia32.h',
- '../../src/ia32/cpu-ia32.cc',
- '../../src/ia32/debug-ia32.cc',
- '../../src/ia32/deoptimizer-ia32.cc',
- '../../src/ia32/disasm-ia32.cc',
- '../../src/ia32/frames-ia32.cc',
- '../../src/ia32/frames-ia32.h',
- '../../src/ia32/full-codegen-ia32.cc',
- '../../src/ia32/ic-ia32.cc',
- '../../src/ia32/jump-target-ia32.cc',
- '../../src/ia32/lithium-codegen-ia32.cc',
- '../../src/ia32/lithium-codegen-ia32.h',
- '../../src/ia32/lithium-ia32.cc',
- '../../src/ia32/lithium-ia32.h',
- '../../src/ia32/macro-assembler-ia32.cc',
- '../../src/ia32/macro-assembler-ia32.h',
- '../../src/ia32/regexp-macro-assembler-ia32.cc',
- '../../src/ia32/regexp-macro-assembler-ia32.h',
- '../../src/ia32/register-allocator-ia32.cc',
- '../../src/ia32/stub-cache-ia32.cc',
- '../../src/ia32/virtual-frame-ia32.cc',
- '../../src/ia32/virtual-frame-ia32.h',
- ],
- }],
- ['v8_target_arch=="x64" or v8_target_arch=="mac" or OS=="mac"', {
+ },
+ {
+ 'target_name': 'v8_base',
+ 'type': '<(library)',
+ 'toolsets': ['host', 'target'],
'include_dirs+': [
- '../../src/x64',
+ '../../src',
],
'sources': [
- '../../src/jump-target-heavy.h',
- '../../src/jump-target-heavy-inl.h',
- '../../src/jump-target-heavy.cc',
- '../../src/virtual-frame-heavy-inl.h',
- '../../src/virtual-frame-heavy.cc',
- '../../src/x64/assembler-x64-inl.h',
- '../../src/x64/assembler-x64.cc',
- '../../src/x64/assembler-x64.h',
- '../../src/x64/builtins-x64.cc',
- '../../src/x64/code-stubs-x64.cc',
- '../../src/x64/code-stubs-x64.h',
- '../../src/x64/codegen-x64.cc',
- '../../src/x64/codegen-x64.h',
- '../../src/x64/cpu-x64.cc',
- '../../src/x64/debug-x64.cc',
- '../../src/x64/deoptimizer-x64.cc',
- '../../src/x64/disasm-x64.cc',
- '../../src/x64/frames-x64.cc',
- '../../src/x64/frames-x64.h',
- '../../src/x64/full-codegen-x64.cc',
- '../../src/x64/ic-x64.cc',
- '../../src/x64/jump-target-x64.cc',
- '../../src/x64/macro-assembler-x64.cc',
- '../../src/x64/macro-assembler-x64.h',
- '../../src/x64/regexp-macro-assembler-x64.cc',
- '../../src/x64/regexp-macro-assembler-x64.h',
- '../../src/x64/register-allocator-x64.cc',
- '../../src/x64/stub-cache-x64.cc',
- '../../src/x64/virtual-frame-x64.cc',
- '../../src/x64/virtual-frame-x64.h',
+ '../../src/accessors.cc',
+ '../../src/accessors.h',
+ '../../src/allocation.cc',
+ '../../src/allocation.h',
+ '../../src/api.cc',
+ '../../src/api.h',
+ '../../src/apiutils.h',
+ '../../src/arguments.h',
+ '../../src/assembler.cc',
+ '../../src/assembler.h',
+ '../../src/ast.cc',
+ '../../src/ast-inl.h',
+ '../../src/ast.h',
+ '../../src/atomicops_internals_x86_gcc.cc',
+ '../../src/bignum.cc',
+ '../../src/bignum.h',
+ '../../src/bignum-dtoa.cc',
+ '../../src/bignum-dtoa.h',
+ '../../src/bootstrapper.cc',
+ '../../src/bootstrapper.h',
+ '../../src/builtins.cc',
+ '../../src/builtins.h',
+ '../../src/bytecodes-irregexp.h',
+ '../../src/cached-powers.cc',
+ '../../src/cached-powers.h',
+ '../../src/char-predicates-inl.h',
+ '../../src/char-predicates.h',
+ '../../src/checks.cc',
+ '../../src/checks.h',
+ '../../src/circular-queue-inl.h',
+ '../../src/circular-queue.cc',
+ '../../src/circular-queue.h',
+ '../../src/code-stubs.cc',
+ '../../src/code-stubs.h',
+ '../../src/code.h',
+ '../../src/codegen-inl.h',
+ '../../src/codegen.cc',
+ '../../src/codegen.h',
+ '../../src/compilation-cache.cc',
+ '../../src/compilation-cache.h',
+ '../../src/compiler.cc',
+ '../../src/compiler.h',
+ '../../src/contexts.cc',
+ '../../src/contexts.h',
+ '../../src/conversions-inl.h',
+ '../../src/conversions.cc',
+ '../../src/conversions.h',
+ '../../src/counters.cc',
+ '../../src/counters.h',
+ '../../src/cpu.h',
+ '../../src/cpu-profiler-inl.h',
+ '../../src/cpu-profiler.cc',
+ '../../src/cpu-profiler.h',
+ '../../src/data-flow.cc',
+ '../../src/data-flow.h',
+ '../../src/dateparser.cc',
+ '../../src/dateparser.h',
+ '../../src/dateparser-inl.h',
+ '../../src/debug.cc',
+ '../../src/debug.h',
+ '../../src/debug-agent.cc',
+ '../../src/debug-agent.h',
+ '../../src/deoptimizer.cc',
+ '../../src/deoptimizer.h',
+ '../../src/disasm.h',
+ '../../src/disassembler.cc',
+ '../../src/disassembler.h',
+ '../../src/dtoa.cc',
+ '../../src/dtoa.h',
+ '../../src/diy-fp.cc',
+ '../../src/diy-fp.h',
+ '../../src/double.h',
+ '../../src/execution.cc',
+ '../../src/execution.h',
+ '../../src/factory.cc',
+ '../../src/factory.h',
+ '../../src/fast-dtoa.cc',
+ '../../src/fast-dtoa.h',
+ '../../src/flag-definitions.h',
+ '../../src/fixed-dtoa.cc',
+ '../../src/fixed-dtoa.h',
+ '../../src/flags.cc',
+ '../../src/flags.h',
+ '../../src/frame-element.cc',
+ '../../src/frame-element.h',
+ '../../src/frames-inl.h',
+ '../../src/frames.cc',
+ '../../src/frames.h',
+ '../../src/full-codegen.cc',
+ '../../src/full-codegen.h',
+ '../../src/func-name-inferrer.cc',
+ '../../src/func-name-inferrer.h',
+ '../../src/global-handles.cc',
+ '../../src/global-handles.h',
+ '../../src/globals.h',
+ '../../src/handles-inl.h',
+ '../../src/handles.cc',
+ '../../src/handles.h',
+ '../../src/hashmap.cc',
+ '../../src/hashmap.h',
+ '../../src/heap-inl.h',
+ '../../src/heap.cc',
+ '../../src/heap.h',
+ '../../src/heap-profiler.cc',
+ '../../src/heap-profiler.h',
+ '../../src/hydrogen.cc',
+ '../../src/hydrogen.h',
+ '../../src/hydrogen-instructions.cc',
+ '../../src/hydrogen-instructions.h',
+ '../../src/ic-inl.h',
+ '../../src/ic.cc',
+ '../../src/ic.h',
+ '../../src/interpreter-irregexp.cc',
+ '../../src/interpreter-irregexp.h',
+ '../../src/jump-target-inl.h',
+ '../../src/jump-target.cc',
+ '../../src/jump-target.h',
+ '../../src/jsregexp.cc',
+ '../../src/jsregexp.h',
+ '../../src/list-inl.h',
+ '../../src/list.h',
+ '../../src/lithium-allocator.cc',
+ '../../src/lithium-allocator.h',
+ '../../src/liveedit.cc',
+ '../../src/liveedit.h',
+ '../../src/log-inl.h',
+ '../../src/log-utils.cc',
+ '../../src/log-utils.h',
+ '../../src/log.cc',
+ '../../src/log.h',
+ '../../src/macro-assembler.h',
+ '../../src/mark-compact.cc',
+ '../../src/mark-compact.h',
+ '../../src/memory.h',
+ '../../src/messages.cc',
+ '../../src/messages.h',
+ '../../src/natives.h',
+ '../../src/objects-debug.cc',
+ '../../src/objects-printer.cc',
+ '../../src/objects-inl.h',
+ '../../src/objects-visiting.cc',
+ '../../src/objects-visiting.h',
+ '../../src/objects.cc',
+ '../../src/objects.h',
+ '../../src/oprofile-agent.h',
+ '../../src/oprofile-agent.cc',
+ '../../src/parser.cc',
+ '../../src/parser.h',
+ '../../src/platform.h',
+ '../../src/preparse-data.cc',
+ '../../src/preparse-data.h',
+ '../../src/preparser.cc',
+ '../../src/preparser.h',
+ '../../src/prettyprinter.cc',
+ '../../src/prettyprinter.h',
+ '../../src/property.cc',
+ '../../src/property.h',
+ '../../src/profile-generator-inl.h',
+ '../../src/profile-generator.cc',
+ '../../src/profile-generator.h',
+ '../../src/regexp-macro-assembler-irregexp-inl.h',
+ '../../src/regexp-macro-assembler-irregexp.cc',
+ '../../src/regexp-macro-assembler-irregexp.h',
+ '../../src/regexp-macro-assembler-tracer.cc',
+ '../../src/regexp-macro-assembler-tracer.h',
+ '../../src/regexp-macro-assembler.cc',
+ '../../src/regexp-macro-assembler.h',
+ '../../src/regexp-stack.cc',
+ '../../src/regexp-stack.h',
+ '../../src/register-allocator.h',
+ '../../src/register-allocator-inl.h',
+ '../../src/register-allocator.cc',
+ '../../src/rewriter.cc',
+ '../../src/rewriter.h',
+ '../../src/runtime.cc',
+ '../../src/runtime.h',
+ '../../src/runtime-profiler.cc',
+ '../../src/runtime-profiler.h',
+ '../../src/safepoint-table.cc',
+ '../../src/safepoint-table.h',
+ '../../src/scanner-base.cc',
+ '../../src/scanner-base.h',
+ '../../src/scanner.cc',
+ '../../src/scanner.h',
+ '../../src/scopeinfo.cc',
+ '../../src/scopeinfo.h',
+ '../../src/scopes.cc',
+ '../../src/scopes.h',
+ '../../src/serialize.cc',
+ '../../src/serialize.h',
+ '../../src/shell.h',
+ '../../src/smart-pointer.h',
+ '../../src/snapshot-common.cc',
+ '../../src/snapshot.h',
+ '../../src/spaces-inl.h',
+ '../../src/spaces.cc',
+ '../../src/spaces.h',
+ '../../src/string-search.cc',
+ '../../src/string-search.h',
+ '../../src/string-stream.cc',
+ '../../src/string-stream.h',
+ '../../src/strtod.cc',
+ '../../src/strtod.h',
+ '../../src/stub-cache.cc',
+ '../../src/stub-cache.h',
+ '../../src/token.cc',
+ '../../src/token.h',
+ '../../src/top.cc',
+ '../../src/top.h',
+ '../../src/type-info.cc',
+ '../../src/type-info.h',
+ '../../src/unbound-queue-inl.h',
+ '../../src/unbound-queue.h',
+ '../../src/unicode-inl.h',
+ '../../src/unicode.cc',
+ '../../src/unicode.h',
+ '../../src/utils.cc',
+ '../../src/utils.h',
+ '../../src/v8-counters.cc',
+ '../../src/v8-counters.h',
+ '../../src/v8.cc',
+ '../../src/v8.h',
+ '../../src/v8checks.h',
+ '../../src/v8globals.h',
+ '../../src/v8threads.cc',
+ '../../src/v8threads.h',
+ '../../src/v8utils.h',
+ '../../src/variables.cc',
+ '../../src/variables.h',
+ '../../src/version.cc',
+ '../../src/version.h',
+ '../../src/virtual-frame-inl.h',
+ '../../src/virtual-frame.cc',
+ '../../src/virtual-frame.h',
+ '../../src/vm-state-inl.h',
+ '../../src/vm-state.h',
+ '../../src/zone-inl.h',
+ '../../src/zone.cc',
+ '../../src/zone.h',
+ '../../src/extensions/externalize-string-extension.cc',
+ '../../src/extensions/externalize-string-extension.h',
+ '../../src/extensions/gc-extension.cc',
+ '../../src/extensions/gc-extension.h',
],
- }],
- ['OS=="linux"', {
- 'link_settings': {
- 'libraries': [
- # Needed for clock_gettime() used by src/platform-linux.cc.
- '-lrt',
- ]},
- 'sources': [
- '../../src/platform-linux.cc',
- '../../src/platform-posix.cc'
+ 'conditions': [
+ ['v8_target_arch=="arm"', {
+ 'include_dirs+': [
+ '../../src/arm',
+ ],
+ 'sources': [
+ '../../src/jump-target-light.h',
+ '../../src/jump-target-light-inl.h',
+ '../../src/jump-target-light.cc',
+ '../../src/virtual-frame-light-inl.h',
+ '../../src/virtual-frame-light.cc',
+ '../../src/arm/assembler-arm-inl.h',
+ '../../src/arm/assembler-arm.cc',
+ '../../src/arm/assembler-arm.h',
+ '../../src/arm/builtins-arm.cc',
+ '../../src/arm/code-stubs-arm.cc',
+ '../../src/arm/code-stubs-arm.h',
+ '../../src/arm/codegen-arm.cc',
+ '../../src/arm/codegen-arm.h',
+ '../../src/arm/constants-arm.h',
+ '../../src/arm/constants-arm.cc',
+ '../../src/arm/cpu-arm.cc',
+ '../../src/arm/debug-arm.cc',
+ '../../src/arm/deoptimizer-arm.cc',
+ '../../src/arm/disasm-arm.cc',
+ '../../src/arm/frames-arm.cc',
+ '../../src/arm/frames-arm.h',
+ '../../src/arm/full-codegen-arm.cc',
+ '../../src/arm/ic-arm.cc',
+ '../../src/arm/jump-target-arm.cc',
+ '../../src/arm/lithium-codegen-arm.cc',
+ '../../src/arm/lithium-codegen-arm.h',
+ '../../src/arm/lithium-arm.cc',
+ '../../src/arm/lithium-arm.h',
+ '../../src/arm/macro-assembler-arm.cc',
+ '../../src/arm/macro-assembler-arm.h',
+ '../../src/arm/regexp-macro-assembler-arm.cc',
+ '../../src/arm/regexp-macro-assembler-arm.h',
+ '../../src/arm/register-allocator-arm.cc',
+ '../../src/arm/simulator-arm.cc',
+ '../../src/arm/stub-cache-arm.cc',
+ '../../src/arm/virtual-frame-arm-inl.h',
+ '../../src/arm/virtual-frame-arm.cc',
+ '../../src/arm/virtual-frame-arm.h',
+ ],
+ 'conditions': [
+ # The ARM assembler assumes the host is 32 bits,
+ # so force building 32-bit host tools.
+ ['host_arch=="x64" and _toolset=="host"', {
+ 'cflags': ['-m32'],
+ 'ldflags': ['-m32'],
+ }]
+ ]
+ }],
+ ['v8_target_arch=="ia32" or v8_target_arch=="mac" or OS=="mac"', {
+ 'include_dirs+': [
+ '../../src/ia32',
+ ],
+ 'sources': [
+ '../../src/jump-target-heavy.h',
+ '../../src/jump-target-heavy-inl.h',
+ '../../src/jump-target-heavy.cc',
+ '../../src/virtual-frame-heavy-inl.h',
+ '../../src/virtual-frame-heavy.cc',
+ '../../src/ia32/assembler-ia32-inl.h',
+ '../../src/ia32/assembler-ia32.cc',
+ '../../src/ia32/assembler-ia32.h',
+ '../../src/ia32/builtins-ia32.cc',
+ '../../src/ia32/code-stubs-ia32.cc',
+ '../../src/ia32/code-stubs-ia32.h',
+ '../../src/ia32/codegen-ia32.cc',
+ '../../src/ia32/codegen-ia32.h',
+ '../../src/ia32/cpu-ia32.cc',
+ '../../src/ia32/debug-ia32.cc',
+ '../../src/ia32/deoptimizer-ia32.cc',
+ '../../src/ia32/disasm-ia32.cc',
+ '../../src/ia32/frames-ia32.cc',
+ '../../src/ia32/frames-ia32.h',
+ '../../src/ia32/full-codegen-ia32.cc',
+ '../../src/ia32/ic-ia32.cc',
+ '../../src/ia32/jump-target-ia32.cc',
+ '../../src/ia32/lithium-codegen-ia32.cc',
+ '../../src/ia32/lithium-codegen-ia32.h',
+ '../../src/ia32/lithium-ia32.cc',
+ '../../src/ia32/lithium-ia32.h',
+ '../../src/ia32/macro-assembler-ia32.cc',
+ '../../src/ia32/macro-assembler-ia32.h',
+ '../../src/ia32/regexp-macro-assembler-ia32.cc',
+ '../../src/ia32/regexp-macro-assembler-ia32.h',
+ '../../src/ia32/register-allocator-ia32.cc',
+ '../../src/ia32/stub-cache-ia32.cc',
+ '../../src/ia32/virtual-frame-ia32.cc',
+ '../../src/ia32/virtual-frame-ia32.h',
+ ],
+ }],
+ ['v8_target_arch=="x64" or v8_target_arch=="mac" or OS=="mac"', {
+ 'include_dirs+': [
+ '../../src/x64',
+ ],
+ 'sources': [
+ '../../src/jump-target-heavy.h',
+ '../../src/jump-target-heavy-inl.h',
+ '../../src/jump-target-heavy.cc',
+ '../../src/virtual-frame-heavy-inl.h',
+ '../../src/virtual-frame-heavy.cc',
+ '../../src/x64/assembler-x64-inl.h',
+ '../../src/x64/assembler-x64.cc',
+ '../../src/x64/assembler-x64.h',
+ '../../src/x64/builtins-x64.cc',
+ '../../src/x64/code-stubs-x64.cc',
+ '../../src/x64/code-stubs-x64.h',
+ '../../src/x64/codegen-x64.cc',
+ '../../src/x64/codegen-x64.h',
+ '../../src/x64/cpu-x64.cc',
+ '../../src/x64/debug-x64.cc',
+ '../../src/x64/deoptimizer-x64.cc',
+ '../../src/x64/disasm-x64.cc',
+ '../../src/x64/frames-x64.cc',
+ '../../src/x64/frames-x64.h',
+ '../../src/x64/full-codegen-x64.cc',
+ '../../src/x64/ic-x64.cc',
+ '../../src/x64/jump-target-x64.cc',
+ '../../src/x64/macro-assembler-x64.cc',
+ '../../src/x64/macro-assembler-x64.h',
+ '../../src/x64/regexp-macro-assembler-x64.cc',
+ '../../src/x64/regexp-macro-assembler-x64.h',
+ '../../src/x64/register-allocator-x64.cc',
+ '../../src/x64/stub-cache-x64.cc',
+ '../../src/x64/virtual-frame-x64.cc',
+ '../../src/x64/virtual-frame-x64.h',
+ ],
+ }],
+ ['OS=="linux"', {
+ 'link_settings': {
+ 'libraries': [
+ # Needed for clock_gettime() used by src/platform-linux.cc.
+ '-lrt',
+ ]},
+ 'sources': [
+ '../../src/platform-linux.cc',
+ '../../src/platform-posix.cc'
+ ],
+ }
],
- }
- ],
- ['OS=="freebsd"', {
- 'link_settings': {
- 'libraries': [
- '-L/usr/local/lib -lexecinfo',
- ]},
- 'sources': [
- '../../src/platform-freebsd.cc',
- '../../src/platform-posix.cc'
+ ['OS=="freebsd"', {
+ 'link_settings': {
+ 'libraries': [
+ '-L/usr/local/lib -lexecinfo',
+ ]},
+ 'sources': [
+ '../../src/platform-freebsd.cc',
+ '../../src/platform-posix.cc'
+ ],
+ }
],
- }
- ],
- ['OS=="openbsd"', {
- 'link_settings': {
- 'libraries': [
- '-L/usr/local/lib -lexecinfo',
- ]},
- 'sources': [
- '../../src/platform-openbsd.cc',
- '../../src/platform-posix.cc'
+ ['OS=="openbsd"', {
+ 'link_settings': {
+ 'libraries': [
+ '-L/usr/local/lib -lexecinfo',
+ ]},
+ 'sources': [
+ '../../src/platform-openbsd.cc',
+ '../../src/platform-posix.cc'
+ ],
+ }
],
- }
- ],
- ['OS=="mac"', {
- 'sources': [
- '../../src/platform-macos.cc',
- '../../src/platform-posix.cc'
- ]},
- ],
- ['OS=="win"', {
- 'sources': [
- '../../src/platform-win32.cc',
+ ['OS=="mac"', {
+ 'sources': [
+ '../../src/platform-macos.cc',
+ '../../src/platform-posix.cc'
+ ]},
+ ],
+ ['OS=="win"', {
+ 'sources': [
+ '../../src/platform-win32.cc',
+ ],
+ # 4355, 4800 came from common.vsprops
+ 'msvs_disabled_warnings': [4355, 4800],
+ 'link_settings': {
+ 'libraries': [ '-lwinmm.lib' ],
+ },
+ }],
+ ['OS=="win" and component=="shared_library"', {
+ 'defines': [
+ 'BUILDING_V8_SHARED'
+ ],
+ }],
],
- # 4355, 4800 came from common.vsprops
- 'msvs_disabled_warnings': [4355, 4800],
- 'link_settings': {
- 'libraries': [ '-lwinmm.lib' ],
+ },
+ {
+ 'target_name': 'js2c',
+ 'type': 'none',
+ 'toolsets': ['host'],
+ 'variables': {
+ 'library_files': [
+ '../../src/runtime.js',
+ '../../src/v8natives.js',
+ '../../src/array.js',
+ '../../src/string.js',
+ '../../src/uri.js',
+ '../../src/math.js',
+ '../../src/messages.js',
+ '../../src/apinatives.js',
+ '../../src/debug-debugger.js',
+ '../../src/mirror-debugger.js',
+ '../../src/liveedit-debugger.js',
+ '../../src/date.js',
+ '../../src/json.js',
+ '../../src/regexp.js',
+ '../../src/macros.py',
+ ],
},
- }],
- ['OS=="win" and component=="shared_library"', {
- 'defines': [
- 'BUILDING_V8_SHARED'
+ 'actions': [
+ {
+ 'action_name': 'js2c',
+ 'inputs': [
+ '../../tools/js2c.py',
+ '<@(library_files)',
+ ],
+ 'outputs': [
+ '<(SHARED_INTERMEDIATE_DIR)/libraries.cc',
+ '<(SHARED_INTERMEDIATE_DIR)/libraries-empty.cc',
+ ],
+ 'action': [
+ 'python',
+ '../../tools/js2c.py',
+ '<@(_outputs)',
+ 'CORE',
+ '<@(library_files)'
+ ],
+ },
],
- }],
- ],
- },
- {
- 'target_name': 'js2c',
- 'type': 'none',
- 'toolsets': ['host'],
- 'variables': {
- 'library_files': [
- '../../src/runtime.js',
- '../../src/v8natives.js',
- '../../src/array.js',
- '../../src/string.js',
- '../../src/uri.js',
- '../../src/math.js',
- '../../src/messages.js',
- '../../src/apinatives.js',
- '../../src/debug-debugger.js',
- '../../src/mirror-debugger.js',
- '../../src/liveedit-debugger.js',
- '../../src/date.js',
- '../../src/json.js',
- '../../src/regexp.js',
- '../../src/macros.py',
- ],
- },
- 'actions': [
+ },
{
- 'action_name': 'js2c',
- 'inputs': [
- '../../tools/js2c.py',
- '<@(library_files)',
+ 'target_name': 'mksnapshot',
+ 'type': 'executable',
+ 'toolsets': ['host'],
+ 'dependencies': [
+ 'v8_nosnapshot',
],
- 'outputs': [
- '<(SHARED_INTERMEDIATE_DIR)/libraries.cc',
- '<(SHARED_INTERMEDIATE_DIR)/libraries-empty.cc',
+ 'include_dirs+': [
+ '../../src',
],
- 'action': [
- 'python',
- '../../tools/js2c.py',
- '<@(_outputs)',
- 'CORE',
- '<@(library_files)'
+ 'sources': [
+ '../../src/mksnapshot.cc',
+ ],
+ 'conditions': [
+ # The ARM assembler assumes the host is 32 bits, so force building
+ # 32-bit host tools.
+ ['v8_target_arch=="arm" and host_arch=="x64" and _toolset=="host"', {
+ 'cflags': ['-m32'],
+ 'ldflags': ['-m32'],
+ }]
+ ]
+ },
+ {
+ 'target_name': 'v8_shell',
+ 'type': 'executable',
+ 'dependencies': [
+ 'v8'
+ ],
+ 'sources': [
+ '../../samples/shell.cc',
+ ],
+ 'conditions': [
+ ['OS=="win"', {
+ # This could be gotten by not setting chromium_code, if that's OK.
+ 'defines': ['_CRT_SECURE_NO_WARNINGS'],
+ }],
],
},
],
- },
- {
- 'target_name': 'mksnapshot',
- 'type': 'executable',
- 'toolsets': ['host'],
- 'dependencies': [
- 'v8_nosnapshot',
- ],
- 'include_dirs+': [
- '../../src',
- ],
- 'sources': [
- '../../src/mksnapshot.cc',
- ],
- 'conditions': [
- # The ARM assembler assumes the host is 32 bits, so force building
- # 32-bit host tools.
- ['v8_target_arch=="arm" and host_arch=="x64" and _toolset=="host"', {
- 'cflags': ['-m32'],
- 'ldflags': ['-m32'],
- }]
- ]
- },
- {
- 'target_name': 'v8_shell',
- 'type': 'executable',
- 'dependencies': [
- 'v8'
- ],
- 'sources': [
- '../../samples/shell.cc',
- ],
- 'conditions': [
- ['OS=="win"', {
- # This could be gotten by not setting chromium_code, if that's OK.
- 'defines': ['_CRT_SECURE_NO_WARNINGS'],
- }],
+ }, { # use_system_v8 != 0
+ 'targets': [
+ {
+ 'target_name': 'v8',
+ 'type': 'settings',
+ 'link_settings': {
+ 'libraries': [
+ '-lv8',
+ ],
+ },
+ },
+ {
+ 'target_name': 'v8_shell',
+ 'type': 'none',
+ 'dependencies': [
+ 'v8'
+ ],
+ },
],
- },
+ }],
],
}
diff --git a/tools/v8.xcodeproj/project.pbxproj b/tools/v8.xcodeproj/project.pbxproj
index 5254c6e6..80a845cb 100644
--- a/tools/v8.xcodeproj/project.pbxproj
+++ b/tools/v8.xcodeproj/project.pbxproj
@@ -59,7 +59,6 @@
893E24AD12B14B3D0083370F /* hydrogen.cc in Sources */ = {isa = PBXBuildFile; fileRef = 893E248F12B14B3D0083370F /* hydrogen.cc */; };
893E24AE12B14B3D0083370F /* lithium-allocator.cc in Sources */ = {isa = PBXBuildFile; fileRef = 893E249312B14B3D0083370F /* lithium-allocator.cc */; };
893E24AF12B14B3D0083370F /* preparse-data.cc in Sources */ = {isa = PBXBuildFile; fileRef = 893E249512B14B3D0083370F /* preparse-data.cc */; };
- 893E24B012B14B3D0083370F /* preparser-api.cc in Sources */ = {isa = PBXBuildFile; fileRef = 893E249712B14B3D0083370F /* preparser-api.cc */; };
893E24B112B14B3D0083370F /* preparser.cc in Sources */ = {isa = PBXBuildFile; fileRef = 893E249812B14B3D0083370F /* preparser.cc */; };
893E24B212B14B3D0083370F /* runtime-profiler.cc in Sources */ = {isa = PBXBuildFile; fileRef = 893E249A12B14B3D0083370F /* runtime-profiler.cc */; };
893E24B312B14B3D0083370F /* safepoint-table.cc in Sources */ = {isa = PBXBuildFile; fileRef = 893E249C12B14B3D0083370F /* safepoint-table.cc */; };
@@ -74,7 +73,6 @@
893E24BC12B14B3D0083370F /* hydrogen.cc in Sources */ = {isa = PBXBuildFile; fileRef = 893E248F12B14B3D0083370F /* hydrogen.cc */; };
893E24BD12B14B3D0083370F /* lithium-allocator.cc in Sources */ = {isa = PBXBuildFile; fileRef = 893E249312B14B3D0083370F /* lithium-allocator.cc */; };
893E24BE12B14B3D0083370F /* preparse-data.cc in Sources */ = {isa = PBXBuildFile; fileRef = 893E249512B14B3D0083370F /* preparse-data.cc */; };
- 893E24BF12B14B3D0083370F /* preparser-api.cc in Sources */ = {isa = PBXBuildFile; fileRef = 893E249712B14B3D0083370F /* preparser-api.cc */; };
893E24C012B14B3D0083370F /* preparser.cc in Sources */ = {isa = PBXBuildFile; fileRef = 893E249812B14B3D0083370F /* preparser.cc */; };
893E24C112B14B3D0083370F /* runtime-profiler.cc in Sources */ = {isa = PBXBuildFile; fileRef = 893E249A12B14B3D0083370F /* runtime-profiler.cc */; };
893E24C212B14B3D0083370F /* safepoint-table.cc in Sources */ = {isa = PBXBuildFile; fileRef = 893E249C12B14B3D0083370F /* safepoint-table.cc */; };
@@ -94,6 +92,8 @@
8944AD100F1D4D500028D560 /* regexp-stack.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8944AD0E0F1D4D3A0028D560 /* regexp-stack.cc */; };
8944AD110F1D4D570028D560 /* regexp-stack.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8944AD0E0F1D4D3A0028D560 /* regexp-stack.cc */; };
894599A30F5D8729008DA8FB /* debug-agent.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8956B6CD0F5D86570033B5A2 /* debug-agent.cc */; };
+ 8946827512C26EB700C914BC /* objects-printer.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8946827412C26EB700C914BC /* objects-printer.cc */; };
+ 8946827612C26EB700C914BC /* objects-printer.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8946827412C26EB700C914BC /* objects-printer.cc */; };
89495E480E79FC23001F68C3 /* compilation-cache.cc in Sources */ = {isa = PBXBuildFile; fileRef = 89495E460E79FC23001F68C3 /* compilation-cache.cc */; };
89495E490E79FC23001F68C3 /* compilation-cache.cc in Sources */ = {isa = PBXBuildFile; fileRef = 89495E460E79FC23001F68C3 /* compilation-cache.cc */; };
8956B6CF0F5D86730033B5A2 /* debug-agent.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8956B6CD0F5D86570033B5A2 /* debug-agent.cc */; };
@@ -412,7 +412,6 @@
893E249412B14B3D0083370F /* lithium-allocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "lithium-allocator.h"; sourceTree = "<group>"; };
893E249512B14B3D0083370F /* preparse-data.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "preparse-data.cc"; sourceTree = "<group>"; };
893E249612B14B3D0083370F /* preparse-data.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "preparse-data.h"; sourceTree = "<group>"; };
- 893E249712B14B3D0083370F /* preparser-api.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "preparser-api.cc"; sourceTree = "<group>"; };
893E249812B14B3D0083370F /* preparser.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = preparser.cc; sourceTree = "<group>"; };
893E249912B14B3D0083370F /* preparser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = preparser.h; sourceTree = "<group>"; };
893E249A12B14B3D0083370F /* runtime-profiler.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "runtime-profiler.cc"; sourceTree = "<group>"; };
@@ -447,6 +446,7 @@
893E24DB12B14B9F0083370F /* gc-extension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "gc-extension.h"; path = "extensions/gc-extension.h"; sourceTree = "<group>"; };
8944AD0E0F1D4D3A0028D560 /* regexp-stack.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "regexp-stack.cc"; sourceTree = "<group>"; };
8944AD0F0F1D4D3A0028D560 /* regexp-stack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "regexp-stack.h"; sourceTree = "<group>"; };
+ 8946827412C26EB700C914BC /* objects-printer.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "objects-printer.cc"; sourceTree = "<group>"; };
89471C7F0EB23EE400B6874B /* flag-definitions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "flag-definitions.h"; sourceTree = "<group>"; };
89495E460E79FC23001F68C3 /* compilation-cache.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "compilation-cache.cc"; sourceTree = "<group>"; };
89495E470E79FC23001F68C3 /* compilation-cache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "compilation-cache.h"; sourceTree = "<group>"; };
@@ -467,8 +467,6 @@
897F767A0E71B4CC007ACF34 /* v8_shell */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = v8_shell; sourceTree = BUILT_PRODUCTS_DIR; };
897FF0D40E719A8500D62E90 /* v8-debug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "v8-debug.h"; sourceTree = "<group>"; };
897FF0D50E719A8500D62E90 /* v8.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = v8.h; sourceTree = "<group>"; };
- 897FF0E00E719B3500D62E90 /* COPYING */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = COPYING; sourceTree = "<group>"; };
- 897FF0E10E719B3500D62E90 /* dtoa.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dtoa.c; sourceTree = "<group>"; };
897FF0F60E719B8F00D62E90 /* accessors.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = accessors.cc; sourceTree = "<group>"; };
897FF0F70E719B8F00D62E90 /* accessors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = accessors.h; sourceTree = "<group>"; };
897FF0F80E719B8F00D62E90 /* allocation.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = allocation.cc; sourceTree = "<group>"; };
@@ -1003,6 +1001,7 @@
897FF15F0E719B8F00D62E90 /* natives.h */,
897FF1600E719B8F00D62E90 /* objects-debug.cc */,
897FF1610E719B8F00D62E90 /* objects-inl.h */,
+ 8946827412C26EB700C914BC /* objects-printer.cc */,
C2D1E9711212F27B00187A52 /* objects-visiting.cc */,
C2D1E9721212F27B00187A52 /* objects-visiting.h */,
897FF1620E719B8F00D62E90 /* objects.cc */,
@@ -1020,7 +1019,6 @@
897FF16A0E719B8F00D62E90 /* platform.h */,
893E249512B14B3D0083370F /* preparse-data.cc */,
893E249612B14B3D0083370F /* preparse-data.h */,
- 893E249712B14B3D0083370F /* preparser-api.cc */,
893E249812B14B3D0083370F /* preparser.cc */,
893E249912B14B3D0083370F /* preparser.h */,
897FF16B0E719B8F00D62E90 /* prettyprinter.cc */,
@@ -1161,7 +1159,6 @@
893E24E212B14BD20083370F /* C++ */,
89A9C1630E71C8E300BE6CCA /* generated */,
897FF0D80E719ABA00D62E90 /* js */,
- 897FF0DE0E719B3400D62E90 /* third_party */,
);
path = src;
sourceTree = "<group>";
@@ -1194,23 +1191,6 @@
name = js;
sourceTree = "<group>";
};
- 897FF0DE0E719B3400D62E90 /* third_party */ = {
- isa = PBXGroup;
- children = (
- 897FF0DF0E719B3400D62E90 /* dtoa */,
- );
- path = third_party;
- sourceTree = "<group>";
- };
- 897FF0DF0E719B3400D62E90 /* dtoa */ = {
- isa = PBXGroup;
- children = (
- 897FF0E00E719B3500D62E90 /* COPYING */,
- 897FF0E10E719B3500D62E90 /* dtoa.c */,
- );
- path = dtoa;
- sourceTree = "<group>";
- };
897FF1B30E719BCE00D62E90 /* samples */ = {
isa = PBXGroup;
children = (
@@ -1583,7 +1563,6 @@
893E24BC12B14B3D0083370F /* hydrogen.cc in Sources */,
893E24BD12B14B3D0083370F /* lithium-allocator.cc in Sources */,
893E24BE12B14B3D0083370F /* preparse-data.cc in Sources */,
- 893E24BF12B14B3D0083370F /* preparser-api.cc in Sources */,
893E24C012B14B3D0083370F /* preparser.cc in Sources */,
893E24C112B14B3D0083370F /* runtime-profiler.cc in Sources */,
893E24C212B14B3D0083370F /* safepoint-table.cc in Sources */,
@@ -1595,6 +1574,7 @@
893E24D712B14B8A0083370F /* lithium-ia32.cc in Sources */,
893E24DC12B14B9F0083370F /* externalize-string-extension.cc in Sources */,
893E24DD12B14B9F0083370F /* gc-extension.cc in Sources */,
+ 8946827512C26EB700C914BC /* objects-printer.cc in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1738,7 +1718,6 @@
893E24AD12B14B3D0083370F /* hydrogen.cc in Sources */,
893E24AE12B14B3D0083370F /* lithium-allocator.cc in Sources */,
893E24AF12B14B3D0083370F /* preparse-data.cc in Sources */,
- 893E24B012B14B3D0083370F /* preparser-api.cc in Sources */,
893E24B112B14B3D0083370F /* preparser.cc in Sources */,
893E24B212B14B3D0083370F /* runtime-profiler.cc in Sources */,
893E24B312B14B3D0083370F /* safepoint-table.cc in Sources */,
@@ -1750,6 +1729,7 @@
893E24CE12B14B520083370F /* lithium-codegen-arm.cc in Sources */,
893E24DE12B14B9F0083370F /* externalize-string-extension.cc in Sources */,
893E24DF12B14B9F0083370F /* gc-extension.cc in Sources */,
+ 8946827612C26EB700C914BC /* objects-printer.cc in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1850,7 +1830,7 @@
DEBUG,
ENABLE_LOGGING_AND_PROFILING,
V8_ENABLE_CHECKS,
- OBJECT_PRINT,
+ OBJECT_PRINT,
ENABLE_VMSTATE_TRACKING,
);
GCC_SYMBOLS_PRIVATE_EXTERN = YES;
@@ -1915,7 +1895,7 @@
V8_TARGET_ARCH_IA32,
DEBUG,
V8_ENABLE_CHECKS,
- OBJECT_PRINT,
+ OBJECT_PRINT,
ENABLE_DEBUGGER_SUPPORT,
);
HEADER_SEARCH_PATHS = ../src;
@@ -1978,7 +1958,7 @@
V8_TARGET_ARCH_IA32,
DEBUG,
V8_ENABLE_CHECKS,
- OBJECT_PRINT,
+ OBJECT_PRINT,
ENABLE_DEBUGGER_SUPPORT,
);
HEADER_SEARCH_PATHS = ../src;
diff --git a/tools/visual_studio/v8_base.vcproj b/tools/visual_studio/v8_base.vcproj
index e53b3fc3..ceeebf9a 100644
--- a/tools/visual_studio/v8_base.vcproj
+++ b/tools/visual_studio/v8_base.vcproj
@@ -793,6 +793,10 @@
>
</File>
<File
+ RelativePath="..\..\src\objects-printer.cc"
+ >
+ </File>
+ <File
RelativePath="..\..\src\objects-visiting.cc"
>
</File>
diff --git a/tools/visual_studio/v8_base_arm.vcproj b/tools/visual_studio/v8_base_arm.vcproj
index 1054958a..cd4c52eb 100644
--- a/tools/visual_studio/v8_base_arm.vcproj
+++ b/tools/visual_studio/v8_base_arm.vcproj
@@ -793,6 +793,10 @@
>
</File>
<File
+ RelativePath="..\..\src\objects-printer.cc"
+ >
+ </File>
+ <File
RelativePath="..\..\src\objects-visiting.cc"
>
</File>
diff --git a/tools/visual_studio/v8_base_x64.vcproj b/tools/visual_studio/v8_base_x64.vcproj
index 28f299ed..2c7bf5ef 100644
--- a/tools/visual_studio/v8_base_x64.vcproj
+++ b/tools/visual_studio/v8_base_x64.vcproj
@@ -770,6 +770,10 @@
>
</File>
<File
+ RelativePath="..\..\src\objects-printer.cc"
+ >
+ </File>
+ <File
RelativePath="..\..\src\objects-visiting.cc"
>
</File>