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. 43
      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. 44
      deps/v8/src/jsregexp.cc
  24. 4
      deps/v8/src/messages.js
  25. 5
      deps/v8/src/objects-inl.h
  26. 117
      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. 184
      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. 41
      deps/v8/src/type-info.cc
  37. 28
      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
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
* WriteUtf8 the number of bytes in the buffer.
* \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.
* \return The number of characters copied to the buffer excluding the null
* terminator. For WriteUtf8: The number of bytes copied to the buffer
* including the null terminator.
* including the null terminator (if written).
*/
enum WriteHints {
NO_HINTS = 0,
HINT_MANY_WRITES_EXPECTED = 1
enum WriteOptions {
NO_OPTIONS = 0,
HINT_MANY_WRITES_EXPECTED = 1,
NO_NULL_TERMINATION = 2
};
V8EXPORT int Write(uint16_t* buffer,
int start = 0,
int length = -1,
WriteHints hints = NO_HINTS) const; // UTF-16
int options = NO_OPTIONS) const; // UTF-16
V8EXPORT int WriteAscii(char* buffer,
int start = 0,
int length = -1,
WriteHints hints = NO_HINTS) const; // ASCII
int options = NO_OPTIONS) const; // ASCII
V8EXPORT int WriteUtf8(char* buffer,
int length = -1,
int* nchars_ref = NULL,
WriteHints hints = NO_HINTS) const; // UTF-8
int options = NO_OPTIONS) const; // UTF-8
/**
* A zero length string.
@ -1335,7 +1336,7 @@ class Number : public Primitive {
static inline Number* Cast(v8::Value* obj);
private:
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);
private:
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 capacity,
int* nchars_ref,
WriteHints hints) const {
int options) const {
i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
if (IsDeadCheck(isolate, "v8::String::WriteUtf8()")) return 0;
LOG_API(isolate, "String::WriteUtf8");
@ -3629,7 +3629,7 @@ int String::WriteUtf8(char* buffer,
i::StringInputBuffer& write_input_buffer = *isolate->write_input_buffer();
i::Handle<i::String> str = Utils::OpenHandle(this);
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
// using StringInputBuffer or Get(i) to access the characters.
str->TryFlatten();
@ -3669,7 +3669,8 @@ int String::WriteUtf8(char* buffer,
}
}
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';
return pos;
}
@ -3678,7 +3679,7 @@ int String::WriteUtf8(char* buffer,
int String::WriteAscii(char* buffer,
int start,
int length,
WriteHints hints) const {
int options) const {
i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
if (IsDeadCheck(isolate, "v8::String::WriteAscii()")) return 0;
LOG_API(isolate, "String::WriteAscii");
@ -3687,7 +3688,7 @@ int String::WriteAscii(char* buffer,
ASSERT(start >= 0 && length >= -1);
i::Handle<i::String> str = Utils::OpenHandle(this);
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
// using StringInputBuffer or Get(i) to access the characters.
str->TryFlatten();
@ -3703,7 +3704,7 @@ int String::WriteAscii(char* buffer,
if (c == '\0') c = ' ';
buffer[i] = c;
}
if (length == -1 || i < length)
if (!(options & NO_NULL_TERMINATION) && (length == -1 || i < length))
buffer[i] = '\0';
return i;
}
@ -3712,7 +3713,7 @@ int String::WriteAscii(char* buffer,
int String::Write(uint16_t* buffer,
int start,
int length,
WriteHints hints) const {
int options) const {
i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
if (IsDeadCheck(isolate, "v8::String::Write()")) return 0;
LOG_API(isolate, "String::Write");
@ -3720,7 +3721,7 @@ int String::Write(uint16_t* buffer,
ASSERT(start >= 0 && length >= -1);
i::Handle<i::String> str = Utils::OpenHandle(this);
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
// using StringInputBuffer or Get(i) to access the characters.
str->TryFlatten();
@ -3730,7 +3731,8 @@ int String::Write(uint16_t* buffer,
end = str->length();
if (end < 0) return 0;
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';
}
return end - start;
@ -4118,7 +4120,7 @@ bool Context::InContext() {
v8::Local<v8::Context> Context::GetEntered() {
i::Isolate* isolate = i::Isolate::Current();
if (IsDeadCheck(isolate, "v8::Context::GetEntered()")) {
if (!EnsureInitializedForIsolate(isolate, "v8::Context::GetEntered()")) {
return Local<Context>();
}
i::Handle<i::Object> last =

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

@ -377,6 +377,9 @@ class Operand BASE_EMBEDDED {
// immediate
INLINE(explicit Operand(int32_t immediate,
RelocInfo::Mode rmode = RelocInfo::NONE));
INLINE(static Operand Zero()) {
return Operand(static_cast<int32_t>(0));
}
INLINE(explicit Operand(const ExternalReference& f));
explicit Operand(Handle<Object> handle);
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 |
// Check for zero.
__ cmp(int_scratch, Operand(0));
__ cmp(int_scratch, Operand::Zero());
__ mov(dst2, int_scratch);
__ mov(dst1, int_scratch);
__ b(eq, &done);
@ -557,7 +557,7 @@ void FloatingPointHelper::ConvertIntToDouble(MacroAssembler* masm,
// Preload the sign of the value.
__ and_(dst2, int_scratch, Operand(HeapNumber::kSignMask), SetCC);
// 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].
@ -589,7 +589,7 @@ void FloatingPointHelper::ConvertIntToDouble(MacroAssembler* masm,
__ mov(scratch2, Operand(int_scratch, LSL, scratch2));
__ orr(dst2, dst2, scratch2);
// Set dst1 to 0.
__ mov(dst1, Operand(0));
__ mov(dst1, Operand::Zero());
}
__ bind(&done);
}
@ -657,7 +657,7 @@ void FloatingPointHelper::LoadNumberAsInt32Double(MacroAssembler* masm,
// Check for 0 and -0.
__ bic(scratch1, dst1, Operand(HeapNumber::kSignMask));
__ orr(scratch1, scratch1, Operand(dst2));
__ cmp(scratch1, Operand(0));
__ cmp(scratch1, Operand::Zero());
__ b(eq, &done);
// 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.
__ bic(dst, scratch1, Operand(HeapNumber::kSignMask));
__ orr(dst, scratch2, Operand(dst));
__ cmp(dst, Operand(0));
__ cmp(dst, Operand::Zero());
__ b(eq, &done);
DoubleIs32BitInteger(masm, scratch1, scratch2, dst, scratch3, not_int32);
@ -747,7 +747,7 @@ void FloatingPointHelper::LoadNumberAsInt32(MacroAssembler* masm,
// Set the sign.
__ ldr(scratch1, FieldMemOperand(object, HeapNumber::kExponentOffset));
__ tst(scratch1, Operand(HeapNumber::kSignMask));
__ rsb(dst, dst, Operand(0), LeaveCC, mi);
__ rsb(dst, dst, Operand::Zero(), LeaveCC, mi);
}
__ bind(&done);
@ -2424,7 +2424,6 @@ void BinaryOpStub::GenerateSmiCode(
Register left = r1;
Register right = r0;
Register scratch1 = r7;
Register scratch2 = r9;
// Perform combined smi check on both operands.
__ orr(scratch1, left, Operand(right));
@ -2618,7 +2617,7 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
__ b(mi, &return_heap_number);
// Check for minus zero. Return heap number for minus zero.
Label not_zero;
__ cmp(scratch1, Operand(0));
__ cmp(scratch1, Operand::Zero());
__ b(ne, &not_zero);
__ vmov(scratch2, d5.high());
__ tst(scratch2, Operand(HeapNumber::kSignMask));
@ -3110,7 +3109,6 @@ void TranscendentalCacheStub::Generate(MacroAssembler* masm) {
Label no_update;
Label skip_cache;
const Register heap_number_map = r5;
// Call C function to calculate the result and update the cache.
// 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);
__ mov(r5, Operand(ExternalReference(js_entry_sp)));
__ ldr(r6, MemOperand(r5));
__ cmp(r6, Operand(0));
__ cmp(r6, Operand::Zero());
__ b(ne, &non_outermost_js);
__ str(fp, MemOperand(r5));
__ mov(ip, Operand(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME)));
@ -3656,7 +3654,7 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
__ pop(r5);
__ cmp(r5, Operand(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME)));
__ b(ne, &non_outermost_js_2);
__ mov(r6, Operand(0));
__ mov(r6, Operand::Zero());
__ mov(r5, Operand(ExternalReference(js_entry_sp)));
__ str(r6, MemOperand(r5));
__ bind(&non_outermost_js_2);
@ -3857,7 +3855,7 @@ void InstanceofStub::Generate(MacroAssembler* masm) {
__ Push(r0, r1);
__ InvokeBuiltin(Builtins::INSTANCE_OF, CALL_FUNCTION);
__ LeaveInternalFrame();
__ cmp(r0, Operand(0));
__ cmp(r0, Operand::Zero());
__ LoadRoot(r0, Heap::kTrueValueRootIndex, eq);
__ LoadRoot(r0, Heap::kFalseValueRootIndex, ne);
__ Ret(HasArgsInRegisters() ? 0 : 2);
@ -3991,7 +3989,7 @@ void ArgumentsAccessStub::GenerateNewNonStrictFast(MacroAssembler* masm) {
FixedArray::kHeaderSize + 2 * kPointerSize;
// If there are no mapped parameters, we do not need the parameter_map.
__ 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);
__ 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, FieldMemOperand(r4, GlobalObject::kGlobalContextOffset));
__ cmp(r1, Operand(0));
__ cmp(r1, Operand::Zero());
__ ldr(r4, MemOperand(r4, kNormalOffset), eq);
__ ldr(r4, MemOperand(r4, kAliasedOffset), ne);
@ -5697,7 +5695,7 @@ void StringCompareStub::GenerateAsciiCharsCompareLoop(
Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
__ add(left, left, Operand(scratch1));
__ add(right, right, Operand(scratch1));
__ rsb(length, length, Operand(0));
__ rsb(length, length, Operand::Zero());
Register index = length; // index = -length;
// Compare loop.
@ -6555,7 +6553,7 @@ void StringDictionaryLookupStub::Generate(MacroAssembler* masm) {
// treated as a lookup success. For positive lookup probing failure
// should be treated as lookup failure.
if (mode_ == POSITIVE_LOOKUP) {
__ mov(result, Operand(0));
__ mov(result, Operand::Zero());
__ Ret();
}
@ -6564,7 +6562,7 @@ void StringDictionaryLookupStub::Generate(MacroAssembler* masm) {
__ Ret();
__ bind(&not_in_dictionary);
__ mov(result, Operand(0));
__ mov(result, Operand::Zero());
__ Ret();
}

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

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

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

@ -1399,7 +1399,6 @@ LInstruction* LChunkBuilder::DoPower(HPower* instr) {
LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) {
Token::Value op = instr->token();
Representation r = instr->GetInputRepresentation();
ASSERT(instr->left()->representation().IsTagged());
ASSERT(instr->right()->representation().IsTagged());
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) {
Register reg = ToRegister(instr->InputAt(0));
Register temp1 = ToRegister(instr->TempAt(0));
Register temp2 = scratch0();
int true_block = chunk_->LookupDestination(instr->true_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) {
Register context = ToRegister(instr->context());
Register result = ToRegister(instr->result());
__ ldr(result, ContextOperand(cp, Context::GLOBAL_INDEX));
}
@ -3965,7 +3963,6 @@ void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
Register scratch1 = scratch0();
Register scratch2 = ToRegister(instr->TempAt(0));
DwVfpRegister double_input = ToDoubleRegister(instr->InputAt(0));
DwVfpRegister double_scratch = double_scratch0();
SwVfpRegister single_scratch = double_scratch0().low();
Label done;

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

@ -254,7 +254,6 @@ void LGapResolver::EmitMove(int index) {
} else {
ASSERT(destination->IsStackSlot());
ASSERT(!in_cycle_); // Constant moves happen after all cycles are gone.
MemOperand destination_operand = cgen_->ToMemOperand(destination);
__ mov(kSavedValueRegister, source_operand);
__ str(kSavedValueRegister, cgen_->ToMemOperand(destination));
}
@ -265,8 +264,7 @@ void LGapResolver::EmitMove(int index) {
__ vmov(cgen_->ToDoubleRegister(destination), source_register);
} else {
ASSERT(destination->IsDoubleStackSlot());
MemOperand destination_operand = cgen_->ToMemOperand(destination);
__ vstr(source_register, destination_operand);
__ vstr(source_register, cgen_->ToMemOperand(destination));
}
} 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);
// Check that the maps haven't changed.
Register reg =
CheckPrototypes(object, receiver, holder,
scratch1, scratch2, scratch3, name, miss);
CheckPrototypes(object, receiver, holder, scratch1, scratch2, scratch3, name,
miss);
// Return the constant value.
__ mov(r0, Operand(Handle<Object>(value)));

43
deps/v8/src/ast.cc

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

74
deps/v8/src/ast.h

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

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();
delete thread;
}
OnExit();
#endif // V8_SHARED
return 0;
}
@ -1290,6 +1288,10 @@ int Shell::Main(int argc, char* argv[]) {
V8::Dispose();
#ifndef V8_SHARED
OnExit();
#endif // V8_SHARED
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.
// Dispatch on type of strings.
if (src->IsAsciiRepresentation()) {
String::FlatContent content = src->GetFlatContent();
ASSERT(content.IsFlat());
if (content.IsAscii()) {
CalculateLineEnds(isolate,
&line_ends,
src->ToAsciiVector(),
content.ToAsciiVector(),
with_last_line);
} else {
CalculateLineEnds(isolate,
&line_ends,
src->ToUC16Vector(),
content.ToUC16Vector(),
with_last_line);
}
}

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

@ -641,6 +641,7 @@ void HBoundsCheck::PrintDataTo(StringStream* stream) {
length()->PrintNameTo(stream);
}
void HCallConstantFunction::PrintDataTo(StringStream* stream) {
if (IsApplyFunction()) {
stream->Add("optimized apply ");
@ -777,7 +778,7 @@ void HHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) {
void HTypeofIsAndBranch::PrintDataTo(StringStream* stream) {
value()->PrintNameTo(stream);
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() {
if (has_int32_value_) {
Range* result = new Range(int32_value_, int32_value_);
@ -1220,6 +1236,7 @@ Range* HSar::InferRange() {
? left()->range()->Copy()
: new Range();
result->Sar(c->Integer32Value());
result->set_can_be_minus_zero(false);
return result;
}
}
@ -1243,6 +1260,7 @@ Range* HShr::InferRange() {
? left()->range()->Copy()
: new Range();
result->Sar(c->Integer32Value());
result->set_can_be_minus_zero(false);
return result;
}
}
@ -1259,6 +1277,7 @@ Range* HShl::InferRange() {
? left()->range()->Copy()
: new Range();
result->Shl(c->Integer32Value());
result->set_can_be_minus_zero(false);
return result;
}
}
@ -1306,7 +1325,7 @@ void HLoadNamedField::PrintDataTo(StringStream* stream) {
HLoadNamedFieldPolymorphic::HLoadNamedFieldPolymorphic(HValue* context,
HValue* object,
ZoneMapList* types,
SmallMapList* types,
Handle<String> name)
: types_(Min(types->length(), kMaxLoadPolymorphism)),
name_(name),

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

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

42
deps/v8/src/hydrogen.cc

@ -2325,20 +2325,11 @@ HGraph* HGraphBuilder::CreateGraph() {
HInferRepresentation rep(graph());
rep.Analyze();
if (FLAG_use_range) {
HRangeAnalysis rangeAnalysis(graph());
rangeAnalysis.Analyze();
}
graph()->InitializeInferredTypes();
graph()->Canonicalize();
graph()->MarkDeoptimizeOnUndefined();
graph()->InsertRepresentationChanges();
graph()->ComputeMinusZeroChecks();
// Eliminate redundant stack checks on backwards branches.
HStackCheckEliminator sce(graph());
sce.Process();
graph()->InitializeInferredTypes();
graph()->Canonicalize();
// Perform common subexpression elimination and loop-invariant code motion.
if (FLAG_use_gvn) {
@ -2347,6 +2338,16 @@ HGraph* HGraphBuilder::CreateGraph() {
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
// 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
@ -3395,7 +3396,7 @@ HInstruction* HGraphBuilder::BuildStoreNamed(HValue* object,
ASSERT(!name.is_null());
LookupResult lookup;
ZoneMapList* types = expr->GetReceiverTypes();
SmallMapList* types = expr->GetReceiverTypes();
bool is_monomorphic = expr->IsMonomorphic() &&
ComputeStoredField(types->first(), name, &lookup);
@ -3409,7 +3410,7 @@ HInstruction* HGraphBuilder::BuildStoreNamed(HValue* object,
void HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr,
HValue* object,
HValue* value,
ZoneMapList* types,
SmallMapList* types,
Handle<String> name) {
// TODO(ager): We should recognize when the prototype chains for different
// 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());
ASSERT(!name.is_null());
ZoneMapList* types = expr->GetReceiverTypes();
SmallMapList* types = expr->GetReceiverTypes();
LookupResult lookup;
if (expr->IsMonomorphic()) {
@ -3986,7 +3987,7 @@ HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object,
*has_side_effects = false;
AddInstruction(new(zone()) HCheckNonSmi(object));
AddInstruction(HCheckInstanceType::NewIsSpecObject(object));
ZoneMapList* maps = prop->GetReceiverTypes();
SmallMapList* maps = prop->GetReceiverTypes();
bool todo_external_array = false;
static const int kNumElementTypes = JSObject::kElementsKindCount;
@ -4260,7 +4261,7 @@ void HGraphBuilder::VisitProperty(Property* expr) {
} else if (expr->key()->IsPropertyName()) {
Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
ZoneMapList* types = expr->GetReceiverTypes();
SmallMapList* types = expr->GetReceiverTypes();
HValue* obj = Pop();
if (expr->IsMonomorphic()) {
@ -4321,7 +4322,7 @@ void HGraphBuilder::AddCheckConstantFunction(Call* expr,
void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr,
HValue* receiver,
ZoneMapList* types,
SmallMapList* types,
Handle<String> name) {
// TODO(ager): We should recognize when the prototype chains for different
// 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();
ZoneMapList* types = expr->GetReceiverTypes();
SmallMapList* types = expr->GetReceiverTypes();
HValue* receiver =
environment()->ExpressionStackAt(expr->arguments()->length());
if (expr->IsMonomorphic()) {
Handle<Map> receiver_map =
(types == NULL) ? Handle<Map>::null() : types->first();
Handle<Map> receiver_map = (types == NULL || types->is_empty())
? Handle<Map>::null()
: types->first();
if (TryInlineBuiltinFunction(expr,
receiver,
receiver_map,

4
deps/v8/src/hydrogen.h

@ -901,11 +901,11 @@ class HGraphBuilder: public AstVisitor {
void HandlePolymorphicStoreNamedField(Assignment* expr,
HValue* object,
HValue* value,
ZoneMapList* types,
SmallMapList* types,
Handle<String> name);
void HandlePolymorphicCallNamed(Call* expr,
HValue* receiver,
ZoneMapList* types,
SmallMapList* types,
Handle<String> name);
void HandleLiteralCompareTypeof(CompareOperation* compare_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
// modification, are permitted provided that the following conditions are
// met:
@ -635,8 +635,9 @@ bool IrregexpInterpreter::Match(Isolate* isolate,
AssertNoAllocation a;
const byte* code_base = code_array->GetDataStartAddress();
uc16 previous_char = '\n';
if (subject->IsAsciiRepresentation()) {
Vector<const char> subject_vector = subject->ToAsciiVector();
String::FlatContent subject_content = subject->GetFlatContent();
if (subject_content.IsAscii()) {
Vector<const char> subject_vector = subject_content.ToAsciiVector();
if (start_position != 0) previous_char = subject_vector[start_position - 1];
return RawMatch(isolate,
code_base,
@ -645,7 +646,8 @@ bool IrregexpInterpreter::Match(Isolate* isolate,
start_position,
previous_char);
} 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];
return RawMatch(isolate,
code_base,

44
deps/v8/src/jsregexp.cc

@ -212,19 +212,7 @@ static void SetAtomLastCapture(FixedArray* array,
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<String> subject,
int index,
@ -237,35 +225,39 @@ Handle<Object> RegExpImpl::AtomExec(Handle<JSRegExp> re,
if (!subject->IsFlat()) FlattenString(subject);
AssertNoAllocation no_heap_allocation; // ensure vectors stay valid
// 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));
int needle_len = needle->length();
ASSERT(needle->IsFlat());
if (needle_len != 0) {
if (index + needle_len > subject->length())
if (index + needle_len > subject->length()) {
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
index = (needle->IsAsciiRepresentation()
? (seq_sub->IsAsciiRepresentation()
index = (needle_content.IsAscii()
? (subject_content.IsAscii()
? SearchString(isolate,
seq_sub->ToAsciiVector(),
needle->ToAsciiVector(),
subject_content.ToAsciiVector(),
needle_content.ToAsciiVector(),
index)
: SearchString(isolate,
seq_sub->ToUC16Vector(),
needle->ToAsciiVector(),
subject_content.ToUC16Vector(),
needle_content.ToAsciiVector(),
index))
: (seq_sub->IsAsciiRepresentation()
: (subject_content.IsAscii()
? SearchString(isolate,
seq_sub->ToAsciiVector(),
needle->ToUC16Vector(),
subject_content.ToAsciiVector(),
needle_content.ToUC16Vector(),
index)
: SearchString(isolate,
seq_sub->ToUC16Vector(),
needle->ToUC16Vector(),
subject_content.ToUC16Vector(),
needle_content.ToUC16Vector(),
index)));
if (index == -1) return isolate->factory()->null_value();
}

4
deps/v8/src/messages.js

@ -57,12 +57,14 @@ function FormatString(format, message) {
for (var i = 0; i < format.length; i++) {
var str = format[i];
for (arg_num = 0; arg_num < kReplacementMarkers.length; arg_num++) {
if (str !== kReplacementMarkers[arg_num]) continue;
if (str == kReplacementMarkers[arg_num]) {
try {
str = ToDetailString(args[arg_num]);
} catch (e) {
str = "#<error>";
}
break;
}
}
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() {
return (type_ & (kStringRepresentationMask | kStringEncodingMask));
}

117
deps/v8/src/objects.cc

@ -5038,55 +5038,36 @@ int String::Utf8Length() {
}
Vector<const char> String::ToAsciiVector() {
ASSERT(IsAsciiRepresentation());
ASSERT(IsFlat());
int offset = 0;
String::FlatContent String::GetFlatContent() {
int length = this->length();
StringRepresentationTag string_tag = StringShape(this).representation_tag();
StringShape shape(this);
String* string = this;
if (string_tag == kConsStringTag) {
if (shape.representation_tag() == kConsStringTag) {
ConsString* cons = ConsString::cast(string);
ASSERT(cons->second()->length() == 0);
if (cons->second()->length() != 0) {
return FlatContent();
}
string = cons->first();
string_tag = StringShape(string).representation_tag();
shape = StringShape(string);
}
if (string_tag == kSeqStringTag) {
SeqAsciiString* seq = SeqAsciiString::cast(string);
char* start = seq->GetChars();
return Vector<const char>(start + offset, length);
if (shape.encoding_tag() == kAsciiStringTag) {
const char* start;
if (shape.representation_tag() == kSeqStringTag) {
start = SeqAsciiString::cast(string)->GetChars();
} else {
start = ExternalAsciiString::cast(string)->resource()->data();
}
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_tag = StringShape(string).representation_tag();
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();
}
if (string_tag == kSeqStringTag) {
SeqTwoByteString* seq = SeqTwoByteString::cast(string);
return Vector<const uc16>(seq->GetChars() + offset, length);
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;
Handle<String> str(str_);
ASSERT(str->IsFlat());
is_ascii_ = str->IsAsciiRepresentation();
String::FlatContent content = str->GetFlatContent();
ASSERT(content.IsFlat());
is_ascii_ = content.IsAscii();
if (is_ascii_) {
start_ = str->ToAsciiVector().start();
start_ = content.ToAsciiVector().start();
} else {
start_ = str->ToUC16Vector().start();
start_ = content.ToUC16Vector().start();
}
}
@ -5860,12 +5843,13 @@ template <typename IteratorA>
static inline bool CompareStringContentsPartial(Isolate* isolate,
IteratorA* ia,
String* b) {
if (b->IsFlat()) {
if (b->IsAsciiRepresentation()) {
VectorIterator<char> ib(b->ToAsciiVector());
String::FlatContent content = b->GetFlatContent();
if (content.IsFlat()) {
if (content.IsAscii()) {
VectorIterator<char> ib(content.ToAsciiVector());
return CompareStringContents(ia, &ib);
} else {
VectorIterator<uc16> ib(b->ToUC16Vector());
VectorIterator<uc16> ib(content.ToUC16Vector());
return CompareStringContents(ia, &ib);
}
} else {
@ -5904,16 +5888,18 @@ bool String::SlowEquals(String* other) {
}
Isolate* isolate = GetIsolate();
if (lhs->IsFlat()) {
if (lhs->IsAsciiRepresentation()) {
Vector<const char> vec1 = lhs->ToAsciiVector();
if (rhs->IsFlat()) {
if (rhs->IsAsciiRepresentation()) {
Vector<const char> vec2 = rhs->ToAsciiVector();
String::FlatContent lhs_content = lhs->GetFlatContent();
String::FlatContent rhs_content = rhs->GetFlatContent();
if (lhs_content.IsFlat()) {
if (lhs_content.IsAscii()) {
Vector<const char> vec1 = lhs_content.ToAsciiVector();
if (rhs_content.IsFlat()) {
if (rhs_content.IsAscii()) {
Vector<const char> vec2 = rhs_content.ToAsciiVector();
return CompareRawStringContents(vec1, vec2);
} else {
VectorIterator<char> buf1(vec1);
VectorIterator<uc16> ib(rhs->ToUC16Vector());
VectorIterator<uc16> ib(rhs_content.ToUC16Vector());
return CompareStringContents(&buf1, &ib);
}
} else {
@ -5923,14 +5909,14 @@ bool String::SlowEquals(String* other) {
isolate->objects_string_compare_buffer_b());
}
} else {
Vector<const uc16> vec1 = lhs->ToUC16Vector();
if (rhs->IsFlat()) {
if (rhs->IsAsciiRepresentation()) {
Vector<const uc16> vec1 = lhs_content.ToUC16Vector();
if (rhs_content.IsFlat()) {
if (rhs_content.IsAscii()) {
VectorIterator<uc16> buf1(vec1);
VectorIterator<char> ib(rhs->ToAsciiVector());
VectorIterator<char> ib(rhs_content.ToAsciiVector());
return CompareStringContents(&buf1, &ib);
} else {
Vector<const uc16> vec2(rhs->ToUC16Vector());
Vector<const uc16> vec2(rhs_content.ToUC16Vector());
return CompareRawStringContents(vec1, vec2);
}
} else {
@ -5983,8 +5969,10 @@ bool String::IsEqualTo(Vector<const char> str) {
bool String::IsAsciiEqualTo(Vector<const char> str) {
int slen = length();
if (str.length() != slen) return false;
if (IsFlat() && IsAsciiRepresentation()) {
return CompareChars(ToAsciiVector().start(), str.start(), slen) == 0;
FlatContent content = GetFlatContent();
if (content.IsAscii()) {
return CompareChars(content.ToAsciiVector().start(),
str.start(), slen) == 0;
}
for (int i = 0; i < slen; i++) {
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) {
int slen = length();
if (str.length() != slen) return false;
if (IsFlat() && IsTwoByteRepresentation()) {
return CompareChars(ToUC16Vector().start(), str.start(), slen) == 0;
FlatContent content = GetFlatContent();
if (content.IsTwoByte()) {
return CompareChars(content.ToUC16Vector().start(), str.start(), slen) == 0;
}
for (int i = 0; i < slen; i++) {
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 IsSymbol();
inline StringRepresentationTag representation_tag();
inline uint32_t encoding_tag();
inline uint32_t full_representation_tag();
inline uint32_t size_tag();
#ifdef DEBUG
@ -5820,6 +5821,51 @@ class StringShape BASE_EMBEDDED {
// All string values have a length field.
class String: public HeapObject {
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.
inline int length();
inline void set_length(int value);
@ -5831,10 +5877,10 @@ class String: public HeapObject {
inline bool IsAsciiRepresentation();
inline bool IsTwoByteRepresentation();
// Returns whether this string has ascii chars, i.e. all of them can
// be ascii encoded. This might be the case even if the string is
// 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
// 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
// possible.
@ -5868,8 +5914,12 @@ class String: public HeapObject {
// string.
inline String* TryFlattenGetString(PretenureFlag pretenure = NOT_TENURED);
Vector<const char> ToAsciiVector();
Vector<const uc16> ToUC16Vector();
// Tries to return the content of a flat string as a structure holding either
// 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
// 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()) {
const char* tag = objects_tags_.GetTag(object);
const char* name = collection_->names()->GetName(
GetConstructorNameForHeapProfile(JSObject::cast(object)));
GetConstructorName(JSObject::cast(object)));
if (tag != NULL) {
name = collection_->names()->GetFormatted("%s / %s", name, tag);
}
@ -1691,8 +1691,7 @@ HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object,
return AddEntry(object,
HeapEntry::kObject,
collection_->names()->GetName(
GetConstructorNameForHeapProfile(
JSObject::cast(object))),
GetConstructorName(JSObject::cast(object))),
children_count,
retainers_count);
} 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) {
if (!obj->IsHeapObject()) return NULL;
return filler_->FindOrAddEntry(obj, this);
@ -3250,10 +3274,4 @@ void HeapSnapshotJSONSerializer::SortHashMap(
sorted_entries->Sort(SortUsingEntryValue);
}
String* GetConstructorNameForHeapProfile(JSObject* object) {
if (object->IsJSFunction()) return HEAP->closure_symbol();
return object->constructor_name();
}
} } // namespace v8::internal

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

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

184
deps/v8/src/runtime.cc

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

2
deps/v8/src/string.js

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

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

@ -29,6 +29,7 @@
#include "api.h"
#include "arguments.h"
#include "ast.h"
#include "code-stubs.h"
#include "gdb-jit.h"
#include "ic-inl.h"
@ -1161,7 +1162,7 @@ void StubCache::Clear() {
}
void StubCache::CollectMatchingMaps(ZoneMapList* types,
void StubCache::CollectMatchingMaps(SmallMapList* types,
String* name,
Code::Flags flags) {
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
// validates the map chain as in the mono-morphic case.
class SmallMapList;
class StubCache;
class SCTableReference {
public:
Address address() const { return address_; }
@ -294,7 +296,7 @@ class StubCache {
void Clear();
// Collect all maps that match the name and flags.
void CollectMatchingMaps(ZoneMapList* types,
void CollectMatchingMaps(SmallMapList* types,
String* name,
Code::Flags flags);

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

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

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

@ -203,14 +203,16 @@ enum StringStubFeedback {
// Forward declarations.
class Assignment;
class UnaryOperation;
class BinaryOperation;
class Call;
class CaseClause;
class CompareOperation;
class CountOperation;
class CompilationInfo;
class CountOperation;
class Property;
class CaseClause;
class SmallMapList;
class UnaryOperation;
class TypeFeedbackOracle BASE_EMBEDDED {
public:
@ -225,13 +227,18 @@ class TypeFeedbackOracle BASE_EMBEDDED {
Handle<Map> LoadMonomorphicReceiverType(Property* expr);
Handle<Map> StoreMonomorphicReceiverType(Expression* expr);
ZoneMapList* LoadReceiverTypes(Property* expr, Handle<String> name);
ZoneMapList* StoreReceiverTypes(Assignment* expr, Handle<String> name);
ZoneMapList* CallReceiverTypes(Call* expr,
void LoadReceiverTypes(Property* expr,
Handle<String> name,
SmallMapList* types);
void StoreReceiverTypes(Assignment* expr,
Handle<String> name,
SmallMapList* types);
void CallReceiverTypes(Call* expr,
Handle<String> name,
CallKind call_kind);
CallKind call_kind,
SmallMapList* types);
void CollectKeyedReceiverTypes(unsigned ast_id,
ZoneMapList* types);
SmallMapList* types);
CheckType GetCallCheckType(Call* expr);
Handle<JSObject> GetPrototypeForPrimitiveCheck(CheckType check);
@ -252,9 +259,10 @@ class TypeFeedbackOracle BASE_EMBEDDED {
TypeInfo IncrementType(CountOperation* expr);
private:
ZoneMapList* CollectReceiverTypes(unsigned ast_id,
void CollectReceiverTypes(unsigned ast_id,
Handle<String> name,
Code::Flags flags);
Code::Flags flags,
SmallMapList* types);
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.
#define MAJOR_VERSION 3
#define MINOR_VERSION 5
#define BUILD_NUMBER 7
#define BUILD_NUMBER 8
#define PATCH_LEVEL 0
// Use 1 for candidates and 0 otherwise.
// (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
// nesting and cleans up generated ASTs in the Zone when exiting the
// 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));
uint16_t answer7[] = {'d', 0x101};
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;";
Local<Value> result = CompileRun(init_code);
Local<Value> indexof = CompileRun("str2.indexOf('els')");
Local<Value> lastindexof = CompileRun("str2.lastIndexOf('dab')");
CHECK(result->IsString());
i::Handle<i::String> string = v8::Utils::OpenHandle(String::Cast(*result));
int length = string->length();
@ -13758,6 +13795,10 @@ THREADED_TEST(TwoByteStringInAsciiCons) {
ExpectString("str2.charAt(2);", "e");
ExpectObject("str2.indexOf('els');", indexof);
ExpectObject("str2.lastIndexOf('dab');", lastindexof);
reresult = CompileRun("str2.charCodeAt(2);");
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);
}
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("", 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