Browse Source

Upgrade V8 to 3.5.8

Ryan Dahl 14 years ago
parent
commit
028908ab7c
  1. 11
      deps/v8/ChangeLog
  2. 0
      deps/v8/include/v8-debug.h
  3. 21
      deps/v8/include/v8.h
  4. 0
      deps/v8/src/SConscript
  5. 22
      deps/v8/src/api.cc
  6. 3
      deps/v8/src/arm/assembler-arm.h
  7. 32
      deps/v8/src/arm/code-stubs-arm.cc
  8. 3
      deps/v8/src/arm/full-codegen-arm.cc
  9. 1
      deps/v8/src/arm/lithium-arm.cc
  10. 3
      deps/v8/src/arm/lithium-codegen-arm.cc
  11. 4
      deps/v8/src/arm/lithium-gap-resolver-arm.cc
  12. 5
      deps/v8/src/arm/stub-cache-arm.cc
  13. 47
      deps/v8/src/ast.cc
  14. 74
      deps/v8/src/ast.h
  15. 0
      deps/v8/src/compiler.cc
  16. 6
      deps/v8/src/d8.cc
  17. 8
      deps/v8/src/handles.cc
  18. 23
      deps/v8/src/hydrogen-instructions.cc
  19. 28
      deps/v8/src/hydrogen-instructions.h
  20. 42
      deps/v8/src/hydrogen.cc
  21. 4
      deps/v8/src/hydrogen.h
  22. 10
      deps/v8/src/interpreter-irregexp.cc
  23. 46
      deps/v8/src/jsregexp.cc
  24. 12
      deps/v8/src/messages.js
  25. 5
      deps/v8/src/objects-inl.h
  26. 121
      deps/v8/src/objects.cc
  27. 60
      deps/v8/src/objects.h
  28. 36
      deps/v8/src/profile-generator.cc
  29. 5
      deps/v8/src/profile-generator.h
  30. 212
      deps/v8/src/runtime.cc
  31. 0
      deps/v8/src/scanner.cc
  32. 25
      deps/v8/src/small-pointer-list.h
  33. 2
      deps/v8/src/string.js
  34. 3
      deps/v8/src/stub-cache.cc
  35. 4
      deps/v8/src/stub-cache.h
  36. 45
      deps/v8/src/type-info.cc
  37. 32
      deps/v8/src/type-info.h
  38. 2
      deps/v8/src/version.cc
  39. 4
      deps/v8/src/zone.h
  40. 41
      deps/v8/test/cctest/test-api.cc
  41. 56
      deps/v8/test/cctest/test-heap-profiler.cc
  42. 31
      deps/v8/test/message/replacement-marker-as-argument.js
  43. 32
      deps/v8/test/message/replacement-marker-as-argument.out
  44. 12
      deps/v8/test/mjsunit/string-split.js

11
deps/v8/ChangeLog

@ -1,3 +1,14 @@
2011-08-24: Version 3.5.8
Added V8EXPORT attributes for v8::Array::CheckCast and
v8::Number::CheckCast.
Made a slight API change enabling opting out from null termination
in String::Write*().
Fixed arm build for gcc-4.6.
2011-08-22: Version 3.5.7 2011-08-22: Version 3.5.7
Make scanner handle invalid unicode escapes in identifiers correctly. Make scanner handle invalid unicode escapes in identifiers correctly.

0
deps/v8/include/v8-debug.h

21
deps/v8/include/v8.h

