Version 3.0.5
Fixed a couple of cast errors for gcc-3.4.3.
Performance improvements in GC and IA32 code generator.
git-svn-id: http://v8.googlecode.com/svn/trunk@6131 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/ChangeLog b/ChangeLog
index c81d7a7..d80638b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+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/src/SConscript b/src/SConscript
index dfa099c..b1f9bb6 100755
--- a/src/SConscript
+++ b/src/SConscript
@@ -229,9 +229,10 @@
'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/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc
index 5ec8584..7c3ea89 100644
--- a/src/arm/code-stubs-arm.cc
+++ b/src/arm/code-stubs-arm.cc
@@ -2894,45 +2894,45 @@
// 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, ¬_js_object);
+ __ IsObjectJSObjectType(object, map, scratch, ¬_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 @@
__ 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 @@
__ 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/lithium-arm.cc b/src/arm/lithium-arm.cc
index e31d2e1..9c8e834 100644
--- a/src/arm/lithium-arm.cc
+++ b/src/arm/lithium-arm.cc
@@ -1316,8 +1316,8 @@
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);
}
@@ -1666,19 +1666,15 @@
}
-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));
}
@@ -1854,6 +1850,14 @@
}
+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));
diff --git a/src/arm/lithium-arm.h b/src/arm/lithium-arm.h
index 41209c6..5b152ef 100644
--- a/src/arm/lithium-arm.h
+++ b/src/arm/lithium-arm.h
@@ -101,7 +101,8 @@
// LStoreNamedField
// LStoreNamedGeneric
// LUnaryOperation
-// LArrayLength
+// LJSArrayLength
+// LFixedArrayLength
// LBitNotI
// LBranch
// LCallNew
@@ -127,6 +128,7 @@
// LIsSmiAndBranch
// LLoadNamedField
// LLoadNamedGeneric
+// LLoadFunctionPrototype
// LNumberTagD
// LNumberTagI
// LPushArgument
@@ -161,7 +163,6 @@
V(ArgumentsLength) \
V(ArithmeticD) \
V(ArithmeticT) \
- V(ArrayLength) \
V(ArrayLiteral) \
V(BitI) \
V(BitNotI) \
@@ -195,6 +196,7 @@
V(Deoptimize) \
V(DivI) \
V(DoubleToI) \
+ V(FixedArrayLength) \
V(FunctionLiteral) \
V(Gap) \
V(GlobalObject) \
@@ -209,6 +211,7 @@
V(IsObjectAndBranch) \
V(IsSmi) \
V(IsSmiAndBranch) \
+ V(JSArrayLength) \
V(HasInstanceType) \
V(HasInstanceTypeAndBranch) \
V(HasCachedArrayIndex) \
@@ -223,6 +226,7 @@
V(LoadKeyedGeneric) \
V(LoadNamedField) \
V(LoadNamedGeneric) \
+ V(LoadFunctionPrototype) \
V(ModI) \
V(MulI) \
V(NumberTagD) \
@@ -1141,18 +1145,21 @@
};
-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 +1263,22 @@
};
+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) { }
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
index dfc4891..53a4325 100644
--- a/src/arm/lithium-codegen-arm.cc
+++ b/src/arm/lithium-codegen-arm.cc
@@ -898,24 +898,19 @@
}
-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));
+ Abort("DoJSArrayLength untested.");
+}
- 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.");
}
@@ -1337,14 +1332,16 @@
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);
}
@@ -1447,6 +1444,50 @@
}
+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. Load map into the
+ // result register.
+ __ CompareObjectType(function, result, temp, JS_FUNCTION_TYPE);
+ DeoptimizeIf(ne, instr->environment());
+
+ // Make sure that the function has an instance prototype.
+ Label non_instance;
+ __ ldrb(temp, FieldMemOperand(result, Map::kBitFieldOffset));
+ __ tst(temp, 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, temp, temp, 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.");
}
diff --git a/src/ast.cc b/src/ast.cc
index 895ab67..1a6e768 100644
--- a/src/ast.cc
+++ b/src/ast.cc
@@ -517,6 +517,9 @@
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 ed447e3..ba422fd 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -1208,6 +1208,7 @@
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 @@
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 @@
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 @@
: 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 21381f1..0c76f69 100644
--- a/src/builtins.cc
+++ b/src/builtins.cc
@@ -380,7 +380,7 @@
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 @@
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());
-
- 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());
- }
- }
-#endif
+ if (receiver->IsJSArray()) {
+ JSArray* array = JSArray::cast(receiver);
+ if (!array->HasFastElements() ||
+ !IsJSArrayFastElementMovingAllowed(array)) {
+ return CallJsBuiltin("ArraySlice", args);
}
+
+ 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());
+ }
+ }
+#endif
}
ASSERT(len >= 0);
int n_arguments = args.length() - 1;
diff --git a/src/d8-debug.cc b/src/d8-debug.cc
index 5f3ed76..8a3886c 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 @@
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 @@
} else {
printf("???\n");
}
- PrintPrompt();
+
+ bool is_running = details->Get(String::New("running"))->ToBoolean()->Value();
+ PrintPrompt(is_running);
}
diff --git a/src/date.js b/src/date.js
index bc70327..9eb607c 100644
--- a/src/date.js
+++ b/src/date.js
@@ -1000,7 +1000,7 @@
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/deoptimizer.cc b/src/deoptimizer.cc
index dd70baa..185ff92 100644
--- a/src/deoptimizer.cc
+++ b/src/deoptimizer.cc
@@ -309,9 +309,9 @@
}
-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 2d7dfc8..f9bf280 100644
--- a/src/deoptimizer.h
+++ b/src/deoptimizer.h
@@ -145,9 +145,9 @@
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 83af447..2bc878c 100644
--- a/src/factory.cc
+++ b/src/factory.cc
@@ -99,6 +99,14 @@
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 b7a2882..a5e1591 100644
--- a/src/factory.h
+++ b/src/factory.h
@@ -61,6 +61,8 @@
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/globals.h b/src/globals.h
index 35156ae..9b24bf6 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -181,10 +181,6 @@
#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 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 ef83998..7b91e87 100644
--- a/src/heap-inl.h
+++ b/src/heap-inl.h
@@ -40,6 +40,19 @@
}
+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::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());
}
diff --git a/src/heap.cc b/src/heap.cc
index 1e99991..44229f0 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -2549,20 +2549,10 @@
}
// 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::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 @@
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::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::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 18a4afb..3ceefd8 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -412,7 +412,10 @@
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 @@
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 @@
// 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 cbbe8fc..e9c437f 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -76,7 +76,6 @@
// HLoadKeyed
// HLoadKeyedFastElement
// HLoadKeyedGeneric
-// HLoadNamedGeneric
// HPower
// HStoreNamed
// HStoreNamedField
@@ -119,7 +118,6 @@
// HStoreKeyedFastElement
// HStoreKeyedGeneric
// HUnaryOperation
-// HArrayLength
// HBitNot
// HChange
// HCheckFunction
@@ -129,9 +127,13 @@
// HCheckPrototypeMaps
// HCheckSmi
// HDeleteProperty
+// HFixedArrayLength
+// HJSArrayLength
// HLoadElements
// HTypeofIs
// HLoadNamedField
+// HLoadNamedGeneric
+// HLoadFunctionPrototype
// HPushArgument
// HTypeof
// HUnaryMathOperation
@@ -170,7 +172,6 @@
V(ArgumentsElements) \
V(ArgumentsLength) \
V(ArgumentsObject) \
- V(ArrayLength) \
V(ArrayLiteral) \
V(BitAnd) \
V(BitNot) \
@@ -203,6 +204,7 @@
V(Deoptimize) \
V(Div) \
V(EnterInlined) \
+ V(FixedArrayLength) \
V(FunctionLiteral) \
V(GlobalObject) \
V(GlobalReceiver) \
@@ -213,6 +215,7 @@
V(IsSmi) \
V(HasInstanceType) \
V(HasCachedArrayIndex) \
+ V(JSArrayLength) \
V(ClassOfTest) \
V(LeaveInlined) \
V(LoadElements) \
@@ -221,6 +224,7 @@
V(LoadKeyedGeneric) \
V(LoadNamedField) \
V(LoadNamedGeneric) \
+ V(LoadFunctionPrototype) \
V(Mod) \
V(Mul) \
V(ObjectLiteral) \
@@ -256,6 +260,7 @@
V(GlobalVars) \
V(Maps) \
V(ArrayLengths) \
+ V(FunctionPrototypes) \
V(OsrEntries)
#define DECLARE_INSTRUCTION(type) \
@@ -1336,9 +1341,9 @@
};
-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 +1356,23 @@
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 +1787,8 @@
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 +2640,27 @@
};
+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 +2707,12 @@
};
+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 +2730,10 @@
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 +2814,10 @@
HValue* key() const { return OperandAt(1); }
HValue* value() const { return OperandAt(2); }
+ bool NeedsWriteBarrier() const {
+ return StoringValueNeedsWriteBarrier(value());
+ }
+
DECLARE_INSTRUCTION(StoreKeyed)
protected:
@@ -2779,10 +2837,6 @@
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 e34acd6..03ce5b3 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -3643,9 +3643,18 @@
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 +3680,9 @@
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 +3729,13 @@
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();
@@ -4854,7 +4869,9 @@
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;
diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc
index 13a1177..5beec0d 100644
--- a/src/ia32/full-codegen-ia32.cc
+++ b/src/ia32/full-codegen-ia32.cc
@@ -379,7 +379,7 @@
void FullCodeGenerator::AccumulatorValueContext::Plug(
Handle<Object> lit) const {
- __ mov(result_register(), lit);
+ __ Set(result_register(), Immediate(lit));
}
diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc
index d64f528..9569ac8 100644
--- a/src/ia32/lithium-codegen-ia32.cc
+++ b/src/ia32/lithium-codegen-ia32.cc
@@ -940,7 +940,7 @@
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::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::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 @@
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));
diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc
index 3b272d0..8c003a5 100644
--- a/src/ia32/lithium-ia32.cc
+++ b/src/ia32/lithium-ia32.cc
@@ -1677,19 +1677,15 @@
}
-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 +1856,14 @@
}
+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 +1935,7 @@
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())
diff --git a/src/ia32/lithium-ia32.h b/src/ia32/lithium-ia32.h
index 3f48e50..94bf8fd 100644
--- a/src/ia32/lithium-ia32.h
+++ b/src/ia32/lithium-ia32.h
@@ -104,7 +104,6 @@
// LStoreNamedField
// LStoreNamedGeneric
// LUnaryOperation
-// LArrayLength
// LBitNotI
// LBranch
// LCallNew
@@ -117,6 +116,7 @@
// LClassOfTestAndBranch
// LDeleteProperty
// LDoubleToI
+// LFixedArrayLength
// LHasCachedArrayIndex
// LHasCachedArrayIndexAndBranch
// LHasInstanceType
@@ -128,8 +128,10 @@
// LIsObjectAndBranch
// LIsSmi
// LIsSmiAndBranch
+// LJSArrayLength
// LLoadNamedField
// LLoadNamedGeneric
+// LLoadFunctionPrototype
// LNumberTagD
// LNumberTagI
// LPushArgument
@@ -164,7 +166,6 @@
V(ArgumentsLength) \
V(ArithmeticD) \
V(ArithmeticT) \
- V(ArrayLength) \
V(ArrayLiteral) \
V(BitI) \
V(BitNotI) \
@@ -203,6 +204,7 @@
V(GlobalObject) \
V(GlobalReceiver) \
V(Goto) \
+ V(FixedArrayLength) \
V(InstanceOf) \
V(InstanceOfAndBranch) \
V(Integer32ToDouble) \
@@ -212,6 +214,7 @@
V(IsObjectAndBranch) \
V(IsSmi) \
V(IsSmiAndBranch) \
+ V(JSArrayLength) \
V(HasInstanceType) \
V(HasInstanceTypeAndBranch) \
V(HasCachedArrayIndex) \
@@ -226,6 +229,7 @@
V(LoadKeyedGeneric) \
V(LoadNamedField) \
V(LoadNamedGeneric) \
+ V(LoadFunctionPrototype) \
V(ModI) \
V(MulI) \
V(NumberTagD) \
@@ -1146,18 +1150,21 @@
};
-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 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) { }
diff --git a/src/ia32/regexp-macro-assembler-ia32.cc b/src/ia32/regexp-macro-assembler-ia32.cc
index d435a70..cc2f30d 100644
--- a/src/ia32/regexp-macro-assembler-ia32.cc
+++ b/src/ia32/regexp-macro-assembler-ia32.cc
@@ -211,9 +211,7 @@
// 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();
diff --git a/src/json.js b/src/json.js
index 89009a9..0034176 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 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 @@
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 @@
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 @@
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 @@
// 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/liveedit-debugger.js b/src/liveedit-debugger.js
index 0f7c12d..7ed22c8 100644
--- a/src/liveedit-debugger.js
+++ b/src/liveedit-debugger.js
@@ -144,8 +144,8 @@
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/macros.py b/src/macros.py
index 6d66def..01512e4 100644
--- a/src/macros.py
+++ b/src/macros.py
@@ -120,6 +120,7 @@
# 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 55836ce..9177a6b 100644
--- a/src/mirror-debugger.js
+++ b/src/mirror-debugger.js
@@ -2369,7 +2369,7 @@
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 53296d9..0b83182 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 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 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 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 @@
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 @@
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 @@
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 @@
}
}
}
-#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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 0000000..9879da2
--- /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 55a0a53..6510ca8 100644
--- a/src/objects-visiting.h
+++ b/src/objects-visiting.h
@@ -186,9 +186,9 @@
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 ab2f964..8c8b6e0 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -5143,6 +5143,26 @@
}
+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);
@@ -8086,6 +8106,85 @@
};
+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 +8929,19 @@
}
+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 c5fda7d..163b713 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -2327,6 +2327,10 @@
// 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 +5078,8 @@
// 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 +5251,34 @@
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 08f77b8..03819ee 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -323,22 +323,24 @@
}
-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> 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 @@
// 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,
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 @@
if (pre_data() != NULL) {
symbol_id = pre_data()->GetSymbolIdentifier();
}
- return LookupSymbol(symbol_id, scanner().literal());
+ return LookupSymbol(symbol_id);
}
@@ -2715,8 +2721,9 @@
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;
}
@@ -3066,8 +3073,9 @@
}
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 +3145,9 @@
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 +3429,10 @@
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 +3610,11 @@
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 +3626,8 @@
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);
@@ -4597,10 +4606,9 @@
// 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 +4636,7 @@
return NULL;
}
PartialParserRecorder recorder;
- return DoPreParse(source, allow_lazy, &recorder,
- JavaScriptScanner::kNoLiterals);
+ return DoPreParse(source, allow_lazy, &recorder);
}
@@ -4638,9 +4645,7 @@
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 70d0e18..8623f38 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -578,6 +578,26 @@
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 @@
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/preparse-data.cc b/src/preparse-data.cc
index 9a36771..7c9d8a6 100644
--- a/src/preparse-data.cc
+++ b/src/preparse-data.cc
@@ -110,26 +110,29 @@
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 a96e50f..cc82bcc 100644
--- a/src/preparse-data.h
+++ b/src/preparse-data.h
@@ -75,7 +75,8 @@
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 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 @@
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 @@
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 @@
}
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.cc b/src/preparser.cc
index 7cce685..157fbea 100644
--- a/src/preparser.cc
+++ b/src/preparser.cc
@@ -1121,23 +1121,23 @@
PreParser::Identifier PreParser::GetIdentifierSymbol() {
- const char* literal_chars = scanner_->literal_string();
- int literal_length = scanner_->literal_length();
int identifier_pos = scanner_->location().beg_pos;
-
- log_->LogSymbol(identifier_pos, literal_chars, literal_length);
-
- return kUnknownExpression;
+ if (scanner_->is_literal_ascii()) {
+ log_->LogAsciiSymbol(identifier_pos, scanner_->literal_ascii_string());
+ } else {
+ log_->LogUC16Symbol(identifier_pos, scanner_->literal_uc16_string());
+ }
+ 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);
-
+ 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());
+ }
return kUnknownExpression;
}
@@ -1154,7 +1154,8 @@
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 +1174,8 @@
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/scanner-base.cc b/src/scanner-base.cc
index b26fee0..1babaeb 100644
--- a/src/scanner-base.cc
+++ b/src/scanner-base.cc
@@ -35,28 +35,6 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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::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 c50b8f3..e773586 100644
--- a/src/scanner-base.h
+++ b/src/scanner-base.h
@@ -141,61 +141,103 @@
};
// ----------------------------------------------------------------------------
-// LiteralCollector - Collector of chars of literals.
+// LiteralBuffer - Collector of chars of literals.
-class LiteralCollector {
+class LiteralBuffer {
public:
- LiteralCollector();
- ~LiteralCollector();
+ LiteralBuffer() : is_ascii_(true), position_(0), backing_store_() { }
- 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() {
+ 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;
+ }
+ private:
+ 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;
}
- // 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);
+ 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()) {
+ 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 +283,40 @@
// 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();
}
-
+ Vector<const char> literal_ascii_string() {
+ ASSERT_NOT_NULL(current_.literal_chars);
+ return current_.literal_chars->ascii_literal();
+ }
+ Vector<const uc16> literal_uc16_string() {
+ ASSERT_NOT_NULL(current_.literal_chars);
+ return current_.literal_chars->uc16_literal();
+ }
int literal_length() const {
- // Excluding terminal '\x00' added by TerminateLiteral().
- return current_.literal_chars.length() - 1;
- }
-
- Vector<const char> literal() const {
- return Vector<const char>(literal_string(), literal_length());
+ 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).
+ Vector<const char> next_literal_ascii_string() {
+ ASSERT_NOT_NULL(next_.literal_chars);
+ return next_.literal_chars->ascii_literal();
+ }
+ Vector<const uc16> next_literal_uc16_string() {
+ ASSERT_NOT_NULL(next_.literal_chars);
+ return next_.literal_chars->uc16_literal();
+ }
int next_literal_length() const {
- // Excluding terminal '\x00' added by TerminateLiteral().
- return next_.literal_chars.length() - 1;
- }
-
- Vector<const char> next_literal() const {
- return Vector<const char>(next_literal_string(), next_literal_length());
+ ASSERT_NOT_NULL(next_.literal_chars);
+ return next_.literal_chars->length();
}
static const int kCharacterLookaheadBufferSize = 1;
@@ -279,7 +326,7 @@
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 +335,31 @@
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 +397,16 @@
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 +417,14 @@
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 +466,6 @@
// 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 +489,6 @@
// 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 47e9895..38d0b1c 100755
--- a/src/scanner.cc
+++ b/src/scanner.cc
@@ -324,10 +324,8 @@
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 @@
void JsonScanner::ScanJson() {
- next_.literal_chars = Vector<const char>();
+ next_.literal_chars = NULL;
Token::Value token;
do {
// Remember the position of the next token
diff --git a/src/scanner.h b/src/scanner.h
index 572778f..bdf899b 100644
--- a/src/scanner.h
+++ b/src/scanner.h
@@ -134,8 +134,7 @@
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 eac8475..5de3c09 100644
--- a/src/string-search.h
+++ b/src/string-search.h
@@ -66,12 +66,7 @@
}
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 9527599..ab0ab54 100644
--- a/src/string.js
+++ b/src/string.js
@@ -127,7 +127,7 @@
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/utils.h b/src/utils.h
index 62b8726..21e70d7 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -530,6 +530,24 @@
}
+ // 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/version.cc b/src/version.cc
index d2c0960..e362148 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -34,8 +34,8 @@
// cannot be changed without changing the SCons build script.
#define MAJOR_VERSION 3
#define MINOR_VERSION 0
-#define BUILD_NUMBER 4
-#define PATCH_LEVEL 1
+#define BUILD_NUMBER 5
+#define PATCH_LEVEL 0
#define CANDIDATE_VERSION false
// Define SONAME to have the SCons build the put a specific SONAME into the
diff --git a/src/x64/regexp-macro-assembler-x64.cc b/src/x64/regexp-macro-assembler-x64.cc
index 2cf85f1..0838ddd 100644
--- a/src/x64/regexp-macro-assembler-x64.cc
+++ b/src/x64/regexp-macro-assembler-x64.cc
@@ -223,9 +223,7 @@
// 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();
diff --git a/test/cctest/test-assembler-ia32.cc b/test/cctest/test-assembler-ia32.cc
index 40232ef..14692ff 100644
--- a/test/cctest/test-assembler-ia32.cc
+++ b/test/cctest/test-assembler-ia32.cc
@@ -74,7 +74,7 @@
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 @@
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 @@
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 @@
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 @@
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 5cd56ac..b563f8f 100644
--- a/test/cctest/test-disasm-ia32.cc
+++ b/test/cctest/test-disasm-ia32.cc
@@ -443,7 +443,7 @@
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 e642d1b..da5d771 100755
--- a/test/cctest/test-parsing.cc
+++ b/test/cctest/test-parsing.cc
@@ -573,7 +573,7 @@
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/tools/gyp/v8.gyp b/tools/gyp/v8.gyp
index 6af6611..a274a48 100644
--- a/tools/gyp/v8.gyp
+++ b/tools/gyp/v8.gyp
@@ -438,6 +438,7 @@
'../../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',
diff --git a/tools/v8.xcodeproj/project.pbxproj b/tools/v8.xcodeproj/project.pbxproj
index 5254c6e..80a845c 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 e53b3fc..ceeebf9 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 1054958..cd4c52e 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 28f299e..2c7bf5e 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>