@ -1039,29 +1039,30 @@ class String : public Primitive {
* \param length The number of characters to copy from the string. For * \param length The number of characters to copy from the string. For
* WriteUtf8 the number of bytes in the buffer. * WriteUtf8 the number of bytes in the buffer.
* \param nchars_ref The number of characters written, can be NULL. * \param nchars_ref The number of characters written, can be NULL.
* \param hints Various hints that might affect performance of this or * \param options Various options that might affect performance of this or
* subsequent operations. * subsequent operations.
* \return The number of characters copied to the buffer excluding the null * \return The number of characters copied to the buffer excluding the null
* terminator. For WriteUtf8: The number of bytes copied to the buffer * terminator. For WriteUtf8: The number of bytes copied to the buffer
* including the null terminator. * including the null terminator (if written).
*/ */
enum WriteHints { enum WriteOptions {
NO_HINTS = 0, NO_OPTIONS = 0,
HINT_MANY_WRITES_EXPECTED = 1 HINT_MANY_WRITES_EXPECTED = 1,
NO_NULL_TERMINATION = 2
}; };
V8EXPORT int Write(uint16_t* buffer, V8EXPORT int Write(uint16_t* buffer,
int start = 0, int start = 0,
int length = -1, int length = -1,
WriteHints hints = NO_HINTS) const; // UTF-16 int options = NO_OPTIONS) const; // UTF-16
V8EXPORT int WriteAscii(char* buffer, V8EXPORT int WriteAscii(char* buffer,
int start = 0, int start = 0,
int length = -1, int length = -1,
WriteHints hints = NO_HINTS) const; // ASCII int options = NO_OPTIONS) const; // ASCII
V8EXPORT int WriteUtf8(char* buffer, V8EXPORT int WriteUtf8(char* buffer,
int length = -1, int length = -1,
int* nchars_ref = NULL, int* nchars_ref = NULL,
WriteHints hints = NO_HINTS) const; // UTF-8 int options = NO_OPTIONS) const; // UTF-8
/** /**
* A zero length string. * A zero length string.
@ -1335,7 +1336,7 @@ class Number : public Primitive {
static inline Number* Cast(v8::Value* obj); static inline Number* Cast(v8::Value* obj);
private: private:
V8EXPORT Number(); V8EXPORT Number();
static void CheckCast(v8::Value* obj); V8EXPORT static void CheckCast(v8::Value* obj);
}; };
@ -1709,7 +1710,7 @@ class Array : public Object {
static inline Array* Cast(Value* obj); static inline Array* Cast(Value* obj);
private: private:
V8EXPORT Array(); V8EXPORT Array();
static void CheckCast(Value* obj); V8EXPORT static void CheckCast(Value* obj);
}; };

0
deps/v8/src/SConscript

22
deps/v8/src/api.cc

@ -3621,7 +3621,7 @@ int String::Utf8Length() const {
int String::WriteUtf8(char* buffer, int String::WriteUtf8(char* buffer,
int capacity, int capacity,
int* nchars_ref, int* nchars_ref,
WriteHints hints) const { int options) const {
i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
if (IsDeadCheck(isolate, "v8::String::WriteUtf8()")) return 0; if (IsDeadCheck(isolate, "v8::String::WriteUtf8()")) return 0;
LOG_API(isolate, "String::WriteUtf8"); LOG_API(isolate, "String::WriteUtf8");
@ -3629,7 +3629,7 @@ int String::WriteUtf8(char* buffer,
i::StringInputBuffer& write_input_buffer = *isolate->write_input_buffer(); i::StringInputBuffer& write_input_buffer = *isolate->write_input_buffer();
i::Handle<i::String> str = Utils::OpenHandle(this); i::Handle<i::String> str = Utils::OpenHandle(this);
isolate->string_tracker()->RecordWrite(str); isolate->string_tracker()->RecordWrite(str);
if (hints & HINT_MANY_WRITES_EXPECTED) { if (options & HINT_MANY_WRITES_EXPECTED) {
// Flatten the string for efficiency. This applies whether we are // Flatten the string for efficiency. This applies whether we are
// using StringInputBuffer or Get(i) to access the characters. // using StringInputBuffer or Get(i) to access the characters.
str->TryFlatten(); str->TryFlatten();
@ -3669,7 +3669,8 @@ int String::WriteUtf8(char* buffer,
} }
} }
if (nchars_ref != NULL) *nchars_ref = nchars; if (nchars_ref != NULL) *nchars_ref = nchars;
if (i == len && (capacity == -1 || pos < capacity)) if (!(options & NO_NULL_TERMINATION) &&
(i == len && (capacity == -1 || pos < capacity)))
buffer[pos++] = '\0'; buffer[pos++] = '\0';
return pos; return pos;
} }
@ -3678,7 +3679,7 @@ int String::WriteUtf8(char* buffer,
int String::WriteAscii(char* buffer, int String::WriteAscii(char* buffer,
int start, int start,
int length, int length,
WriteHints hints) const { int options) const {
i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
if (IsDeadCheck(isolate, "v8::String::WriteAscii()")) return 0; if (IsDeadCheck(isolate, "v8::String::WriteAscii()")) return 0;
LOG_API(isolate, "String::WriteAscii"); LOG_API(isolate, "String::WriteAscii");
@ -3687,7 +3688,7 @@ int String::WriteAscii(char* buffer,
ASSERT(start >= 0 && length >= -1); ASSERT(start >= 0 && length >= -1);
i::Handle<i::String> str = Utils::OpenHandle(this); i::Handle<i::String> str = Utils::OpenHandle(this);
isolate->string_tracker()->RecordWrite(str); isolate->string_tracker()->RecordWrite(str);
if (hints & HINT_MANY_WRITES_EXPECTED) { if (options & HINT_MANY_WRITES_EXPECTED) {
// Flatten the string for efficiency. This applies whether we are // Flatten the string for efficiency. This applies whether we are
// using StringInputBuffer or Get(i) to access the characters. // using StringInputBuffer or Get(i) to access the characters.
str->TryFlatten(); str->TryFlatten();
@ -3703,7 +3704,7 @@ int String::WriteAscii(char* buffer,
if (c == '\0') c = ' '; if (c == '\0') c = ' ';
buffer[i] = c; buffer[i] = c;
} }
if (length == -1 || i < length) if (!(options & NO_NULL_TERMINATION) && (length == -1 || i < length))
buffer[i] = '\0'; buffer[i] = '\0';
return i; return i;
} }
@ -3712,7 +3713,7 @@ int String::WriteAscii(char* buffer,
int String::Write(uint16_t* buffer, int String::Write(uint16_t* buffer,
int start, int start,
int length, int length,
WriteHints hints) const { int options) const {
i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
if (IsDeadCheck(isolate, "v8::String::Write()")) return 0; if (IsDeadCheck(isolate, "v8::String::Write()")) return 0;
LOG_API(isolate, "String::Write"); LOG_API(isolate, "String::Write");
@ -3720,7 +3721,7 @@ int String::Write(uint16_t* buffer,
ASSERT(start >= 0 && length >= -1); ASSERT(start >= 0 && length >= -1);
i::Handle<i::String> str = Utils::OpenHandle(this); i::Handle<i::String> str = Utils::OpenHandle(this);
isolate->string_tracker()->RecordWrite(str); isolate->string_tracker()->RecordWrite(str);
if (hints & HINT_MANY_WRITES_EXPECTED) { if (options & HINT_MANY_WRITES_EXPECTED) {
// Flatten the string for efficiency. This applies whether we are // Flatten the string for efficiency. This applies whether we are
// using StringInputBuffer or Get(i) to access the characters. // using StringInputBuffer or Get(i) to access the characters.
str->TryFlatten(); str->TryFlatten();
@ -3730,7 +3731,8 @@ int String::Write(uint16_t* buffer,
end = str->length(); end = str->length();
if (end < 0) return 0; if (end < 0) return 0;
i::String::WriteToFlat(*str, buffer, start, end); i::String::WriteToFlat(*str, buffer, start, end);
if (length == -1 || end - start < length) { if (!(options & NO_NULL_TERMINATION) &&
(length == -1 || end - start < length)) {
buffer[end - start] = '\0'; buffer[end - start] = '\0';
} }
return end - start; return end - start;
@ -4118,7 +4120,7 @@ bool Context::InContext() {
v8::Local<v8::Context> Context::GetEntered() { v8::Local<v8::Context> Context::GetEntered() {
i::Isolate* isolate = i::Isolate::Current(); i::Isolate* isolate = i::Isolate::Current();
if (IsDeadCheck(isolate, "v8::Context::GetEntered()")) { if (!EnsureInitializedForIsolate(isolate, "v8::Context::GetEntered()")) {
return Local<Context>(); return Local<Context>();
} }
i::Handle<i::Object> last = i::Handle<i::Object> last =

3
deps/v8/src/arm/assembler-arm.h

@ -377,6 +377,9 @@ class Operand BASE_EMBEDDED {
// immediate // immediate
INLINE(explicit Operand(int32_t immediate, INLINE(explicit Operand(int32_t immediate,
RelocInfo::Mode rmode = RelocInfo::NONE)); RelocInfo::Mode rmode = RelocInfo::NONE));
INLINE(static Operand Zero()) {
return Operand(static_cast<int32_t>(0));
}
INLINE(explicit Operand(const ExternalReference& f)); INLINE(explicit Operand(const ExternalReference& f));
explicit Operand(Handle<Object> handle); explicit Operand(Handle<Object> handle);
INLINE(explicit Operand(Smi* value)); INLINE(explicit Operand(Smi* value));

32
deps/v8/src/arm/code-stubs-arm.cc

@ -549,7 +549,7 @@ void FloatingPointHelper::ConvertIntToDouble(MacroAssembler* masm,
// | s | exp | mantissa | // | s | exp | mantissa |
// Check for zero. // Check for zero.
__ cmp(int_scratch, Operand(0)); __ cmp(int_scratch, Operand::Zero());
__ mov(dst2, int_scratch); __ mov(dst2, int_scratch);
__ mov(dst1, int_scratch); __ mov(dst1, int_scratch);
__ b(eq, &done); __ b(eq, &done);
@ -557,7 +557,7 @@ void FloatingPointHelper::ConvertIntToDouble(MacroAssembler* masm,
// Preload the sign of the value. // Preload the sign of the value.
__ and_(dst2, int_scratch, Operand(HeapNumber::kSignMask), SetCC); __ and_(dst2, int_scratch, Operand(HeapNumber::kSignMask), SetCC);
// Get the absolute value of the object (as an unsigned integer). // Get the absolute value of the object (as an unsigned integer).
__ rsb(int_scratch, int_scratch, Operand(0), SetCC, mi); __ rsb(int_scratch, int_scratch, Operand::Zero(), SetCC, mi);
// Get mantisssa[51:20]. // Get mantisssa[51:20].
@ -589,7 +589,7 @@ void FloatingPointHelper::ConvertIntToDouble(MacroAssembler* masm,
__ mov(scratch2, Operand(int_scratch, LSL, scratch2)); __ mov(scratch2, Operand(int_scratch, LSL, scratch2));
__ orr(dst2, dst2, scratch2); __ orr(dst2, dst2, scratch2);
// Set dst1 to 0. // Set dst1 to 0.
__ mov(dst1, Operand(0)); __ mov(dst1, Operand::Zero());
} }
__ bind(&done); __ bind(&done);
} }
@ -657,7 +657,7 @@ void FloatingPointHelper::LoadNumberAsInt32Double(MacroAssembler* masm,
// Check for 0 and -0. // Check for 0 and -0.
__ bic(scratch1, dst1, Operand(HeapNumber::kSignMask)); __ bic(scratch1, dst1, Operand(HeapNumber::kSignMask));
__ orr(scratch1, scratch1, Operand(dst2)); __ orr(scratch1, scratch1, Operand(dst2));
__ cmp(scratch1, Operand(0)); __ cmp(scratch1, Operand::Zero());
__ b(eq, &done); __ b(eq, &done);
// Check that the value can be exactly represented by a 32-bit integer. // Check that the value can be exactly represented by a 32-bit integer.
@ -730,7 +730,7 @@ void FloatingPointHelper::LoadNumberAsInt32(MacroAssembler* masm,
// Check for 0 and -0. // Check for 0 and -0.
__ bic(dst, scratch1, Operand(HeapNumber::kSignMask)); __ bic(dst, scratch1, Operand(HeapNumber::kSignMask));
__ orr(dst, scratch2, Operand(dst)); __ orr(dst, scratch2, Operand(dst));
__ cmp(dst, Operand(0)); __ cmp(dst, Operand::Zero());
__ b(eq, &done); __ b(eq, &done);
DoubleIs32BitInteger(masm, scratch1, scratch2, dst, scratch3, not_int32); DoubleIs32BitInteger(masm, scratch1, scratch2, dst, scratch3, not_int32);
@ -747,7 +747,7 @@ void FloatingPointHelper::LoadNumberAsInt32(MacroAssembler* masm,
// Set the sign. // Set the sign.
__ ldr(scratch1, FieldMemOperand(object, HeapNumber::kExponentOffset)); __ ldr(scratch1, FieldMemOperand(object, HeapNumber::kExponentOffset));
__ tst(scratch1, Operand(HeapNumber::kSignMask)); __ tst(scratch1, Operand(HeapNumber::kSignMask));
__ rsb(dst, dst, Operand(0), LeaveCC, mi); __ rsb(dst, dst, Operand::Zero(), LeaveCC, mi);
} }
__ bind(&done); __ bind(&done);
@ -2424,7 +2424,6 @@ void BinaryOpStub::GenerateSmiCode(
Register left = r1; Register left = r1;
Register right = r0; Register right = r0;
Register scratch1 = r7; Register scratch1 = r7;
Register scratch2 = r9;
// Perform combined smi check on both operands. // Perform combined smi check on both operands.
__ orr(scratch1, left, Operand(right)); __ orr(scratch1, left, Operand(right));
@ -2618,7 +2617,7 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
__ b(mi, &return_heap_number); __ b(mi, &return_heap_number);
// Check for minus zero. Return heap number for minus zero. // Check for minus zero. Return heap number for minus zero.
Label not_zero; Label not_zero;
__ cmp(scratch1, Operand(0)); __ cmp(scratch1, Operand::Zero());
__ b(ne, &not_zero); __ b(ne, &not_zero);
__ vmov(scratch2, d5.high()); __ vmov(scratch2, d5.high());
__ tst(scratch2, Operand(HeapNumber::kSignMask)); __ tst(scratch2, Operand(HeapNumber::kSignMask));
@ -3110,7 +3109,6 @@ void TranscendentalCacheStub::Generate(MacroAssembler* masm) {
Label no_update; Label no_update;
Label skip_cache; Label skip_cache;
const Register heap_number_map = r5;
// Call C function to calculate the result and update the cache. // Call C function to calculate the result and update the cache.
// Register r0 holds precalculated cache entry address; preserve // Register r0 holds precalculated cache entry address; preserve
@ -3581,7 +3579,7 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
ExternalReference js_entry_sp(Isolate::k_js_entry_sp_address, isolate); ExternalReference js_entry_sp(Isolate::k_js_entry_sp_address, isolate);
__ mov(r5, Operand(ExternalReference(js_entry_sp))); __ mov(r5, Operand(ExternalReference(js_entry_sp)));
__ ldr(r6, MemOperand(r5)); __ ldr(r6, MemOperand(r5));
__ cmp(r6, Operand(0)); __ cmp(r6, Operand::Zero());
__ b(ne, &non_outermost_js); __ b(ne, &non_outermost_js);
__ str(fp, MemOperand(r5)); __ str(fp, MemOperand(r5));
__ mov(ip, Operand(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME))); __ mov(ip, Operand(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME)));
@ -3656,7 +3654,7 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
__ pop(r5); __ pop(r5);
__ cmp(r5, Operand(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME))); __ cmp(r5, Operand(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME)));
__ b(ne, &non_outermost_js_2); __ b(ne, &non_outermost_js_2);
__ mov(r6, Operand(0)); __ mov(r6, Operand::Zero());
__ mov(r5, Operand(ExternalReference(js_entry_sp))); __ mov(r5, Operand(ExternalReference(js_entry_sp)));
__ str(r6, MemOperand(r5)); __ str(r6, MemOperand(r5));
__ bind(&non_outermost_js_2); __ bind(&non_outermost_js_2);
@ -3857,7 +3855,7 @@ void InstanceofStub::Generate(MacroAssembler* masm) {
__ Push(r0, r1); __ Push(r0, r1);
__ InvokeBuiltin(Builtins::INSTANCE_OF, CALL_FUNCTION); __ InvokeBuiltin(Builtins::INSTANCE_OF, CALL_FUNCTION);
__ LeaveInternalFrame(); __ LeaveInternalFrame();
__ cmp(r0, Operand(0)); __ cmp(r0, Operand::Zero());
__ LoadRoot(r0, Heap::kTrueValueRootIndex, eq); __ LoadRoot(r0, Heap::kTrueValueRootIndex, eq);
__ LoadRoot(r0, Heap::kFalseValueRootIndex, ne); __ LoadRoot(r0, Heap::kFalseValueRootIndex, ne);
__ Ret(HasArgsInRegisters() ? 0 : 2); __ Ret(HasArgsInRegisters() ? 0 : 2);
@ -3991,7 +3989,7 @@ void ArgumentsAccessStub::GenerateNewNonStrictFast(MacroAssembler* masm) {
FixedArray::kHeaderSize + 2 * kPointerSize; FixedArray::kHeaderSize + 2 * kPointerSize;
// If there are no mapped parameters, we do not need the parameter_map. // If there are no mapped parameters, we do not need the parameter_map.
__ cmp(r1, Operand(Smi::FromInt(0))); __ cmp(r1, Operand(Smi::FromInt(0)));
__ mov(r9, Operand(0), LeaveCC, eq); __ mov(r9, Operand::Zero(), LeaveCC, eq);
__ mov(r9, Operand(r1, LSL, 1), LeaveCC, ne); __ mov(r9, Operand(r1, LSL, 1), LeaveCC, ne);
__ add(r9, r9, Operand(kParameterMapHeaderSize), LeaveCC, ne); __ add(r9, r9, Operand(kParameterMapHeaderSize), LeaveCC, ne);
@ -4015,7 +4013,7 @@ void ArgumentsAccessStub::GenerateNewNonStrictFast(MacroAssembler* masm) {
__ ldr(r4, MemOperand(r8, Context::SlotOffset(Context::GLOBAL_INDEX))); __ ldr(r4, MemOperand(r8, Context::SlotOffset(Context::GLOBAL_INDEX)));
__ ldr(r4, FieldMemOperand(r4, GlobalObject::kGlobalContextOffset)); __ ldr(r4, FieldMemOperand(r4, GlobalObject::kGlobalContextOffset));
__ cmp(r1, Operand(0)); __ cmp(r1, Operand::Zero());
__ ldr(r4, MemOperand(r4, kNormalOffset), eq); __ ldr(r4, MemOperand(r4, kNormalOffset), eq);
__ ldr(r4, MemOperand(r4, kAliasedOffset), ne); __ ldr(r4, MemOperand(r4, kAliasedOffset), ne);
@ -5697,7 +5695,7 @@ void StringCompareStub::GenerateAsciiCharsCompareLoop(
Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
__ add(left, left, Operand(scratch1)); __ add(left, left, Operand(scratch1));
__ add(right, right, Operand(scratch1)); __ add(right, right, Operand(scratch1));
__ rsb(length, length, Operand(0)); __ rsb(length, length, Operand::Zero());
Register index = length; // index = -length; Register index = length; // index = -length;
// Compare loop. // Compare loop.
@ -6555,7 +6553,7 @@ void StringDictionaryLookupStub::Generate(MacroAssembler* masm) {
// treated as a lookup success. For positive lookup probing failure // treated as a lookup success. For positive lookup probing failure
// should be treated as lookup failure. // should be treated as lookup failure.
if (mode_ == POSITIVE_LOOKUP) { if (mode_ == POSITIVE_LOOKUP) {
__ mov(result, Operand(0)); __ mov(result, Operand::Zero());
__ Ret(); __ Ret();
} }
@ -6564,7 +6562,7 @@ void StringDictionaryLookupStub::Generate(MacroAssembler* masm) {
__ Ret(); __ Ret();
__ bind(&not_in_dictionary); __ bind(&not_in_dictionary);
__ mov(result, Operand(0)); __ mov(result, Operand::Zero());
__ Ret(); __ Ret();
} }

3
deps/v8/src/arm/full-codegen-arm.cc

@ -4129,11 +4129,8 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
default: { default: {
VisitForAccumulatorValue(expr->right()); VisitForAccumulatorValue(expr->right());
Condition cond = eq; Condition cond = eq;
bool strict = false;
switch (op) { switch (op) {
case Token::EQ_STRICT: case Token::EQ_STRICT:
strict = true;
// Fall through
case Token::EQ: case Token::EQ:
cond = eq; cond = eq;
__ pop(r1); __ pop(r1);

1
deps/v8/src/arm/lithium-arm.cc

@ -1399,7 +1399,6 @@ LInstruction* LChunkBuilder::DoPower(HPower* instr) {
LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) { LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) {
Token::Value op = instr->token(); Token::Value op = instr->token();
Representation r = instr->GetInputRepresentation();
ASSERT(instr->left()->representation().IsTagged()); ASSERT(instr->left()->representation().IsTagged());
ASSERT(instr->right()->representation().IsTagged()); ASSERT(instr->right()->representation().IsTagged());
bool reversed = (op == Token::GT || op == Token::LTE); bool reversed = (op == Token::GT || op == Token::LTE);

3
deps/v8/src/arm/lithium-codegen-arm.cc

@ -1804,7 +1804,6 @@ Condition LCodeGen::EmitIsObject(Register input,
void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) {
Register reg = ToRegister(instr->InputAt(0)); Register reg = ToRegister(instr->InputAt(0));
Register temp1 = ToRegister(instr->TempAt(0)); Register temp1 = ToRegister(instr->TempAt(0));
Register temp2 = scratch0();
int true_block = chunk_->LookupDestination(instr->true_block_id()); int true_block = chunk_->LookupDestination(instr->true_block_id());
int false_block = chunk_->LookupDestination(instr->false_block_id()); int false_block = chunk_->LookupDestination(instr->false_block_id());
@ -2759,7 +2758,6 @@ void LCodeGen::DoOuterContext(LOuterContext* instr) {
void LCodeGen::DoGlobalObject(LGlobalObject* instr) { void LCodeGen::DoGlobalObject(LGlobalObject* instr) {
Register context = ToRegister(instr->context());
Register result = ToRegister(instr->result()); Register result = ToRegister(instr->result());
__ ldr(result, ContextOperand(cp, Context::GLOBAL_INDEX)); __ ldr(result, ContextOperand(cp, Context::GLOBAL_INDEX));
} }
@ -3965,7 +3963,6 @@ void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
Register scratch1 = scratch0(); Register scratch1 = scratch0();
Register scratch2 = ToRegister(instr->TempAt(0)); Register scratch2 = ToRegister(instr->TempAt(0));
DwVfpRegister double_input = ToDoubleRegister(instr->InputAt(0)); DwVfpRegister double_input = ToDoubleRegister(instr->InputAt(0));
DwVfpRegister double_scratch = double_scratch0();
SwVfpRegister single_scratch = double_scratch0().low(); SwVfpRegister single_scratch = double_scratch0().low();
Label done; Label done;

4
deps/v8/src/arm/lithium-gap-resolver-arm.cc

@ -254,7 +254,6 @@ void LGapResolver::EmitMove(int index) {
} else { } else {
ASSERT(destination->IsStackSlot()); ASSERT(destination->IsStackSlot());
ASSERT(!in_cycle_); // Constant moves happen after all cycles are gone. ASSERT(!in_cycle_); // Constant moves happen after all cycles are gone.
MemOperand destination_operand = cgen_->ToMemOperand(destination);
__ mov(kSavedValueRegister, source_operand); __ mov(kSavedValueRegister, source_operand);
__ str(kSavedValueRegister, cgen_->ToMemOperand(destination)); __ str(kSavedValueRegister, cgen_->ToMemOperand(destination));
} }
@ -265,8 +264,7 @@ void LGapResolver::EmitMove(int index) {
__ vmov(cgen_->ToDoubleRegister(destination), source_register); __ vmov(cgen_->ToDoubleRegister(destination), source_register);
} else { } else {
ASSERT(destination->IsDoubleStackSlot()); ASSERT(destination->IsDoubleStackSlot());
MemOperand destination_operand = cgen_->ToMemOperand(destination); __ vstr(source_register, cgen_->ToMemOperand(destination));
__ vstr(source_register, destination_operand);
} }
} else if (source->IsDoubleStackSlot()) { } else if (source->IsDoubleStackSlot()) {

5
deps/v8/src/arm/stub-cache-arm.cc

@ -1183,9 +1183,8 @@ void StubCompiler::GenerateLoadConstant(JSObject* object,
__ JumpIfSmi(receiver, miss); __ JumpIfSmi(receiver, miss);
// Check that the maps haven't changed. // Check that the maps haven't changed.
Register reg = CheckPrototypes(object, receiver, holder, scratch1, scratch2, scratch3, name,
CheckPrototypes(object, receiver, holder, miss);
scratch1, scratch2, scratch3, name, miss);
// Return the constant value. // Return the constant value.
__ mov(r0, Operand(Handle<Object>(value))); __ mov(r0, Operand(Handle<Object>(value)));

47
deps/v8/src/ast.cc

@ -139,8 +139,7 @@ Assignment::Assignment(Isolate* isolate,
assignment_id_(GetNextId(isolate)), assignment_id_(GetNextId(isolate)),
block_start_(false), block_start_(false),
block_end_(false), block_end_(false),
is_monomorphic_(false), is_monomorphic_(false) {
receiver_types_(NULL) {
ASSERT(Token::IsAssignmentOp(op)); ASSERT(Token::IsAssignmentOp(op));
if (is_compound()) { if (is_compound()) {
binary_operation_ = binary_operation_ =
@ -652,6 +651,7 @@ bool CountOperation::IsInlineable() const {
void Property::RecordTypeFeedback(TypeFeedbackOracle* oracle) { void Property::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
// Record type feedback from the oracle in the AST. // Record type feedback from the oracle in the AST.
is_monomorphic_ = oracle->LoadIsMonomorphicNormal(this); is_monomorphic_ = oracle->LoadIsMonomorphicNormal(this);
receiver_types_.Clear();
if (key()->IsPropertyName()) { if (key()->IsPropertyName()) {
if (oracle->LoadIsBuiltin(this, Builtins::kLoadIC_ArrayLength)) { if (oracle->LoadIsBuiltin(this, Builtins::kLoadIC_ArrayLength)) {
is_array_length_ = true; is_array_length_ = true;
@ -664,16 +664,15 @@ void Property::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
Literal* lit_key = key()->AsLiteral(); Literal* lit_key = key()->AsLiteral();
ASSERT(lit_key != NULL && lit_key->handle()->IsString()); ASSERT(lit_key != NULL && lit_key->handle()->IsString());
Handle<String> name = Handle<String>::cast(lit_key->handle()); Handle<String> name = Handle<String>::cast(lit_key->handle());
ZoneMapList* types = oracle->LoadReceiverTypes(this, name); oracle->LoadReceiverTypes(this, name, &receiver_types_);
receiver_types_ = types;
} }
} else if (oracle->LoadIsBuiltin(this, Builtins::kKeyedLoadIC_String)) { } else if (oracle->LoadIsBuiltin(this, Builtins::kKeyedLoadIC_String)) {
is_string_access_ = true; is_string_access_ = true;
} else if (is_monomorphic_) { } else if (is_monomorphic_) {
monomorphic_receiver_type_ = oracle->LoadMonomorphicReceiverType(this); receiver_types_.Add(oracle->LoadMonomorphicReceiverType(this));
} else if (oracle->LoadIsMegamorphicWithTypeInfo(this)) { } else if (oracle->LoadIsMegamorphicWithTypeInfo(this)) {
receiver_types_ = new ZoneMapList(kMaxKeyedPolymorphism); receiver_types_.Reserve(kMaxKeyedPolymorphism);
oracle->CollectKeyedReceiverTypes(this->id(), receiver_types_); oracle->CollectKeyedReceiverTypes(this->id(), &receiver_types_);
} }
} }
@ -682,30 +681,31 @@ void Assignment::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
Property* prop = target()->AsProperty(); Property* prop = target()->AsProperty();
ASSERT(prop != NULL); ASSERT(prop != NULL);
is_monomorphic_ = oracle->StoreIsMonomorphicNormal(this); is_monomorphic_ = oracle->StoreIsMonomorphicNormal(this);
receiver_types_.Clear();
if (prop->key()->IsPropertyName()) { if (prop->key()->IsPropertyName()) {
Literal* lit_key = prop->key()->AsLiteral(); Literal* lit_key = prop->key()->AsLiteral();
ASSERT(lit_key != NULL && lit_key->handle()->IsString()); ASSERT(lit_key != NULL && lit_key->handle()->IsString());
Handle<String> name = Handle<String>::cast(lit_key->handle()); Handle<String> name = Handle<String>::cast(lit_key->handle());
ZoneMapList* types = oracle->StoreReceiverTypes(this, name); oracle->StoreReceiverTypes(this, name, &receiver_types_);
receiver_types_ = types;
} else if (is_monomorphic_) { } else if (is_monomorphic_) {
// Record receiver type for monomorphic keyed stores. // Record receiver type for monomorphic keyed stores.
monomorphic_receiver_type_ = oracle->StoreMonomorphicReceiverType(this); receiver_types_.Add(oracle->StoreMonomorphicReceiverType(this));
} else if (oracle->StoreIsMegamorphicWithTypeInfo(this)) { } else if (oracle->StoreIsMegamorphicWithTypeInfo(this)) {
receiver_types_ = new ZoneMapList(kMaxKeyedPolymorphism); receiver_types_.Reserve(kMaxKeyedPolymorphism);
oracle->CollectKeyedReceiverTypes(this->id(), receiver_types_); oracle->CollectKeyedReceiverTypes(this->id(), &receiver_types_);
} }
} }
void CountOperation::RecordTypeFeedback(TypeFeedbackOracle* oracle) { void CountOperation::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
is_monomorphic_ = oracle->StoreIsMonomorphicNormal(this); is_monomorphic_ = oracle->StoreIsMonomorphicNormal(this);
receiver_types_.Clear();
if (is_monomorphic_) { if (is_monomorphic_) {
// Record receiver type for monomorphic keyed stores. // Record receiver type for monomorphic keyed stores.
monomorphic_receiver_type_ = oracle->StoreMonomorphicReceiverType(this); receiver_types_.Add(oracle->StoreMonomorphicReceiverType(this));
} else if (oracle->StoreIsMegamorphicWithTypeInfo(this)) { } else if (oracle->StoreIsMegamorphicWithTypeInfo(this)) {
receiver_types_ = new ZoneMapList(kMaxKeyedPolymorphism); receiver_types_.Reserve(kMaxKeyedPolymorphism);
oracle->CollectKeyedReceiverTypes(this->id(), receiver_types_); oracle->CollectKeyedReceiverTypes(this->id(), &receiver_types_);
} }
} }
@ -789,15 +789,14 @@ void Call::RecordTypeFeedback(TypeFeedbackOracle* oracle,
Literal* key = property->key()->AsLiteral(); Literal* key = property->key()->AsLiteral();
ASSERT(key != NULL && key->handle()->IsString()); ASSERT(key != NULL && key->handle()->IsString());
Handle<String> name = Handle<String>::cast(key->handle()); Handle<String> name = Handle<String>::cast(key->handle());
receiver_types_ = oracle->CallReceiverTypes(this, name, call_kind); receiver_types_.Clear();
oracle->CallReceiverTypes(this, name, call_kind, &receiver_types_);
#ifdef DEBUG #ifdef DEBUG
if (FLAG_enable_slow_asserts) { if (FLAG_enable_slow_asserts) {
if (receiver_types_ != NULL) { int length = receiver_types_.length();
int length = receiver_types_->length(); for (int i = 0; i < length; i++) {
for (int i = 0; i < length; i++) { Handle<Map> map = receiver_types_.at(i);
Handle<Map> map = receiver_types_->at(i); ASSERT(!map.is_null() && *map != NULL);
ASSERT(!map.is_null() && *map != NULL);
}
} }
} }
#endif #endif
@ -805,9 +804,9 @@ void Call::RecordTypeFeedback(TypeFeedbackOracle* oracle,
check_type_ = oracle->GetCallCheckType(this); check_type_ = oracle->GetCallCheckType(this);
if (is_monomorphic_) { if (is_monomorphic_) {
Handle<Map> map; Handle<Map> map;
if (receiver_types_ != NULL && receiver_types_->length() > 0) { if (receiver_types_.length() > 0) {
ASSERT(check_type_ == RECEIVER_MAP_CHECK); ASSERT(check_type_ == RECEIVER_MAP_CHECK);
map = receiver_types_->at(0); map = receiver_types_.at(0);
} else { } else {
ASSERT(check_type_ != RECEIVER_MAP_CHECK); ASSERT(check_type_ != RECEIVER_MAP_CHECK);
holder_ = Handle<JSObject>( holder_ = Handle<JSObject>(

74
deps/v8/src/ast.h

@ -33,6 +33,7 @@
#include "factory.h" #include "factory.h"
#include "jsregexp.h" #include "jsregexp.h"
#include "runtime.h" #include "runtime.h"
#include "small-pointer-list.h"
#include "token.h" #include "token.h"
#include "variables.h" #include "variables.h"
@ -207,6 +208,36 @@ class Statement: public AstNode {
}; };
class SmallMapList {
public:
SmallMapList() {}
explicit SmallMapList(int capacity) : list_(capacity) {}
void Reserve(int capacity) { list_.Reserve(capacity); }
void Clear() { list_.Clear(); }
bool is_empty() const { return list_.is_empty(); }
int length() const { return list_.length(); }
void Add(Handle<Map> handle) {
list_.Add(handle.location());
}
Handle<Map> at(int i) const {
return Handle<Map>(list_.at(i));
}
Handle<Map> first() const { return at(0); }
Handle<Map> last() const { return at(length() - 1); }
private:
// The list stores pointers to Map*, that is Map**, so it's GC safe.
SmallPointerList<Map*> list_;
DISALLOW_COPY_AND_ASSIGN(SmallMapList);
};
class Expression: public AstNode { class Expression: public AstNode {
public: public:
enum Context { enum Context {
@ -265,13 +296,15 @@ class Expression: public AstNode {
UNREACHABLE(); UNREACHABLE();
return false; return false;
} }
virtual ZoneMapList* GetReceiverTypes() { virtual SmallMapList* GetReceiverTypes() {
UNREACHABLE(); UNREACHABLE();
return NULL; return NULL;
} }
virtual Handle<Map> GetMonomorphicReceiverType() { Handle<Map> GetMonomorphicReceiverType() {
UNREACHABLE(); ASSERT(IsMonomorphic());
return Handle<Map>(); SmallMapList* types = GetReceiverTypes();
ASSERT(types != NULL && types->length() == 1);
return types->at(0);
} }
unsigned id() const { return id_; } unsigned id() const { return id_; }
@ -1213,7 +1246,6 @@ class Property: public Expression {
key_(key), key_(key),
pos_(pos), pos_(pos),
type_(type), type_(type),
receiver_types_(NULL),
is_monomorphic_(false), is_monomorphic_(false),
is_array_length_(false), is_array_length_(false),
is_string_length_(false), is_string_length_(false),
@ -1237,11 +1269,8 @@ class Property: public Expression {
// Type feedback information. // Type feedback information.
void RecordTypeFeedback(TypeFeedbackOracle* oracle); void RecordTypeFeedback(TypeFeedbackOracle* oracle);
virtual bool IsMonomorphic() { return is_monomorphic_; } virtual bool IsMonomorphic() { return is_monomorphic_; }
virtual ZoneMapList* GetReceiverTypes() { return receiver_types_; } virtual SmallMapList* GetReceiverTypes() { return &receiver_types_; }
virtual bool IsArrayLength() { return is_array_length_; } virtual bool IsArrayLength() { return is_array_length_; }
virtual Handle<Map> GetMonomorphicReceiverType() {
return monomorphic_receiver_type_;
}
private: private:
Expression* obj_; Expression* obj_;
@ -1249,13 +1278,12 @@ class Property: public Expression {
int pos_; int pos_;
Type type_; Type type_;
ZoneMapList* receiver_types_; SmallMapList receiver_types_;
bool is_monomorphic_ : 1; bool is_monomorphic_ : 1;
bool is_array_length_ : 1; bool is_array_length_ : 1;
bool is_string_length_ : 1; bool is_string_length_ : 1;
bool is_string_access_ : 1; bool is_string_access_ : 1;
bool is_function_prototype_ : 1; bool is_function_prototype_ : 1;
Handle<Map> monomorphic_receiver_type_;
}; };
@ -1271,7 +1299,6 @@ class Call: public Expression {
pos_(pos), pos_(pos),
is_monomorphic_(false), is_monomorphic_(false),
check_type_(RECEIVER_MAP_CHECK), check_type_(RECEIVER_MAP_CHECK),
receiver_types_(NULL),
return_id_(GetNextId(isolate)) { return_id_(GetNextId(isolate)) {
} }
@ -1285,7 +1312,7 @@ class Call: public Expression {
void RecordTypeFeedback(TypeFeedbackOracle* oracle, void RecordTypeFeedback(TypeFeedbackOracle* oracle,
CallKind call_kind); CallKind call_kind);
virtual ZoneMapList* GetReceiverTypes() { return receiver_types_; } virtual SmallMapList* GetReceiverTypes() { return &receiver_types_; }
virtual bool IsMonomorphic() { return is_monomorphic_; } virtual bool IsMonomorphic() { return is_monomorphic_; }
CheckType check_type() const { return check_type_; } CheckType check_type() const { return check_type_; }
Handle<JSFunction> target() { return target_; } Handle<JSFunction> target() { return target_; }
@ -1310,7 +1337,7 @@ class Call: public Expression {
bool is_monomorphic_; bool is_monomorphic_;
CheckType check_type_; CheckType check_type_;
ZoneMapList* receiver_types_; SmallMapList receiver_types_;
Handle<JSFunction> target_; Handle<JSFunction> target_;
Handle<JSObject> holder_; Handle<JSObject> holder_;
Handle<JSGlobalPropertyCell> cell_; Handle<JSGlobalPropertyCell> cell_;
@ -1485,8 +1512,7 @@ class CountOperation: public Expression {
expression_(expr), expression_(expr),
pos_(pos), pos_(pos),
assignment_id_(GetNextId(isolate)), assignment_id_(GetNextId(isolate)),
count_id_(GetNextId(isolate)), count_id_(GetNextId(isolate)) {}
receiver_types_(NULL) { }
DECLARE_NODE_TYPE(CountOperation) DECLARE_NODE_TYPE(CountOperation)
@ -1507,10 +1533,7 @@ class CountOperation: public Expression {
void RecordTypeFeedback(TypeFeedbackOracle* oracle); void RecordTypeFeedback(TypeFeedbackOracle* oracle);
virtual bool IsMonomorphic() { return is_monomorphic_; } virtual bool IsMonomorphic() { return is_monomorphic_; }
virtual Handle<Map> GetMonomorphicReceiverType() { virtual SmallMapList* GetReceiverTypes() { return &receiver_types_; }
return monomorphic_receiver_type_;
}
virtual ZoneMapList* GetReceiverTypes() { return receiver_types_; }
// Bailout support. // Bailout support.
int AssignmentId() const { return assignment_id_; } int AssignmentId() const { return assignment_id_; }
@ -1524,8 +1547,7 @@ class CountOperation: public Expression {
int pos_; int pos_;
int assignment_id_; int assignment_id_;
int count_id_; int count_id_;
Handle<Map> monomorphic_receiver_type_; SmallMapList receiver_types_;
ZoneMapList* receiver_types_;
}; };
@ -1673,10 +1695,7 @@ class Assignment: public Expression {
// Type feedback information. // Type feedback information.
void RecordTypeFeedback(TypeFeedbackOracle* oracle); void RecordTypeFeedback(TypeFeedbackOracle* oracle);
virtual bool IsMonomorphic() { return is_monomorphic_; } virtual bool IsMonomorphic() { return is_monomorphic_; }
virtual ZoneMapList* GetReceiverTypes() { return receiver_types_; } virtual SmallMapList* GetReceiverTypes() { return &receiver_types_; }
virtual Handle<Map> GetMonomorphicReceiverType() {
return monomorphic_receiver_type_;
}
// Bailout support. // Bailout support.
int CompoundLoadId() const { return compound_load_id_; } int CompoundLoadId() const { return compound_load_id_; }
@ -1695,8 +1714,7 @@ class Assignment: public Expression {
bool block_end_; bool block_end_;
bool is_monomorphic_; bool is_monomorphic_;
ZoneMapList* receiver_types_; SmallMapList receiver_types_;
Handle<Map> monomorphic_receiver_type_;
}; };

0
deps/v8/src/compiler.cc

6
deps/v8/src/d8.cc

@ -1237,8 +1237,6 @@ int Shell::RunMain(int argc, char* argv[]) {
thread->Join(); thread->Join();
delete thread; delete thread;
} }
OnExit();
#endif // V8_SHARED #endif // V8_SHARED
return 0; return 0;
} }
@ -1290,6 +1288,10 @@ int Shell::Main(int argc, char* argv[]) {
V8::Dispose(); V8::Dispose();
#ifndef V8_SHARED
OnExit();
#endif // V8_SHARED
return result; return result;
} }

8
deps/v8/src/handles.cc

@ -617,15 +617,17 @@ Handle<FixedArray> CalculateLineEnds(Handle<String> src,
{ {
AssertNoAllocation no_heap_allocation; // ensure vectors stay valid. AssertNoAllocation no_heap_allocation; // ensure vectors stay valid.
// Dispatch on type of strings. // Dispatch on type of strings.
if (src->IsAsciiRepresentation()) { String::FlatContent content = src->GetFlatContent();
ASSERT(content.IsFlat());
if (content.IsAscii()) {
CalculateLineEnds(isolate, CalculateLineEnds(isolate,
&line_ends, &line_ends,
src->ToAsciiVector(), content.ToAsciiVector(),
with_last_line); with_last_line);
} else { } else {
CalculateLineEnds(isolate, CalculateLineEnds(isolate,
&line_ends, &line_ends,
src->ToUC16Vector(), content.ToUC16Vector(),
with_last_line); with_last_line);
} }
} }

23
deps/v8/src/hydrogen-instructions.cc

@ -641,6 +641,7 @@ void HBoundsCheck::PrintDataTo(StringStream* stream) {
length()->PrintNameTo(stream); length()->PrintNameTo(stream);
} }
void HCallConstantFunction::PrintDataTo(StringStream* stream) { void HCallConstantFunction::PrintDataTo(StringStream* stream) {
if (IsApplyFunction()) { if (IsApplyFunction()) {
stream->Add("optimized apply "); stream->Add("optimized apply ");
@ -777,7 +778,7 @@ void HHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) {
void HTypeofIsAndBranch::PrintDataTo(StringStream* stream) { void HTypeofIsAndBranch::PrintDataTo(StringStream* stream) {
value()->PrintNameTo(stream); value()->PrintNameTo(stream);
stream->Add(" == "); stream->Add(" == ");
stream->Add(type_literal_->ToAsciiVector()); stream->Add(type_literal_->GetFlatContent().ToAsciiVector());
} }
@ -875,6 +876,21 @@ Range* HValue::InferRange() {
} }
Range* HChange::InferRange() {
Range* input_range = value()->range();
if (from().IsInteger32() &&
to().IsTagged() &&
input_range != NULL && input_range->IsInSmiRange()) {
set_type(HType::Smi());
}
Range* result = (input_range != NULL)
? input_range->Copy()
: HValue::InferRange();
if (to().IsInteger32()) result->set_can_be_minus_zero(false);
return result;
}
Range* HConstant::InferRange() { Range* HConstant::InferRange() {
if (has_int32_value_) { if (has_int32_value_) {
Range* result = new Range(int32_value_, int32_value_); Range* result = new Range(int32_value_, int32_value_);
@ -1220,6 +1236,7 @@ Range* HSar::InferRange() {
? left()->range()->Copy() ? left()->range()->Copy()
: new Range(); : new Range();
result->Sar(c->Integer32Value()); result->Sar(c->Integer32Value());
result->set_can_be_minus_zero(false);
return result; return result;
} }
} }
@ -1243,6 +1260,7 @@ Range* HShr::InferRange() {
? left()->range()->Copy() ? left()->range()->Copy()
: new Range(); : new Range();
result->Sar(c->Integer32Value()); result->Sar(c->Integer32Value());
result->set_can_be_minus_zero(false);
return result; return result;
} }
} }
@ -1259,6 +1277,7 @@ Range* HShl::InferRange() {
? left()->range()->Copy() ? left()->range()->Copy()
: new Range(); : new Range();
result->Shl(c->Integer32Value()); result->Shl(c->Integer32Value());
result->set_can_be_minus_zero(false);
return result; return result;
} }
} }
@ -1306,7 +1325,7 @@ void HLoadNamedField::PrintDataTo(StringStream* stream) {
HLoadNamedFieldPolymorphic::HLoadNamedFieldPolymorphic(HValue* context, HLoadNamedFieldPolymorphic::HLoadNamedFieldPolymorphic(HValue* context,
HValue* object, HValue* object,
ZoneMapList* types, SmallMapList* types,
Handle<String> name) Handle<String> name)
: types_(Min(types->length(), kMaxLoadPolymorphism)), : types_(Min(types->length(), kMaxLoadPolymorphism)),
name_(name), name_(name),

28
deps/v8/src/hydrogen-instructions.h

@ -227,14 +227,20 @@ class Range: public ZoneObject {
Range* next() const { return next_; } Range* next() const { return next_; }
Range* CopyClearLower() const { return new Range(kMinInt, upper_); } Range* CopyClearLower() const { return new Range(kMinInt, upper_); }
Range* CopyClearUpper() const { return new Range(lower_, kMaxInt); } Range* CopyClearUpper() const { return new Range(lower_, kMaxInt); }
Range* Copy() const { return new Range(lower_, upper_); } Range* Copy() const {
Range* result = new Range(lower_, upper_);
result->set_can_be_minus_zero(CanBeMinusZero());
return result;
}
int32_t Mask() const; int32_t Mask() const;
void set_can_be_minus_zero(bool b) { can_be_minus_zero_ = b; } void set_can_be_minus_zero(bool b) { can_be_minus_zero_ = b; }
bool CanBeMinusZero() const { return CanBeZero() && can_be_minus_zero_; } bool CanBeMinusZero() const { return CanBeZero() && can_be_minus_zero_; }
bool CanBeZero() const { return upper_ >= 0 && lower_ <= 0; } bool CanBeZero() const { return upper_ >= 0 && lower_ <= 0; }
bool CanBeNegative() const { return lower_ < 0; } bool CanBeNegative() const { return lower_ < 0; }
bool Includes(int value) const { return lower_ <= value && upper_ >= value; } bool Includes(int value) const { return lower_ <= value && upper_ >= value; }
bool IsMostGeneric() const { return lower_ == kMinInt && upper_ == kMaxInt; } bool IsMostGeneric() const {
return lower_ == kMinInt && upper_ == kMaxInt && CanBeMinusZero();
}
bool IsInSmiRange() const { bool IsInSmiRange() const {
return lower_ >= Smi::kMinValue && upper_ <= Smi::kMaxValue; return lower_ >= Smi::kMinValue && upper_ <= Smi::kMaxValue;
} }
@ -578,9 +584,9 @@ class HValue: public ZoneObject {
virtual bool IsConvertibleToInteger() const { return true; } virtual bool IsConvertibleToInteger() const { return true; }
HType type() const { return type_; } HType type() const { return type_; }
void set_type(HType type) { void set_type(HType new_type) {
ASSERT(HasNoUses()); ASSERT(new_type.IsSubtypeOf(type_));
type_ = type; type_ = new_type;
} }
// An operation needs to override this function iff: // An operation needs to override this function iff:
@ -1100,10 +1106,6 @@ class HChange: public HUnaryOperation {
set_representation(to); set_representation(to);
SetFlag(kUseGVN); SetFlag(kUseGVN);
if (is_truncating) SetFlag(kTruncatingToInt32); if (is_truncating) SetFlag(kTruncatingToInt32);
if (from.IsInteger32() && to.IsTagged() && value->range() != NULL &&
value->range()->IsInSmiRange()) {
set_type(HType::Smi());
}
} }
virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited); virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
@ -1115,6 +1117,8 @@ class HChange: public HUnaryOperation {
return from_; return from_;
} }
virtual Range* InferRange();
virtual void PrintDataTo(StringStream* stream); virtual void PrintDataTo(StringStream* stream);
DECLARE_CONCRETE_INSTRUCTION(Change) DECLARE_CONCRETE_INSTRUCTION(Change)
@ -3405,12 +3409,12 @@ class HLoadNamedFieldPolymorphic: public HTemplateInstruction<2> {
public: public:
HLoadNamedFieldPolymorphic(HValue* context, HLoadNamedFieldPolymorphic(HValue* context,
HValue* object, HValue* object,
ZoneMapList* types, SmallMapList* types,
Handle<String> name); Handle<String> name);
HValue* context() { return OperandAt(0); } HValue* context() { return OperandAt(0); }
HValue* object() { return OperandAt(1); } HValue* object() { return OperandAt(1); }
ZoneMapList* types() { return &types_; } SmallMapList* types() { return &types_; }
Handle<String> name() { return name_; } Handle<String> name() { return name_; }
bool need_generic() { return need_generic_; } bool need_generic() { return need_generic_; }
@ -3428,7 +3432,7 @@ class HLoadNamedFieldPolymorphic: public HTemplateInstruction<2> {
virtual bool DataEquals(HValue* value); virtual bool DataEquals(HValue* value);
private: private:
ZoneMapList types_; SmallMapList types_;
Handle<String> name_; Handle<String> name_;
bool need_generic_; bool need_generic_;
}; };

42
deps/v8/src/hydrogen.cc

@ -2325,20 +2325,11 @@ HGraph* HGraphBuilder::CreateGraph() {
HInferRepresentation rep(graph()); HInferRepresentation rep(graph());
rep.Analyze(); rep.Analyze();
if (FLAG_use_range) {
HRangeAnalysis rangeAnalysis(graph());
rangeAnalysis.Analyze();
}
graph()->InitializeInferredTypes();
graph()->Canonicalize();
graph()->MarkDeoptimizeOnUndefined(); graph()->MarkDeoptimizeOnUndefined();
graph()->InsertRepresentationChanges(); graph()->InsertRepresentationChanges();
graph()->ComputeMinusZeroChecks();
// Eliminate redundant stack checks on backwards branches. graph()->InitializeInferredTypes();
HStackCheckEliminator sce(graph()); graph()->Canonicalize();
sce.Process();
// Perform common subexpression elimination and loop-invariant code motion. // Perform common subexpression elimination and loop-invariant code motion.
if (FLAG_use_gvn) { if (FLAG_use_gvn) {
@ -2347,6 +2338,16 @@ HGraph* HGraphBuilder::CreateGraph() {
gvn.Analyze(); gvn.Analyze();
} }
if (FLAG_use_range) {
HRangeAnalysis rangeAnalysis(graph());
rangeAnalysis.Analyze();
}
graph()->ComputeMinusZeroChecks();
// Eliminate redundant stack checks on backwards branches.
HStackCheckEliminator sce(graph());
sce.Process();
// Replace the results of check instructions with the original value, if the // Replace the results of check instructions with the original value, if the
// result is used. This is safe now, since we don't do code motion after this // result is used. This is safe now, since we don't do code motion after this
// point. It enables better register allocation since the value produced by // point. It enables better register allocation since the value produced by
@ -3395,7 +3396,7 @@ HInstruction* HGraphBuilder::BuildStoreNamed(HValue* object,
ASSERT(!name.is_null()); ASSERT(!name.is_null());
LookupResult lookup; LookupResult lookup;
ZoneMapList* types = expr->GetReceiverTypes(); SmallMapList* types = expr->GetReceiverTypes();
bool is_monomorphic = expr->IsMonomorphic() && bool is_monomorphic = expr->IsMonomorphic() &&
ComputeStoredField(types->first(), name, &lookup); ComputeStoredField(types->first(), name, &lookup);
@ -3409,7 +3410,7 @@ HInstruction* HGraphBuilder::BuildStoreNamed(HValue* object,
void HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr, void HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr,
HValue* object, HValue* object,
HValue* value, HValue* value,
ZoneMapList* types, SmallMapList* types,
Handle<String> name) { Handle<String> name) {
// TODO(ager): We should recognize when the prototype chains for different // TODO(ager): We should recognize when the prototype chains for different
// maps are identical. In that case we can avoid repeatedly generating the // maps are identical. In that case we can avoid repeatedly generating the
@ -3500,7 +3501,7 @@ void HGraphBuilder::HandlePropertyAssignment(Assignment* expr) {
Handle<String> name = Handle<String>::cast(key->handle()); Handle<String> name = Handle<String>::cast(key->handle());
ASSERT(!name.is_null()); ASSERT(!name.is_null());
ZoneMapList* types = expr->GetReceiverTypes(); SmallMapList* types = expr->GetReceiverTypes();
LookupResult lookup; LookupResult lookup;
if (expr->IsMonomorphic()) { if (expr->IsMonomorphic()) {
@ -3986,7 +3987,7 @@ HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object,
*has_side_effects = false; *has_side_effects = false;
AddInstruction(new(zone()) HCheckNonSmi(object)); AddInstruction(new(zone()) HCheckNonSmi(object));
AddInstruction(HCheckInstanceType::NewIsSpecObject(object)); AddInstruction(HCheckInstanceType::NewIsSpecObject(object));
ZoneMapList* maps = prop->GetReceiverTypes(); SmallMapList* maps = prop->GetReceiverTypes();
bool todo_external_array = false; bool todo_external_array = false;
static const int kNumElementTypes = JSObject::kElementsKindCount; static const int kNumElementTypes = JSObject::kElementsKindCount;
@ -4260,7 +4261,7 @@ void HGraphBuilder::VisitProperty(Property* expr) {
} else if (expr->key()->IsPropertyName()) { } else if (expr->key()->IsPropertyName()) {
Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
ZoneMapList* types = expr->GetReceiverTypes(); SmallMapList* types = expr->GetReceiverTypes();
HValue* obj = Pop(); HValue* obj = Pop();
if (expr->IsMonomorphic()) { if (expr->IsMonomorphic()) {
@ -4321,7 +4322,7 @@ void HGraphBuilder::AddCheckConstantFunction(Call* expr,
void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr, void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr,
HValue* receiver, HValue* receiver,
ZoneMapList* types, SmallMapList* types,
Handle<String> name) { Handle<String> name) {
// TODO(ager): We should recognize when the prototype chains for different // TODO(ager): We should recognize when the prototype chains for different
// maps are identical. In that case we can avoid repeatedly generating the // maps are identical. In that case we can avoid repeatedly generating the
@ -4849,13 +4850,14 @@ void HGraphBuilder::VisitCall(Call* expr) {
Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
ZoneMapList* types = expr->GetReceiverTypes(); SmallMapList* types = expr->GetReceiverTypes();
HValue* receiver = HValue* receiver =
environment()->ExpressionStackAt(expr->arguments()->length()); environment()->ExpressionStackAt(expr->arguments()->length());
if (expr->IsMonomorphic()) { if (expr->IsMonomorphic()) {
Handle<Map> receiver_map = Handle<Map> receiver_map = (types == NULL || types->is_empty())
(types == NULL) ? Handle<Map>::null() : types->first(); ? Handle<Map>::null()
: types->first();
if (TryInlineBuiltinFunction(expr, if (TryInlineBuiltinFunction(expr,
receiver, receiver,
receiver_map, receiver_map,

4
deps/v8/src/hydrogen.h

@ -901,11 +901,11 @@ class HGraphBuilder: public AstVisitor {
void HandlePolymorphicStoreNamedField(Assignment* expr, void HandlePolymorphicStoreNamedField(Assignment* expr,
HValue* object, HValue* object,
HValue* value, HValue* value,
ZoneMapList* types, SmallMapList* types,
Handle<String> name); Handle<String> name);
void HandlePolymorphicCallNamed(Call* expr, void HandlePolymorphicCallNamed(Call* expr,
HValue* receiver, HValue* receiver,
ZoneMapList* types, SmallMapList* types,
Handle<String> name); Handle<String> name);
void HandleLiteralCompareTypeof(CompareOperation* compare_expr, void HandleLiteralCompareTypeof(CompareOperation* compare_expr,
Expression* expr, Expression* expr,

10
deps/v8/src/interpreter-irregexp.cc

@ -1,4 +1,4 @@
// Copyright 2008 the V8 project authors. All rights reserved. // Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -635,8 +635,9 @@ bool IrregexpInterpreter::Match(Isolate* isolate,
AssertNoAllocation a; AssertNoAllocation a;
const byte* code_base = code_array->GetDataStartAddress(); const byte* code_base = code_array->GetDataStartAddress();
uc16 previous_char = '\n'; uc16 previous_char = '\n';
if (subject->IsAsciiRepresentation()) { String::FlatContent subject_content = subject->GetFlatContent();
Vector<const char> subject_vector = subject->ToAsciiVector(); if (subject_content.IsAscii()) {
Vector<const char> subject_vector = subject_content.ToAsciiVector();
if (start_position != 0) previous_char = subject_vector[start_position - 1]; if (start_position != 0) previous_char = subject_vector[start_position - 1];
return RawMatch(isolate, return RawMatch(isolate,
code_base, code_base,
@ -645,7 +646,8 @@ bool IrregexpInterpreter::Match(Isolate* isolate,
start_position, start_position,
previous_char); previous_char);
} else { } else {
Vector<const uc16> subject_vector = subject->ToUC16Vector(); ASSERT(subject_content.IsTwoByte());
Vector<const uc16> subject_vector = subject_content.ToUC16Vector();
if (start_position != 0) previous_char = subject_vector[start_position - 1]; if (start_position != 0) previous_char = subject_vector[start_position - 1];
return RawMatch(isolate, return RawMatch(isolate,
code_base, code_base,

46
deps/v8/src/jsregexp.cc

@ -212,19 +212,7 @@ static void SetAtomLastCapture(FixedArray* array,
RegExpImpl::SetCapture(array, 1, to); RegExpImpl::SetCapture(array, 1, to);
} }
/* template <typename SubjectChar>, typename PatternChar>
static int ReStringMatch(Vector<const SubjectChar> sub_vector,
Vector<const PatternChar> pat_vector,
int start_index) {
int pattern_length = pat_vector.length();
if (pattern_length == 0) return start_index;
int subject_length = sub_vector.length();
if (start_index + pattern_length > subject_length) return -1;
return SearchString(sub_vector, pat_vector, start_index);
}
*/
Handle<Object> RegExpImpl::AtomExec(Handle<JSRegExp> re, Handle<Object> RegExpImpl::AtomExec(Handle<JSRegExp> re,
Handle<String> subject, Handle<String> subject,
int index, int index,
@ -237,35 +225,39 @@ Handle<Object> RegExpImpl::AtomExec(Handle<JSRegExp> re,
if (!subject->IsFlat()) FlattenString(subject); if (!subject->IsFlat()) FlattenString(subject);
AssertNoAllocation no_heap_allocation; // ensure vectors stay valid AssertNoAllocation no_heap_allocation; // ensure vectors stay valid
// Extract flattened substrings of cons strings before determining asciiness. // Extract flattened substrings of cons strings before determining asciiness.
String* seq_sub = *subject;
if (seq_sub->IsConsString()) seq_sub = ConsString::cast(seq_sub)->first();
String* needle = String::cast(re->DataAt(JSRegExp::kAtomPatternIndex)); String* needle = String::cast(re->DataAt(JSRegExp::kAtomPatternIndex));
int needle_len = needle->length(); int needle_len = needle->length();
ASSERT(needle->IsFlat());
if (needle_len != 0) { if (needle_len != 0) {
if (index + needle_len > subject->length()) if (index + needle_len > subject->length()) {
return isolate->factory()->null_value(); return isolate->factory()->null_value();
}
String::FlatContent needle_content = needle->GetFlatContent();
String::FlatContent subject_content = subject->GetFlatContent();
ASSERT(needle_content.IsFlat());
ASSERT(subject_content.IsFlat());
// dispatch on type of strings // dispatch on type of strings
index = (needle->IsAsciiRepresentation() index = (needle_content.IsAscii()
? (seq_sub->IsAsciiRepresentation() ? (subject_content.IsAscii()
? SearchString(isolate, ? SearchString(isolate,
seq_sub->ToAsciiVector(), subject_content.ToAsciiVector(),
needle->ToAsciiVector(), needle_content.ToAsciiVector(),
index) index)
: SearchString(isolate, : SearchString(isolate,
seq_sub->ToUC16Vector(), subject_content.ToUC16Vector(),
needle->ToAsciiVector(), needle_content.ToAsciiVector(),
index)) index))
: (seq_sub->IsAsciiRepresentation() : (subject_content.IsAscii()
? SearchString(isolate, ? SearchString(isolate,
seq_sub->ToAsciiVector(), subject_content.ToAsciiVector(),
needle->ToUC16Vector(), needle_content.ToUC16Vector(),
index) index)
: SearchString(isolate, : SearchString(isolate,
seq_sub->ToUC16Vector(), subject_content.ToUC16Vector(),
needle->ToUC16Vector(), needle_content.ToUC16Vector(),
index))); index)));
if (index == -1) return isolate->factory()->null_value(); if (index == -1) return isolate->factory()->null_value();
} }

12
deps/v8/src/messages.js

@ -57,11 +57,13 @@ function FormatString(format, message) {
for (var i = 0; i < format.length; i++) { for (var i = 0; i < format.length; i++) {
var str = format[i]; var str = format[i];
for (arg_num = 0; arg_num < kReplacementMarkers.length; arg_num++) { for (arg_num = 0; arg_num < kReplacementMarkers.length; arg_num++) {
if (str !== kReplacementMarkers[arg_num]) continue; if (str == kReplacementMarkers[arg_num]) {
try { try {
str = ToDetailString(args[arg_num]); str = ToDetailString(args[arg_num]);
} catch (e) { } catch (e) {
str = "#<error>"; str = "#<error>";
}
break;
} }
} }
result += str; result += str;

5
deps/v8/src/objects-inl.h

@ -297,6 +297,11 @@ StringRepresentationTag StringShape::representation_tag() {
} }
uint32_t StringShape::encoding_tag() {
return type_ & kStringEncodingMask;
}
uint32_t StringShape::full_representation_tag() { uint32_t StringShape::full_representation_tag() {
return (type_ & (kStringRepresentationMask | kStringEncodingMask)); return (type_ & (kStringRepresentationMask | kStringEncodingMask));
} }

121
deps/v8/src/objects.cc

@ -5038,55 +5038,36 @@ int String::Utf8Length() {
} }
Vector<const char> String::ToAsciiVector() { String::FlatContent String::GetFlatContent() {
ASSERT(IsAsciiRepresentation());
ASSERT(IsFlat());
int offset = 0;
int length = this->length(); int length = this->length();
StringRepresentationTag string_tag = StringShape(this).representation_tag(); StringShape shape(this);
String* string = this; String* string = this;
if (string_tag == kConsStringTag) { if (shape.representation_tag() == kConsStringTag) {
ConsString* cons = ConsString::cast(string); ConsString* cons = ConsString::cast(string);
ASSERT(cons->second()->length() == 0); if (cons->second()->length() != 0) {
string = cons->first(); return FlatContent();
string_tag = StringShape(string).representation_tag(); }
}
if (string_tag == kSeqStringTag) {
SeqAsciiString* seq = SeqAsciiString::cast(string);
char* start = seq->GetChars();
return Vector<const char>(start + offset, length);
}
ASSERT(string_tag == kExternalStringTag);
ExternalAsciiString* ext = ExternalAsciiString::cast(string);
const char* start = ext->resource()->data();
return Vector<const char>(start + offset, length);
}
Vector<const uc16> String::ToUC16Vector() {
ASSERT(IsTwoByteRepresentation());
ASSERT(IsFlat());
int offset = 0;
int length = this->length();
StringRepresentationTag string_tag = StringShape(this).representation_tag();
String* string = this;
if (string_tag == kConsStringTag) {
ConsString* cons = ConsString::cast(string);
ASSERT(cons->second()->length() == 0);
string = cons->first(); string = cons->first();
string_tag = StringShape(string).representation_tag(); shape = StringShape(string);
} }
if (string_tag == kSeqStringTag) { if (shape.encoding_tag() == kAsciiStringTag) {
SeqTwoByteString* seq = SeqTwoByteString::cast(string); const char* start;
return Vector<const uc16>(seq->GetChars() + offset, length); if (shape.representation_tag() == kSeqStringTag) {
start = SeqAsciiString::cast(string)->GetChars();
} else {
start = ExternalAsciiString::cast(string)->resource()->data();
}
return FlatContent(Vector<const char>(start, length));
} else {
ASSERT(shape.encoding_tag() == kTwoByteStringTag);
const uc16* start;
if (shape.representation_tag() == kSeqStringTag) {
start = SeqTwoByteString::cast(string)->GetChars();
} else {
start = ExternalTwoByteString::cast(string)->resource()->data();
}
return FlatContent(Vector<const uc16>(start, length));
} }
ASSERT(string_tag == kExternalStringTag);
ExternalTwoByteString* ext = ExternalTwoByteString::cast(string);
const uc16* start =
reinterpret_cast<const uc16*>(ext->resource()->data());
return Vector<const uc16>(start + offset, length);
} }
@ -5536,11 +5517,13 @@ void FlatStringReader::PostGarbageCollection() {
if (str_ == NULL) return; if (str_ == NULL) return;
Handle<String> str(str_); Handle<String> str(str_);
ASSERT(str->IsFlat()); ASSERT(str->IsFlat());
is_ascii_ = str->IsAsciiRepresentation(); String::FlatContent content = str->GetFlatContent();
ASSERT(content.IsFlat());
is_ascii_ = content.IsAscii();
if (is_ascii_) { if (is_ascii_) {
start_ = str->ToAsciiVector().start(); start_ = content.ToAsciiVector().start();
} else { } else {
start_ = str->ToUC16Vector().start(); start_ = content.ToUC16Vector().start();
} }
} }
@ -5860,12 +5843,13 @@ template <typename IteratorA>
static inline bool CompareStringContentsPartial(Isolate* isolate, static inline bool CompareStringContentsPartial(Isolate* isolate,
IteratorA* ia, IteratorA* ia,
String* b) { String* b) {
if (b->IsFlat()) { String::FlatContent content = b->GetFlatContent();
if (b->IsAsciiRepresentation()) { if (content.IsFlat()) {
VectorIterator<char> ib(b->ToAsciiVector()); if (content.IsAscii()) {
VectorIterator<char> ib(content.ToAsciiVector());
return CompareStringContents(ia, &ib); return CompareStringContents(ia, &ib);
} else { } else {
VectorIterator<uc16> ib(b->ToUC16Vector()); VectorIterator<uc16> ib(content.ToUC16Vector());
return CompareStringContents(ia, &ib); return CompareStringContents(ia, &ib);
} }
} else { } else {
@ -5904,16 +5888,18 @@ bool String::SlowEquals(String* other) {
} }
Isolate* isolate = GetIsolate(); Isolate* isolate = GetIsolate();
if (lhs->IsFlat()) { String::FlatContent lhs_content = lhs->GetFlatContent();
if (lhs->IsAsciiRepresentation()) { String::FlatContent rhs_content = rhs->GetFlatContent();
Vector<const char> vec1 = lhs->ToAsciiVector(); if (lhs_content.IsFlat()) {
if (rhs->IsFlat()) { if (lhs_content.IsAscii()) {
if (rhs->IsAsciiRepresentation()) { Vector<const char> vec1 = lhs_content.ToAsciiVector();
Vector<const char> vec2 = rhs->ToAsciiVector(); if (rhs_content.IsFlat()) {
if (rhs_content.IsAscii()) {
Vector<const char> vec2 = rhs_content.ToAsciiVector();
return CompareRawStringContents(vec1, vec2); return CompareRawStringContents(vec1, vec2);
} else { } else {
VectorIterator<char> buf1(vec1); VectorIterator<char> buf1(vec1);
VectorIterator<uc16> ib(rhs->ToUC16Vector()); VectorIterator<uc16> ib(rhs_content.ToUC16Vector());
return CompareStringContents(&buf1, &ib); return CompareStringContents(&buf1, &ib);
} }
} else { } else {
@ -5923,14 +5909,14 @@ bool String::SlowEquals(String* other) {
isolate->objects_string_compare_buffer_b()); isolate->objects_string_compare_buffer_b());
} }
} else { } else {
Vector<const uc16> vec1 = lhs->ToUC16Vector(); Vector<const uc16> vec1 = lhs_content.ToUC16Vector();
if (rhs->IsFlat()) { if (rhs_content.IsFlat()) {
if (rhs->IsAsciiRepresentation()) { if (rhs_content.IsAscii()) {
VectorIterator<uc16> buf1(vec1); VectorIterator<uc16> buf1(vec1);
VectorIterator<char> ib(rhs->ToAsciiVector()); VectorIterator<char> ib(rhs_content.ToAsciiVector());
return CompareStringContents(&buf1, &ib); return CompareStringContents(&buf1, &ib);
} else { } else {
Vector<const uc16> vec2(rhs->ToUC16Vector()); Vector<const uc16> vec2(rhs_content.ToUC16Vector());
return CompareRawStringContents(vec1, vec2); return CompareRawStringContents(vec1, vec2);
} }
} else { } else {
@ -5983,8 +5969,10 @@ bool String::IsEqualTo(Vector<const char> str) {
bool String::IsAsciiEqualTo(Vector<const char> str) { bool String::IsAsciiEqualTo(Vector<const char> str) {
int slen = length(); int slen = length();
if (str.length() != slen) return false; if (str.length() != slen) return false;
if (IsFlat() && IsAsciiRepresentation()) { FlatContent content = GetFlatContent();
return CompareChars(ToAsciiVector().start(), str.start(), slen) == 0; if (content.IsAscii()) {
return CompareChars(content.ToAsciiVector().start(),
str.start(), slen) == 0;
} }
for (int i = 0; i < slen; i++) { for (int i = 0; i < slen; i++) {
if (Get(i) != static_cast<uint16_t>(str[i])) return false; if (Get(i) != static_cast<uint16_t>(str[i])) return false;
@ -5996,8 +5984,9 @@ bool String::IsAsciiEqualTo(Vector<const char> str) {
bool String::IsTwoByteEqualTo(Vector<const uc16> str) { bool String::IsTwoByteEqualTo(Vector<const uc16> str) {
int slen = length(); int slen = length();
if (str.length() != slen) return false; if (str.length() != slen) return false;
if (IsFlat() && IsTwoByteRepresentation()) { FlatContent content = GetFlatContent();
return CompareChars(ToUC16Vector().start(), str.start(), slen) == 0; if (content.IsTwoByte()) {
return CompareChars(content.ToUC16Vector().start(), str.start(), slen) == 0;
} }
for (int i = 0; i < slen; i++) { for (int i = 0; i < slen; i++) {
if (Get(i) != str[i]) return false; if (Get(i) != str[i]) return false;

60
deps/v8/src/objects.h

@ -5789,6 +5789,7 @@ class StringShape BASE_EMBEDDED {
inline bool IsSequentialTwoByte(); inline bool IsSequentialTwoByte();
inline bool IsSymbol(); inline bool IsSymbol();
inline StringRepresentationTag representation_tag(); inline StringRepresentationTag representation_tag();
inline uint32_t encoding_tag();
inline uint32_t full_representation_tag(); inline uint32_t full_representation_tag();
inline uint32_t size_tag(); inline uint32_t size_tag();
#ifdef DEBUG #ifdef DEBUG
@ -5820,6 +5821,51 @@ class StringShape BASE_EMBEDDED {
// All string values have a length field. // All string values have a length field.
class String: public HeapObject { class String: public HeapObject {
public: public:
// Representation of the flat content of a String.
// A non-flat string doesn't have flat content.
// A flat string has content that's encoded as a sequence of either
// ASCII chars or two-byte UC16.
// Returned by String::GetFlatContent().
class FlatContent {
public:
// Returns true if the string is flat and this structure contains content.
bool IsFlat() { return state_ != NON_FLAT; }
// Returns true if the structure contains ASCII content.
bool IsAscii() { return state_ == ASCII; }
// Returns true if the structure contains two-byte content.
bool IsTwoByte() { return state_ == TWO_BYTE; }
// Return the ASCII content of the string. Only use if IsAscii() returns
// true.
Vector<const char> ToAsciiVector() {
ASSERT_EQ(ASCII, state_);
return Vector<const char>::cast(buffer_);
}
// Return the two-byte content of the string. Only use if IsTwoByte()
// returns true.
Vector<const uc16> ToUC16Vector() {
ASSERT_EQ(TWO_BYTE, state_);
return Vector<const uc16>::cast(buffer_);
}
private:
enum State { NON_FLAT, ASCII, TWO_BYTE };
// Constructors only used by String::GetFlatContent().
explicit FlatContent(Vector<const char> chars)
: buffer_(Vector<const byte>::cast(chars)),
state_(ASCII) { }
explicit FlatContent(Vector<const uc16> chars)
: buffer_(Vector<const byte>::cast(chars)),
state_(TWO_BYTE) { }
FlatContent() : buffer_(), state_(NON_FLAT) { }
Vector<const byte> buffer_;
State state_;
friend class String;
};
// Get and set the length of the string. // Get and set the length of the string.
inline int length(); inline int length();
inline void set_length(int value); inline void set_length(int value);
@ -5831,10 +5877,10 @@ class String: public HeapObject {
inline bool IsAsciiRepresentation(); inline bool IsAsciiRepresentation();
inline bool IsTwoByteRepresentation(); inline bool IsTwoByteRepresentation();
// Returns whether this string has ascii chars, i.e. all of them can // Returns whether this string has only ASCII chars, i.e. all of them can
// be ascii encoded. This might be the case even if the string is // be ASCII encoded. This might be the case even if the string is
// two-byte. Such strings may appear when the embedder prefers // two-byte. Such strings may appear when the embedder prefers
// two-byte external representations even for ascii data. // two-byte external representations even for ASCII data.
// //
// NOTE: this should be considered only a hint. False negatives are // NOTE: this should be considered only a hint. False negatives are
// possible. // possible.
@ -5868,8 +5914,12 @@ class String: public HeapObject {
// string. // string.
inline String* TryFlattenGetString(PretenureFlag pretenure = NOT_TENURED); inline String* TryFlattenGetString(PretenureFlag pretenure = NOT_TENURED);
Vector<const char> ToAsciiVector(); // Tries to return the content of a flat string as a structure holding either
Vector<const uc16> ToUC16Vector(); // a flat vector of char or of uc16.
// If the string isn't flat, and therefore doesn't have flat content, the
// returned structure will report so, and can't provide a vector of either
// kind.
FlatContent GetFlatContent();
// Mark the string as an undetectable object. It only applies to // Mark the string as an undetectable object. It only applies to
// ascii and two byte string types. // ascii and two byte string types.

36
deps/v8/src/profile-generator.cc

@ -1663,7 +1663,7 @@ HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object,
} else if (object->IsJSGlobalObject()) { } else if (object->IsJSGlobalObject()) {
const char* tag = objects_tags_.GetTag(object); const char* tag = objects_tags_.GetTag(object);
const char* name = collection_->names()->GetName( const char* name = collection_->names()->GetName(
GetConstructorNameForHeapProfile(JSObject::cast(object))); GetConstructorName(JSObject::cast(object)));
if (tag != NULL) { if (tag != NULL) {
name = collection_->names()->GetFormatted("%s / %s", name, tag); name = collection_->names()->GetFormatted("%s / %s", name, tag);
} }
@ -1691,8 +1691,7 @@ HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object,
return AddEntry(object, return AddEntry(object,
HeapEntry::kObject, HeapEntry::kObject,
collection_->names()->GetName( collection_->names()->GetName(
GetConstructorNameForHeapProfile( GetConstructorName(JSObject::cast(object))),
JSObject::cast(object))),
children_count, children_count,
retainers_count); retainers_count);
} else if (object->IsString()) { } else if (object->IsString()) {
@ -2101,6 +2100,31 @@ void V8HeapExplorer::ExtractInternalReferences(JSObject* js_obj,
} }
String* V8HeapExplorer::GetConstructorName(JSObject* object) {
if (object->IsJSFunction()) return HEAP->closure_symbol();
String* constructor_name = object->constructor_name();
if (constructor_name == HEAP->Object_symbol()) {
// Look up an immediate "constructor" property, if it is a function,
// return its name. This is for instances of binding objects, which
// have prototype constructor type "Object".
Object* constructor_prop = NULL;
LookupResult result;
object->LocalLookupRealNamedProperty(HEAP->constructor_symbol(), &result);
if (result.IsProperty()) {
constructor_prop = result.GetLazyValue();
}
if (constructor_prop->IsJSFunction()) {
Object* maybe_name = JSFunction::cast(constructor_prop)->shared()->name();
if (maybe_name->IsString()) {
String* name = String::cast(maybe_name);
if (name->length() > 0) return name;
}
}
}
return object->constructor_name();
}
HeapEntry* V8HeapExplorer::GetEntry(Object* obj) { HeapEntry* V8HeapExplorer::GetEntry(Object* obj) {
if (!obj->IsHeapObject()) return NULL; if (!obj->IsHeapObject()) return NULL;
return filler_->FindOrAddEntry(obj, this); return filler_->FindOrAddEntry(obj, this);
@ -3250,10 +3274,4 @@ void HeapSnapshotJSONSerializer::SortHashMap(
sorted_entries->Sort(SortUsingEntryValue); sorted_entries->Sort(SortUsingEntryValue);
} }
String* GetConstructorNameForHeapProfile(JSObject* object) {
if (object->IsJSFunction()) return HEAP->closure_symbol();
return object->constructor_name();
}
} } // namespace v8::internal } } // namespace v8::internal

5
deps/v8/src/profile-generator.h

@ -921,6 +921,8 @@ class V8HeapExplorer : public HeapEntriesAllocator {
bool IterateAndExtractReferences(SnapshotFillerInterface* filler); bool IterateAndExtractReferences(SnapshotFillerInterface* filler);
void TagGlobalObjects(); void TagGlobalObjects();
static String* GetConstructorName(JSObject* object);
static HeapObject* const kInternalRootObject; static HeapObject* const kInternalRootObject;
private: private:
@ -1119,9 +1121,6 @@ class HeapSnapshotJSONSerializer {
DISALLOW_COPY_AND_ASSIGN(HeapSnapshotJSONSerializer); DISALLOW_COPY_AND_ASSIGN(HeapSnapshotJSONSerializer);
}; };
String* GetConstructorNameForHeapProfile(JSObject* object);
} } // namespace v8::internal } } // namespace v8::internal
#endif // V8_PROFILE_GENERATOR_H_ #endif // V8_PROFILE_GENERATOR_H_

212
deps/v8/src/runtime.cc

@ -2663,21 +2663,22 @@ class CompiledReplacement {
void CompiledReplacement::Compile(Handle<String> replacement, void CompiledReplacement::Compile(Handle<String> replacement,
int capture_count, int capture_count,
int subject_length) { int subject_length) {
ASSERT(replacement->IsFlat()); {
if (replacement->IsAsciiRepresentation()) {
AssertNoAllocation no_alloc;
ParseReplacementPattern(&parts_,
replacement->ToAsciiVector(),
capture_count,
subject_length);
} else {
ASSERT(replacement->IsTwoByteRepresentation());
AssertNoAllocation no_alloc; AssertNoAllocation no_alloc;
String::FlatContent content = replacement->GetFlatContent();
ParseReplacementPattern(&parts_, ASSERT(content.IsFlat());
replacement->ToUC16Vector(), if (content.IsAscii()) {
capture_count, ParseReplacementPattern(&parts_,
subject_length); content.ToAsciiVector(),
capture_count,
subject_length);
} else {
ASSERT(content.IsTwoByte());
ParseReplacementPattern(&parts_,
content.ToUC16Vector(),
capture_count,
subject_length);
}
} }
Isolate* isolate = replacement->GetIsolate(); Isolate* isolate = replacement->GetIsolate();
// Find substrings of replacement string and create them as String objects. // Find substrings of replacement string and create them as String objects.
@ -3049,34 +3050,32 @@ int Runtime::StringMatch(Isolate* isolate,
AssertNoAllocation no_heap_allocation; // ensure vectors stay valid AssertNoAllocation no_heap_allocation; // ensure vectors stay valid
// Extract flattened substrings of cons strings before determining asciiness. // Extract flattened substrings of cons strings before determining asciiness.
String* seq_sub = *sub; String::FlatContent seq_sub = sub->GetFlatContent();
if (seq_sub->IsConsString()) seq_sub = ConsString::cast(seq_sub)->first(); String::FlatContent seq_pat = pat->GetFlatContent();
String* seq_pat = *pat;
if (seq_pat->IsConsString()) seq_pat = ConsString::cast(seq_pat)->first();
// dispatch on type of strings // dispatch on type of strings
if (seq_pat->IsAsciiRepresentation()) { if (seq_pat.IsAscii()) {
Vector<const char> pat_vector = seq_pat->ToAsciiVector(); Vector<const char> pat_vector = seq_pat.ToAsciiVector();
if (seq_sub->IsAsciiRepresentation()) { if (seq_sub.IsAscii()) {
return SearchString(isolate, return SearchString(isolate,
seq_sub->ToAsciiVector(), seq_sub.ToAsciiVector(),
pat_vector, pat_vector,
start_index); start_index);
} }
return SearchString(isolate, return SearchString(isolate,
seq_sub->ToUC16Vector(), seq_sub.ToUC16Vector(),
pat_vector, pat_vector,
start_index); start_index);
} }
Vector<const uc16> pat_vector = seq_pat->ToUC16Vector(); Vector<const uc16> pat_vector = seq_pat.ToUC16Vector();
if (seq_sub->IsAsciiRepresentation()) { if (seq_sub.IsAscii()) {
return SearchString(isolate, return SearchString(isolate,
seq_sub->ToAsciiVector(), seq_sub.ToAsciiVector(),
pat_vector, pat_vector,
start_index); start_index);
} }
return SearchString(isolate, return SearchString(isolate,
seq_sub->ToUC16Vector(), seq_sub.ToUC16Vector(),
pat_vector, pat_vector,
start_index); start_index);
} }
@ -3159,29 +3158,31 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringLastIndexOf) {
if (!sub->IsFlat()) FlattenString(sub); if (!sub->IsFlat()) FlattenString(sub);
if (!pat->IsFlat()) FlattenString(pat); if (!pat->IsFlat()) FlattenString(pat);
int position = -1;
AssertNoAllocation no_heap_allocation; // ensure vectors stay valid AssertNoAllocation no_heap_allocation; // ensure vectors stay valid
int position = -1; String::FlatContent sub_content = sub->GetFlatContent();
String::FlatContent pat_content = pat->GetFlatContent();
if (pat->IsAsciiRepresentation()) { if (pat_content.IsAscii()) {
Vector<const char> pat_vector = pat->ToAsciiVector(); Vector<const char> pat_vector = pat_content.ToAsciiVector();
if (sub->IsAsciiRepresentation()) { if (sub_content.IsAscii()) {
position = StringMatchBackwards(sub->ToAsciiVector(), position = StringMatchBackwards(sub_content.ToAsciiVector(),
pat_vector, pat_vector,
start_index); start_index);
} else { } else {
position = StringMatchBackwards(sub->ToUC16Vector(), position = StringMatchBackwards(sub_content.ToUC16Vector(),
pat_vector, pat_vector,
start_index); start_index);
} }
} else { } else {
Vector<const uc16> pat_vector = pat->ToUC16Vector(); Vector<const uc16> pat_vector = pat_content.ToUC16Vector();
if (sub->IsAsciiRepresentation()) { if (sub_content.IsAscii()) {
position = StringMatchBackwards(sub->ToAsciiVector(), position = StringMatchBackwards(sub_content.ToAsciiVector(),
pat_vector, pat_vector,
start_index); start_index);
} else { } else {
position = StringMatchBackwards(sub->ToUC16Vector(), position = StringMatchBackwards(sub_content.ToUC16Vector(),
pat_vector, pat_vector,
start_index); start_index);
} }
@ -3399,36 +3400,38 @@ static bool SearchStringMultiple(Isolate* isolate,
for (;;) { // Break when search complete. for (;;) { // Break when search complete.
builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch); builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch);
AssertNoAllocation no_gc; AssertNoAllocation no_gc;
if (subject->IsAsciiRepresentation()) { String::FlatContent subject_content = subject->GetFlatContent();
Vector<const char> subject_vector = subject->ToAsciiVector(); String::FlatContent pattern_content = pattern->GetFlatContent();
if (pattern->IsAsciiRepresentation()) { if (subject_content.IsAscii()) {
Vector<const char> subject_vector = subject_content.ToAsciiVector();
if (pattern_content.IsAscii()) {
if (SearchStringMultiple(isolate, if (SearchStringMultiple(isolate,
subject_vector, subject_vector,
pattern->ToAsciiVector(), pattern_content.ToAsciiVector(),
*pattern, *pattern,
builder, builder,
&match_pos)) break; &match_pos)) break;
} else { } else {
if (SearchStringMultiple(isolate, if (SearchStringMultiple(isolate,
subject_vector, subject_vector,
pattern->ToUC16Vector(), pattern_content.ToUC16Vector(),
*pattern, *pattern,
builder, builder,
&match_pos)) break; &match_pos)) break;
} }
} else { } else {
Vector<const uc16> subject_vector = subject->ToUC16Vector(); Vector<const uc16> subject_vector = subject_content.ToUC16Vector();
if (pattern->IsAsciiRepresentation()) { if (pattern_content.IsAscii()) {
if (SearchStringMultiple(isolate, if (SearchStringMultiple(isolate,
subject_vector, subject_vector,
pattern->ToAsciiVector(), pattern_content.ToAsciiVector(),
*pattern, *pattern,
builder, builder,
&match_pos)) break; &match_pos)) break;
} else { } else {
if (SearchStringMultiple(isolate, if (SearchStringMultiple(isolate,
subject_vector, subject_vector,
pattern->ToUC16Vector(), pattern_content.ToUC16Vector(),
*pattern, *pattern,
builder, builder,
&match_pos)) break; &match_pos)) break;
@ -5416,12 +5419,14 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_QuoteJSONString) {
str = String::cast(flat); str = String::cast(flat);
ASSERT(str->IsFlat()); ASSERT(str->IsFlat());
} }
if (str->IsTwoByteRepresentation()) { String::FlatContent flat = str->GetFlatContent();
ASSERT(flat.IsFlat());
if (flat.IsTwoByte()) {
return QuoteJsonString<uc16, SeqTwoByteString, false>(isolate, return QuoteJsonString<uc16, SeqTwoByteString, false>(isolate,
str->ToUC16Vector()); flat.ToUC16Vector());
} else { } else {
return QuoteJsonString<char, SeqAsciiString, false>(isolate, return QuoteJsonString<char, SeqAsciiString, false>(isolate,
str->ToAsciiVector()); flat.ToAsciiVector());
} }
} }
@ -5438,12 +5443,13 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_QuoteJSONStringComma) {
str = String::cast(flat); str = String::cast(flat);
ASSERT(str->IsFlat()); ASSERT(str->IsFlat());
} }
if (str->IsTwoByteRepresentation()) { String::FlatContent flat = str->GetFlatContent();
if (flat.IsTwoByte()) {
return QuoteJsonString<uc16, SeqTwoByteString, true>(isolate, return QuoteJsonString<uc16, SeqTwoByteString, true>(isolate,
str->ToUC16Vector()); flat.ToUC16Vector());
} else { } else {
return QuoteJsonString<char, SeqAsciiString, true>(isolate, return QuoteJsonString<char, SeqAsciiString, true>(isolate,
str->ToAsciiVector()); flat.ToAsciiVector());
} }
} }
@ -5478,14 +5484,16 @@ static MaybeObject* QuoteJsonStringArray(Isolate* isolate,
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
if (i != 0) *(write_cursor++) = ','; if (i != 0) *(write_cursor++) = ',';
String* str = String::cast(array->get(i)); String* str = String::cast(array->get(i));
if (str->IsTwoByteRepresentation()) { String::FlatContent content = str->GetFlatContent();
ASSERT(content.IsFlat());
if (content.IsTwoByte()) {
write_cursor = WriteQuoteJsonString<Char, uc16>(isolate, write_cursor = WriteQuoteJsonString<Char, uc16>(isolate,
write_cursor, write_cursor,
str->ToUC16Vector()); content.ToUC16Vector());
} else { } else {
write_cursor = WriteQuoteJsonString<Char, char>(isolate, write_cursor = WriteQuoteJsonString<Char, char>(isolate,
write_cursor, write_cursor,
str->ToAsciiVector()); content.ToAsciiVector());
} }
} }
*(write_cursor++) = ']'; *(write_cursor++) = ']';
@ -5964,11 +5972,15 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringSplit) {
// No allocation block. // No allocation block.
{ {
AssertNoAllocation nogc; AssertNoAllocation no_gc;
if (subject->IsAsciiRepresentation()) { String::FlatContent subject_content = subject->GetFlatContent();
Vector<const char> subject_vector = subject->ToAsciiVector(); String::FlatContent pattern_content = pattern->GetFlatContent();
if (pattern->IsAsciiRepresentation()) { ASSERT(subject_content.IsFlat());
Vector<const char> pattern_vector = pattern->ToAsciiVector(); ASSERT(pattern_content.IsFlat());
if (subject_content.IsAscii()) {
Vector<const char> subject_vector = subject_content.ToAsciiVector();
if (pattern_content.IsAscii()) {
Vector<const char> pattern_vector = pattern_content.ToAsciiVector();
if (pattern_vector.length() == 1) { if (pattern_vector.length() == 1) {
FindAsciiStringIndices(subject_vector, FindAsciiStringIndices(subject_vector,
pattern_vector[0], pattern_vector[0],
@ -5984,22 +5996,22 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringSplit) {
} else { } else {
FindStringIndices(isolate, FindStringIndices(isolate,
subject_vector, subject_vector,
pattern->ToUC16Vector(), pattern_content.ToUC16Vector(),
&indices, &indices,
limit); limit);
} }
} else { } else {
Vector<const uc16> subject_vector = subject->ToUC16Vector(); Vector<const uc16> subject_vector = subject_content.ToUC16Vector();
if (pattern->IsAsciiRepresentation()) { if (pattern->IsAsciiRepresentation()) {
FindStringIndices(isolate, FindStringIndices(isolate,
subject_vector, subject_vector,
pattern->ToAsciiVector(), pattern_content.ToAsciiVector(),
&indices, &indices,
limit); limit);
} else { } else {
FindStringIndices(isolate, FindStringIndices(isolate,
subject_vector, subject_vector,
pattern->ToUC16Vector(), pattern_content.ToUC16Vector(),
&indices, &indices,
limit); limit);
} }
@ -6048,7 +6060,7 @@ static int CopyCachedAsciiCharsToArray(Heap* heap,
const char* chars, const char* chars,
FixedArray* elements, FixedArray* elements,
int length) { int length) {
AssertNoAllocation nogc; AssertNoAllocation no_gc;
FixedArray* ascii_cache = heap->single_character_string_cache(); FixedArray* ascii_cache = heap->single_character_string_cache();
Object* undefined = heap->undefined_value(); Object* undefined = heap->undefined_value();
int i; int i;
@ -6081,36 +6093,39 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToArray) {
CONVERT_ARG_CHECKED(String, s, 0); CONVERT_ARG_CHECKED(String, s, 0);
CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[1]); CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[1]);
s->TryFlatten(); s = FlattenGetString(s);
const int length = static_cast<int>(Min<uint32_t>(s->length(), limit)); const int length = static_cast<int>(Min<uint32_t>(s->length(), limit));
Handle<FixedArray> elements; Handle<FixedArray> elements;
int position = 0;
if (s->IsFlat() && s->IsAsciiRepresentation()) { if (s->IsFlat() && s->IsAsciiRepresentation()) {
// Try using cached chars where possible.
Object* obj; Object* obj;
{ MaybeObject* maybe_obj = { MaybeObject* maybe_obj =
isolate->heap()->AllocateUninitializedFixedArray(length); isolate->heap()->AllocateUninitializedFixedArray(length);
if (!maybe_obj->ToObject(&obj)) return maybe_obj; if (!maybe_obj->ToObject(&obj)) return maybe_obj;
} }
elements = Handle<FixedArray>(FixedArray::cast(obj), isolate); elements = Handle<FixedArray>(FixedArray::cast(obj), isolate);
String::FlatContent content = s->GetFlatContent();
Vector<const char> chars = s->ToAsciiVector(); if (content.IsAscii()) {
// Note, this will initialize all elements (not only the prefix) Vector<const char> chars = content.ToAsciiVector();
// to prevent GC from seeing partially initialized array. // Note, this will initialize all elements (not only the prefix)
int num_copied_from_cache = CopyCachedAsciiCharsToArray(isolate->heap(), // to prevent GC from seeing partially initialized array.
chars.start(), position = CopyCachedAsciiCharsToArray(isolate->heap(),
*elements, chars.start(),
length); *elements,
length);
for (int i = num_copied_from_cache; i < length; ++i) { } else {
Handle<Object> str = LookupSingleCharacterStringFromCode(chars[i]); MemsetPointer(elements->data_start(),
elements->set(i, *str); isolate->heap()->undefined_value(),
length);
} }
} else { } else {
elements = isolate->factory()->NewFixedArray(length); elements = isolate->factory()->NewFixedArray(length);
for (int i = 0; i < length; ++i) { }
Handle<Object> str = LookupSingleCharacterStringFromCode(s->Get(i)); for (int i = position; i < length; ++i) {
elements->set(i, *str); Handle<Object> str = LookupSingleCharacterStringFromCode(s->Get(i));
} elements->set(i, *str);
} }
#ifdef DEBUG #ifdef DEBUG
@ -6921,22 +6936,24 @@ static Object* FlatStringCompare(String* x, String* y) {
equal_prefix_result = Smi::FromInt(LESS); equal_prefix_result = Smi::FromInt(LESS);
} }
int r; int r;
if (x->IsAsciiRepresentation()) { String::FlatContent x_content = x->GetFlatContent();
Vector<const char> x_chars = x->ToAsciiVector(); String::FlatContent y_content = y->GetFlatContent();
if (y->IsAsciiRepresentation()) { if (x_content.IsAscii()) {
Vector<const char> y_chars = y->ToAsciiVector(); Vector<const char> x_chars = x_content.ToAsciiVector();
if (y_content.IsAscii()) {
Vector<const char> y_chars = y_content.ToAsciiVector();
r = CompareChars(x_chars.start(), y_chars.start(), prefix_length); r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
} else { } else {
Vector<const uc16> y_chars = y->ToUC16Vector(); Vector<const uc16> y_chars = y_content.ToUC16Vector();
r = CompareChars(x_chars.start(), y_chars.start(), prefix_length); r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
} }
} else { } else {
Vector<const uc16> x_chars = x->ToUC16Vector(); Vector<const uc16> x_chars = x_content.ToUC16Vector();
if (y->IsAsciiRepresentation()) { if (y_content.IsAscii()) {
Vector<const char> y_chars = y->ToAsciiVector(); Vector<const char> y_chars = y_content.ToAsciiVector();
r = CompareChars(x_chars.start(), y_chars.start(), prefix_length); r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
} else { } else {
Vector<const uc16> y_chars = y->ToUC16Vector(); Vector<const uc16> y_chars = y_content.ToUC16Vector();
r = CompareChars(x_chars.start(), y_chars.start(), prefix_length); r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
} }
} }
@ -8817,13 +8834,14 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DateParseString) {
FixedArray* output_array = FixedArray::cast(output->elements()); FixedArray* output_array = FixedArray::cast(output->elements());
RUNTIME_ASSERT(output_array->length() >= DateParser::OUTPUT_SIZE); RUNTIME_ASSERT(output_array->length() >= DateParser::OUTPUT_SIZE);
bool result; bool result;
if (str->IsAsciiRepresentation()) { String::FlatContent str_content = str->GetFlatContent();
result = DateParser::Parse(str->ToAsciiVector(), if (str_content.IsAscii()) {
result = DateParser::Parse(str_content.ToAsciiVector(),
output_array, output_array,
isolate->unicode_cache()); isolate->unicode_cache());
} else { } else {
ASSERT(str->IsTwoByteRepresentation()); ASSERT(str_content.IsTwoByte());
result = DateParser::Parse(str->ToUC16Vector(), result = DateParser::Parse(str_content.ToUC16Vector(),
output_array, output_array,
isolate->unicode_cache()); isolate->unicode_cache());
} }
@ -12803,7 +12821,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_Log) {
ASSERT(args.length() == 2); ASSERT(args.length() == 2);
CONVERT_CHECKED(String, format, args[0]); CONVERT_CHECKED(String, format, args[0]);
CONVERT_CHECKED(JSArray, elms, args[1]); CONVERT_CHECKED(JSArray, elms, args[1]);
Vector<const char> chars = format->ToAsciiVector(); String::FlatContent format_content = format->GetFlatContent();
RUNTIME_ASSERT(format_content.IsAscii());
Vector<const char> chars = format_content.ToAsciiVector();
LOGGER->LogRuntime(chars, elms); LOGGER->LogRuntime(chars, elms);
return isolate->heap()->undefined_value(); return isolate->heap()->undefined_value();
} }

0
deps/v8/src/scanner.cc

25
deps/v8/src/small-pointer-list.h

@ -44,6 +44,31 @@ class SmallPointerList {
public: public:
SmallPointerList() : data_(kEmptyTag) {} SmallPointerList() : data_(kEmptyTag) {}
explicit SmallPointerList(int capacity) : data_(kEmptyTag) {
Reserve(capacity);
}
void Reserve(int capacity) {
if (capacity < 2) return;
if ((data_ & kTagMask) == kListTag) {
if (list()->capacity() >= capacity) return;
int old_length = list()->length();
list()->AddBlock(NULL, capacity - list()->capacity());
list()->Rewind(old_length);
return;
}
PointerList* list = new PointerList(capacity);
if ((data_ & kTagMask) == kSingletonTag) {
list->Add(single_value());
}
ASSERT(IsAligned(reinterpret_cast<intptr_t>(list), kPointerAlignment));
data_ = reinterpret_cast<intptr_t>(list) | kListTag;
}
void Clear() {
data_ = kEmptyTag;
}
bool is_empty() const { return length() == 0; } bool is_empty() const { return length() == 0; }
int length() const { int length() const {

2
deps/v8/src/string.js

@ -149,7 +149,7 @@ function StringLastIndexOf(pat /* position */) { // length == 1
position = 0; position = 0;
} }
if (position + patLength < subLength) { if (position + patLength < subLength) {
index = position index = position;
} }
} }
} }

3
deps/v8/src/stub-cache.cc

@ -29,6 +29,7 @@
#include "api.h" #include "api.h"
#include "arguments.h" #include "arguments.h"
#include "ast.h"
#include "code-stubs.h" #include "code-stubs.h"
#include "gdb-jit.h" #include "gdb-jit.h"
#include "ic-inl.h" #include "ic-inl.h"
@ -1161,7 +1162,7 @@ void StubCache::Clear() {
} }
void StubCache::CollectMatchingMaps(ZoneMapList* types, void StubCache::CollectMatchingMaps(SmallMapList* types,
String* name, String* name,
Code::Flags flags) { Code::Flags flags) {
for (int i = 0; i < kPrimaryTableSize; i++) { for (int i = 0; i < kPrimaryTableSize; i++) {

4
deps/v8/src/stub-cache.h

@ -46,8 +46,10 @@ namespace internal {
// invalidate the cache whenever a prototype map is changed. The stub // invalidate the cache whenever a prototype map is changed. The stub
// validates the map chain as in the mono-morphic case. // validates the map chain as in the mono-morphic case.
class SmallMapList;
class StubCache; class StubCache;
class SCTableReference { class SCTableReference {
public: public:
Address address() const { return address_; } Address address() const { return address_; }
@ -294,7 +296,7 @@ class StubCache {
void Clear(); void Clear();
// Collect all maps that match the name and flags. // Collect all maps that match the name and flags.
void CollectMatchingMaps(ZoneMapList* types, void CollectMatchingMaps(SmallMapList* types,
String* name, String* name,
Code::Flags flags); Code::Flags flags);

45
deps/v8/src/type-info.cc

@ -159,23 +159,26 @@ Handle<Map> TypeFeedbackOracle::StoreMonomorphicReceiverType(Expression* expr) {
} }
ZoneMapList* TypeFeedbackOracle::LoadReceiverTypes(Property* expr, void TypeFeedbackOracle::LoadReceiverTypes(Property* expr,
Handle<String> name) { Handle<String> name,
SmallMapList* types) {
Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, NORMAL); Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, NORMAL);
return CollectReceiverTypes(expr->id(), name, flags); CollectReceiverTypes(expr->id(), name, flags, types);
} }
ZoneMapList* TypeFeedbackOracle::StoreReceiverTypes(Assignment* expr, void TypeFeedbackOracle::StoreReceiverTypes(Assignment* expr,
Handle<String> name) { Handle<String> name,
SmallMapList* types) {
Code::Flags flags = Code::ComputeMonomorphicFlags(Code::STORE_IC, NORMAL); Code::Flags flags = Code::ComputeMonomorphicFlags(Code::STORE_IC, NORMAL);
return CollectReceiverTypes(expr->id(), name, flags); CollectReceiverTypes(expr->id(), name, flags, types);
} }
ZoneMapList* TypeFeedbackOracle::CallReceiverTypes(Call* expr, void TypeFeedbackOracle::CallReceiverTypes(Call* expr,
Handle<String> name, Handle<String> name,
CallKind call_kind) { CallKind call_kind,
SmallMapList* types) {
int arity = expr->arguments()->length(); int arity = expr->arguments()->length();
// Note: Currently we do not take string extra ic data into account // Note: Currently we do not take string extra ic data into account
@ -189,7 +192,7 @@ ZoneMapList* TypeFeedbackOracle::CallReceiverTypes(Call* expr,
OWN_MAP, OWN_MAP,
NOT_IN_LOOP, NOT_IN_LOOP,
arity); arity);
return CollectReceiverTypes(expr->id(), name, flags); CollectReceiverTypes(expr->id(), name, flags, types);
} }
@ -391,36 +394,30 @@ TypeInfo TypeFeedbackOracle::IncrementType(CountOperation* expr) {
} }
ZoneMapList* TypeFeedbackOracle::CollectReceiverTypes(unsigned ast_id, void TypeFeedbackOracle::CollectReceiverTypes(unsigned ast_id,
Handle<String> name, Handle<String> name,
Code::Flags flags) { Code::Flags flags,
SmallMapList* types) {
Isolate* isolate = Isolate::Current(); Isolate* isolate = Isolate::Current();
Handle<Object> object = GetInfo(ast_id); Handle<Object> object = GetInfo(ast_id);
if (object->IsUndefined() || object->IsSmi()) return NULL; if (object->IsUndefined() || object->IsSmi()) return;
if (*object == isolate->builtins()->builtin(Builtins::kStoreIC_GlobalProxy)) { if (*object == isolate->builtins()->builtin(Builtins::kStoreIC_GlobalProxy)) {
// TODO(fschneider): We could collect the maps and signal that // TODO(fschneider): We could collect the maps and signal that
// we need a generic store (or load) here. // we need a generic store (or load) here.
ASSERT(Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC); ASSERT(Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC);
return NULL;
} else if (object->IsMap()) { } else if (object->IsMap()) {
ZoneMapList* types = new ZoneMapList(1);
types->Add(Handle<Map>::cast(object)); types->Add(Handle<Map>::cast(object));
return types;
} else if (Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC) { } else if (Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC) {
ZoneMapList* types = new ZoneMapList(4); types->Reserve(4);
ASSERT(object->IsCode()); ASSERT(object->IsCode());
isolate->stub_cache()->CollectMatchingMaps(types, *name, flags); isolate->stub_cache()->CollectMatchingMaps(types, *name, flags);
return types->length() > 0 ? types : NULL;
} else {
return NULL;
} }
} }
void TypeFeedbackOracle::CollectKeyedReceiverTypes( void TypeFeedbackOracle::CollectKeyedReceiverTypes(unsigned ast_id,
unsigned ast_id, SmallMapList* types) {
ZoneMapList* types) {
Handle<Object> object = GetInfo(ast_id); Handle<Object> object = GetInfo(ast_id);
if (!object->IsCode()) return; if (!object->IsCode()) return;
Handle<Code> code = Handle<Code>::cast(object); Handle<Code> code = Handle<Code>::cast(object);

32
deps/v8/src/type-info.h

@ -203,14 +203,16 @@ enum StringStubFeedback {
// Forward declarations. // Forward declarations.
class Assignment; class Assignment;
class UnaryOperation;
class BinaryOperation; class BinaryOperation;
class Call; class Call;
class CaseClause;
class CompareOperation; class CompareOperation;
class CountOperation;
class CompilationInfo; class CompilationInfo;
class CountOperation;
class Property; class Property;
class CaseClause; class SmallMapList;
class UnaryOperation;
class TypeFeedbackOracle BASE_EMBEDDED { class TypeFeedbackOracle BASE_EMBEDDED {
public: public:
@ -225,13 +227,18 @@ class TypeFeedbackOracle BASE_EMBEDDED {
Handle<Map> LoadMonomorphicReceiverType(Property* expr); Handle<Map> LoadMonomorphicReceiverType(Property* expr);
Handle<Map> StoreMonomorphicReceiverType(Expression* expr); Handle<Map> StoreMonomorphicReceiverType(Expression* expr);
ZoneMapList* LoadReceiverTypes(Property* expr, Handle<String> name); void LoadReceiverTypes(Property* expr,
ZoneMapList* StoreReceiverTypes(Assignment* expr, Handle<String> name); Handle<String> name,
ZoneMapList* CallReceiverTypes(Call* expr, SmallMapList* types);
Handle<String> name, void StoreReceiverTypes(Assignment* expr,
CallKind call_kind); Handle<String> name,
SmallMapList* types);
void CallReceiverTypes(Call* expr,
Handle<String> name,
CallKind call_kind,
SmallMapList* types);
void CollectKeyedReceiverTypes(unsigned ast_id, void CollectKeyedReceiverTypes(unsigned ast_id,
ZoneMapList* types); SmallMapList* types);
CheckType GetCallCheckType(Call* expr); CheckType GetCallCheckType(Call* expr);
Handle<JSObject> GetPrototypeForPrimitiveCheck(CheckType check); Handle<JSObject> GetPrototypeForPrimitiveCheck(CheckType check);
@ -252,9 +259,10 @@ class TypeFeedbackOracle BASE_EMBEDDED {
TypeInfo IncrementType(CountOperation* expr); TypeInfo IncrementType(CountOperation* expr);
private: private:
ZoneMapList* CollectReceiverTypes(unsigned ast_id, void CollectReceiverTypes(unsigned ast_id,
Handle<String> name, Handle<String> name,
Code::Flags flags); Code::Flags flags,
SmallMapList* types);
void SetInfo(unsigned ast_id, Object* target); void SetInfo(unsigned ast_id, Object* target);

2
deps/v8/src/version.cc

@ -34,7 +34,7 @@
// cannot be changed without changing the SCons build script. // cannot be changed without changing the SCons build script.
#define MAJOR_VERSION 3 #define MAJOR_VERSION 3
#define MINOR_VERSION 5 #define MINOR_VERSION 5
#define BUILD_NUMBER 7 #define BUILD_NUMBER 8
#define PATCH_LEVEL 0 #define PATCH_LEVEL 0
// Use 1 for candidates and 0 otherwise. // Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.) // (Boolean macro values are not supported by all preprocessors.)

4
deps/v8/src/zone.h

@ -200,10 +200,6 @@ class ZoneList: public List<T, ZoneListAllocationPolicy> {
}; };
// Introduce a convenience type for zone lists of map handles.
typedef ZoneList<Handle<Map> > ZoneMapList;
// ZoneScopes keep track of the current parsing and compilation // ZoneScopes keep track of the current parsing and compilation
// nesting and cleans up generated ASTs in the Zone when exiting the // nesting and cleans up generated ASTs in the Zone when exiting the
// outer-most scope. // outer-most scope.

41
deps/v8/test/cctest/test-api.cc

@ -5296,6 +5296,40 @@ THREADED_TEST(StringWrite) {
CHECK_EQ(0, strncmp("d\1", buf, 2)); CHECK_EQ(0, strncmp("d\1", buf, 2));
uint16_t answer7[] = {'d', 0x101}; uint16_t answer7[] = {'d', 0x101};
CHECK_EQ(0, StrNCmp16(answer7, wbuf, 2)); CHECK_EQ(0, StrNCmp16(answer7, wbuf, 2));
memset(wbuf, 0x1, sizeof(wbuf));
wbuf[5] = 'X';
len = str->Write(wbuf, 0, 6, String::NO_NULL_TERMINATION);
CHECK_EQ(5, len);
CHECK_EQ('X', wbuf[5]);
uint16_t answer8a[] = {'a', 'b', 'c', 'd', 'e'};
uint16_t answer8b[] = {'a', 'b', 'c', 'd', 'e', '\0'};
CHECK_EQ(0, StrNCmp16(answer8a, wbuf, 5));
CHECK_NE(0, StrCmp16(answer8b, wbuf));
wbuf[5] = '\0';
CHECK_EQ(0, StrCmp16(answer8b, wbuf));
memset(buf, 0x1, sizeof(buf));
buf[5] = 'X';
len = str->WriteAscii(buf, 0, 6, String::NO_NULL_TERMINATION);
CHECK_EQ(5, len);
CHECK_EQ('X', buf[5]);
CHECK_EQ(0, strncmp("abcde", buf, 5));
CHECK_NE(0, strcmp("abcde", buf));
buf[5] = '\0';
CHECK_EQ(0, strcmp("abcde", buf));
memset(utf8buf, 0x1, sizeof(utf8buf));
utf8buf[8] = 'X';
len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
String::NO_NULL_TERMINATION);
CHECK_EQ(8, len);
CHECK_EQ('X', utf8buf[8]);
CHECK_EQ(5, charlen);
CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203", 8));
CHECK_NE(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
utf8buf[8] = '\0';
CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
} }
@ -13693,6 +13727,9 @@ THREADED_TEST(TwoByteStringInAsciiCons) {
"str2;"; "str2;";
Local<Value> result = CompileRun(init_code); Local<Value> result = CompileRun(init_code);
Local<Value> indexof = CompileRun("str2.indexOf('els')");
Local<Value> lastindexof = CompileRun("str2.lastIndexOf('dab')");
CHECK(result->IsString()); CHECK(result->IsString());
i::Handle<i::String> string = v8::Utils::OpenHandle(String::Cast(*result)); i::Handle<i::String> string = v8::Utils::OpenHandle(String::Cast(*result));
int length = string->length(); int length = string->length();
@ -13758,6 +13795,10 @@ THREADED_TEST(TwoByteStringInAsciiCons) {
ExpectString("str2.charAt(2);", "e"); ExpectString("str2.charAt(2);", "e");
ExpectObject("str2.indexOf('els');", indexof);
ExpectObject("str2.lastIndexOf('dab');", lastindexof);
reresult = CompileRun("str2.charCodeAt(2);"); reresult = CompileRun("str2.charCodeAt(2);");
CHECK_EQ(static_cast<int32_t>('e'), reresult->Int32Value()); CHECK_EQ(static_cast<int32_t>('e'), reresult->Int32Value());
} }

56
deps/v8/test/cctest/test-heap-profiler.cc

@ -889,3 +889,59 @@ TEST(NodesIteration) {
} }
CHECK_EQ(1, count); CHECK_EQ(1, count);
} }
static int StringCmp(const char* ref, i::String* act) {
i::SmartPointer<char> s_act = act->ToCString();
int result = strcmp(ref, *s_act);
if (result != 0)
fprintf(stderr, "Expected: \"%s\", Actual: \"%s\"\n", ref, *s_act);
return result;
}
TEST(GetConstructorName) {
v8::HandleScope scope;
LocalContext env;
CompileRun(
"function Constructor1() {};\n"
"var obj1 = new Constructor1();\n"
"var Constructor2 = function() {};\n"
"var obj2 = new Constructor2();\n"
"var obj3 = {};\n"
"obj3.constructor = function Constructor3() {};\n"
"var obj4 = {};\n"
"// Slow properties\n"
"for (var i=0; i<2000; ++i) obj4[\"p\" + i] = i;\n"
"obj4.constructor = function Constructor4() {};\n"
"var obj5 = {};\n"
"var obj6 = {};\n"
"obj6.constructor = 6;");
v8::Local<v8::Object> js_global =
env->Global()->GetPrototype().As<v8::Object>();
v8::Local<v8::Object> obj1 = js_global->Get(v8_str("obj1")).As<v8::Object>();
i::Handle<i::JSObject> js_obj1 = v8::Utils::OpenHandle(*obj1);
CHECK_EQ(0, StringCmp(
"Constructor1", i::V8HeapExplorer::GetConstructorName(*js_obj1)));
v8::Local<v8::Object> obj2 = js_global->Get(v8_str("obj2")).As<v8::Object>();
i::Handle<i::JSObject> js_obj2 = v8::Utils::OpenHandle(*obj2);
CHECK_EQ(0, StringCmp(
"Constructor2", i::V8HeapExplorer::GetConstructorName(*js_obj2)));
v8::Local<v8::Object> obj3 = js_global->Get(v8_str("obj3")).As<v8::Object>();
i::Handle<i::JSObject> js_obj3 = v8::Utils::OpenHandle(*obj3);
CHECK_EQ(0, StringCmp(
"Constructor3", i::V8HeapExplorer::GetConstructorName(*js_obj3)));
v8::Local<v8::Object> obj4 = js_global->Get(v8_str("obj4")).As<v8::Object>();
i::Handle<i::JSObject> js_obj4 = v8::Utils::OpenHandle(*obj4);
CHECK_EQ(0, StringCmp(
"Constructor4", i::V8HeapExplorer::GetConstructorName(*js_obj4)));
v8::Local<v8::Object> obj5 = js_global->Get(v8_str("obj5")).As<v8::Object>();
i::Handle<i::JSObject> js_obj5 = v8::Utils::OpenHandle(*obj5);
CHECK_EQ(0, StringCmp(
"Object", i::V8HeapExplorer::GetConstructorName(*js_obj5)));
v8::Local<v8::Object> obj6 = js_global->Get(v8_str("obj6")).As<v8::Object>();
i::Handle<i::JSObject> js_obj6 = v8::Utils::OpenHandle(*obj6);
CHECK_EQ(0, StringCmp(
"Object", i::V8HeapExplorer::GetConstructorName(*js_obj6)));
}

31
deps/v8/test/message/replacement-marker-as-argument.js

@ -0,0 +1,31 @@
// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"use strict";
var o = { get "%3" (){} };
o["%3"] = 10;

32
deps/v8/test/message/replacement-marker-as-argument.out

@ -0,0 +1,32 @@
# Copyright 2011 the V8 project authors. All rights reserved.
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*%(basename)s:31: TypeError: Cannot set property %%3 of #<Object> which has only a getter
o["%%3"] = 10;
^
TypeError: Cannot set property %%3 of #<Object> which has only a getter
at *%(basename)s:31:9

12
deps/v8/test/mjsunit/string-split.js

@ -116,3 +116,15 @@ assertEquals(["a", "b", "c"], "abc".split("", 3));
assertEquals(["a", "b", "c"], "abc".split("", numberObj(3))); assertEquals(["a", "b", "c"], "abc".split("", numberObj(3)));
assertEquals(["a", "b", "c"], "abc".split("", 4)); assertEquals(["a", "b", "c"], "abc".split("", 4));
assertEquals(["a", "b", "c"], "abc".split("", numberObj(4))); assertEquals(["a", "b", "c"], "abc".split("", numberObj(4)));
var all_ascii_codes = [];
for (var i = 0; i < 128; i++) all_ascii_codes[i] = i;
var all_ascii_string = String.fromCharCode.apply(String, all_ascii_codes);
var split_chars = all_ascii_string.split("");
assertEquals(128, split_chars.length);
for (var i = 0; i < 128; i++) {
assertEquals(1, split_chars[i].length);
assertEquals(i, split_chars[i].charCodeAt(0));
}

Loading…
Cancel
Save