diff --git a/deps/v8/ChangeLog b/deps/v8/ChangeLog index aeeea78ac1..6b4506421d 100644 --- a/deps/v8/ChangeLog +++ b/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. diff --git a/deps/v8/include/v8-debug.h b/deps/v8/include/v8-debug.h old mode 100755 new mode 100644 diff --git a/deps/v8/include/v8.h b/deps/v8/include/v8.h index e722d34e67..5a781607f7 100644 --- a/deps/v8/include/v8.h +++ b/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); }; diff --git a/deps/v8/src/SConscript b/deps/v8/src/SConscript old mode 100755 new mode 100644 diff --git a/deps/v8/src/api.cc b/deps/v8/src/api.cc index 5a5f14dc65..0207f51eb4 100644 --- a/deps/v8/src/api.cc +++ b/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 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 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 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 Context::GetEntered() { i::Isolate* isolate = i::Isolate::Current(); - if (IsDeadCheck(isolate, "v8::Context::GetEntered()")) { + if (!EnsureInitializedForIsolate(isolate, "v8::Context::GetEntered()")) { return Local(); } i::Handle last = diff --git a/deps/v8/src/arm/assembler-arm.h b/deps/v8/src/arm/assembler-arm.h index 97d4226503..9a586936fe 100644 --- a/deps/v8/src/arm/assembler-arm.h +++ b/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(0)); + } INLINE(explicit Operand(const ExternalReference& f)); explicit Operand(Handle handle); INLINE(explicit Operand(Smi* value)); diff --git a/deps/v8/src/arm/code-stubs-arm.cc b/deps/v8/src/arm/code-stubs-arm.cc index 82fa8ceaf3..ba345e24ba 100644 --- a/deps/v8/src/arm/code-stubs-arm.cc +++ b/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, ¬_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(¬_in_dictionary); - __ mov(result, Operand(0)); + __ mov(result, Operand::Zero()); __ Ret(); } diff --git a/deps/v8/src/arm/full-codegen-arm.cc b/deps/v8/src/arm/full-codegen-arm.cc index d8ce956ec9..97f7fea793 100644 --- a/deps/v8/src/arm/full-codegen-arm.cc +++ b/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); diff --git a/deps/v8/src/arm/lithium-arm.cc b/deps/v8/src/arm/lithium-arm.cc index 65ef3e6e1f..38f77cda4c 100644 --- a/deps/v8/src/arm/lithium-arm.cc +++ b/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); diff --git a/deps/v8/src/arm/lithium-codegen-arm.cc b/deps/v8/src/arm/lithium-codegen-arm.cc index 4e135d66b5..3469bb63a8 100644 --- a/deps/v8/src/arm/lithium-codegen-arm.cc +++ b/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; diff --git a/deps/v8/src/arm/lithium-gap-resolver-arm.cc b/deps/v8/src/arm/lithium-gap-resolver-arm.cc index 02608a6950..26f60fac11 100644 --- a/deps/v8/src/arm/lithium-gap-resolver-arm.cc +++ b/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()) { diff --git a/deps/v8/src/arm/stub-cache-arm.cc b/deps/v8/src/arm/stub-cache-arm.cc index 1767b9d5b2..16e6468422 100644 --- a/deps/v8/src/arm/stub-cache-arm.cc +++ b/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(value))); diff --git a/deps/v8/src/ast.cc b/deps/v8/src/ast.cc index 3e6d856ce4..7319abe6dd 100644 --- a/deps/v8/src/ast.cc +++ b/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 name = Handle::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 name = Handle::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,15 +789,14 @@ void Call::RecordTypeFeedback(TypeFeedbackOracle* oracle, Literal* key = property->key()->AsLiteral(); ASSERT(key != NULL && key->handle()->IsString()); Handle name = Handle::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(); - for (int i = 0; i < length; i++) { - Handle map = receiver_types_->at(i); - ASSERT(!map.is_null() && *map != NULL); - } + int length = receiver_types_.length(); + for (int i = 0; i < length; i++) { + Handle map = receiver_types_.at(i); + ASSERT(!map.is_null() && *map != NULL); } } #endif @@ -805,9 +804,9 @@ void Call::RecordTypeFeedback(TypeFeedbackOracle* oracle, check_type_ = oracle->GetCallCheckType(this); if (is_monomorphic_) { Handle 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( diff --git a/deps/v8/src/ast.h b/deps/v8/src/ast.h index 4031b7d810..399d27894c 100644 --- a/deps/v8/src/ast.h +++ b/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 handle) { + list_.Add(handle.location()); + } + + Handle at(int i) const { + return Handle(list_.at(i)); + } + + Handle first() const { return at(0); } + Handle last() const { return at(length() - 1); } + + private: + // The list stores pointers to Map*, that is Map**, so it's GC safe. + SmallPointerList 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 GetMonomorphicReceiverType() { - UNREACHABLE(); - return Handle(); + Handle 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 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 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 target() { return target_; } @@ -1310,7 +1337,7 @@ class Call: public Expression { bool is_monomorphic_; CheckType check_type_; - ZoneMapList* receiver_types_; + SmallMapList receiver_types_; Handle target_; Handle holder_; Handle 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 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 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 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 monomorphic_receiver_type_; + SmallMapList receiver_types_; }; diff --git a/deps/v8/src/compiler.cc b/deps/v8/src/compiler.cc old mode 100755 new mode 100644 diff --git a/deps/v8/src/d8.cc b/deps/v8/src/d8.cc index 780b0c0716..120496eccc 100644 --- a/deps/v8/src/d8.cc +++ b/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; } diff --git a/deps/v8/src/handles.cc b/deps/v8/src/handles.cc index c9984aa92f..8c6439b227 100644 --- a/deps/v8/src/handles.cc +++ b/deps/v8/src/handles.cc @@ -617,15 +617,17 @@ Handle CalculateLineEnds(Handle 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); } } diff --git a/deps/v8/src/hydrogen-instructions.cc b/deps/v8/src/hydrogen-instructions.cc index 71c59b5d9e..d3cc8a62b4 100644 --- a/deps/v8/src/hydrogen-instructions.cc +++ b/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 name) : types_(Min(types->length(), kMaxLoadPolymorphism)), name_(name), diff --git a/deps/v8/src/hydrogen-instructions.h b/deps/v8/src/hydrogen-instructions.h index e7a9104e87..76007d764e 100644 --- a/deps/v8/src/hydrogen-instructions.h +++ b/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 name); HValue* context() { return OperandAt(0); } HValue* object() { return OperandAt(1); } - ZoneMapList* types() { return &types_; } + SmallMapList* types() { return &types_; } Handle 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 name_; bool need_generic_; }; diff --git a/deps/v8/src/hydrogen.cc b/deps/v8/src/hydrogen.cc index ca0aebbbb9..d321aacb08 100644 --- a/deps/v8/src/hydrogen.cc +++ b/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 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 name = Handle::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 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 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 name = prop->key()->AsLiteral()->AsPropertyName(); - ZoneMapList* types = expr->GetReceiverTypes(); + SmallMapList* types = expr->GetReceiverTypes(); HValue* receiver = environment()->ExpressionStackAt(expr->arguments()->length()); if (expr->IsMonomorphic()) { - Handle receiver_map = - (types == NULL) ? Handle::null() : types->first(); + Handle receiver_map = (types == NULL || types->is_empty()) + ? Handle::null() + : types->first(); if (TryInlineBuiltinFunction(expr, receiver, receiver_map, diff --git a/deps/v8/src/hydrogen.h b/deps/v8/src/hydrogen.h index 99225511c5..c18ba58153 100644 --- a/deps/v8/src/hydrogen.h +++ b/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 name); void HandlePolymorphicCallNamed(Call* expr, HValue* receiver, - ZoneMapList* types, + SmallMapList* types, Handle name); void HandleLiteralCompareTypeof(CompareOperation* compare_expr, Expression* expr, diff --git a/deps/v8/src/interpreter-irregexp.cc b/deps/v8/src/interpreter-irregexp.cc index 1c6c52ca89..796a447e2f 100644 --- a/deps/v8/src/interpreter-irregexp.cc +++ b/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 subject_vector = subject->ToAsciiVector(); + String::FlatContent subject_content = subject->GetFlatContent(); + if (subject_content.IsAscii()) { + Vector 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 subject_vector = subject->ToUC16Vector(); + ASSERT(subject_content.IsTwoByte()); + Vector subject_vector = subject_content.ToUC16Vector(); if (start_position != 0) previous_char = subject_vector[start_position - 1]; return RawMatch(isolate, code_base, diff --git a/deps/v8/src/jsregexp.cc b/deps/v8/src/jsregexp.cc index af644376b5..62d93a7220 100644 --- a/deps/v8/src/jsregexp.cc +++ b/deps/v8/src/jsregexp.cc @@ -212,19 +212,7 @@ static void SetAtomLastCapture(FixedArray* array, RegExpImpl::SetCapture(array, 1, to); } - /* template , typename PatternChar> -static int ReStringMatch(Vector sub_vector, - Vector 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 RegExpImpl::AtomExec(Handle re, Handle subject, int index, @@ -237,35 +225,39 @@ Handle RegExpImpl::AtomExec(Handle 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()) - return isolate->factory()->null_value(); + 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(); } diff --git a/deps/v8/src/messages.js b/deps/v8/src/messages.js index 8ea31eaadb..cbbb70eb1a 100644 --- a/deps/v8/src/messages.js +++ b/deps/v8/src/messages.js @@ -57,11 +57,13 @@ 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; - try { - str = ToDetailString(args[arg_num]); - } catch (e) { - str = "#"; + if (str == kReplacementMarkers[arg_num]) { + try { + str = ToDetailString(args[arg_num]); + } catch (e) { + str = "#"; + } + break; } } result += str; diff --git a/deps/v8/src/objects-inl.h b/deps/v8/src/objects-inl.h index c5fda89e42..098bd7a5c7 100644 --- a/deps/v8/src/objects-inl.h +++ b/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)); } diff --git a/deps/v8/src/objects.cc b/deps/v8/src/objects.cc index 1b29071324..0bf4c1843c 100644 --- a/deps/v8/src/objects.cc +++ b/deps/v8/src/objects.cc @@ -5038,55 +5038,36 @@ int String::Utf8Length() { } -Vector 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); - string = cons->first(); - string_tag = StringShape(string).representation_tag(); - } - if (string_tag == kSeqStringTag) { - SeqAsciiString* seq = SeqAsciiString::cast(string); - char* start = seq->GetChars(); - return Vector(start + offset, length); - } - ASSERT(string_tag == kExternalStringTag); - ExternalAsciiString* ext = ExternalAsciiString::cast(string); - const char* start = ext->resource()->data(); - return Vector(start + offset, length); -} - - -Vector 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); + if (cons->second()->length() != 0) { + return FlatContent(); + } string = cons->first(); - string_tag = StringShape(string).representation_tag(); + shape = StringShape(string); } - if (string_tag == kSeqStringTag) { - SeqTwoByteString* seq = SeqTwoByteString::cast(string); - return Vector(seq->GetChars() + 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(); + } + return FlatContent(Vector(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(start, length)); } - ASSERT(string_tag == kExternalStringTag); - ExternalTwoByteString* ext = ExternalTwoByteString::cast(string); - const uc16* start = - reinterpret_cast(ext->resource()->data()); - return Vector(start + offset, length); } @@ -5536,11 +5517,13 @@ void FlatStringReader::PostGarbageCollection() { if (str_ == NULL) return; Handle 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 static inline bool CompareStringContentsPartial(Isolate* isolate, IteratorA* ia, String* b) { - if (b->IsFlat()) { - if (b->IsAsciiRepresentation()) { - VectorIterator ib(b->ToAsciiVector()); + String::FlatContent content = b->GetFlatContent(); + if (content.IsFlat()) { + if (content.IsAscii()) { + VectorIterator ib(content.ToAsciiVector()); return CompareStringContents(ia, &ib); } else { - VectorIterator ib(b->ToUC16Vector()); + VectorIterator 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 vec1 = lhs->ToAsciiVector(); - if (rhs->IsFlat()) { - if (rhs->IsAsciiRepresentation()) { - Vector vec2 = rhs->ToAsciiVector(); + String::FlatContent lhs_content = lhs->GetFlatContent(); + String::FlatContent rhs_content = rhs->GetFlatContent(); + if (lhs_content.IsFlat()) { + if (lhs_content.IsAscii()) { + Vector vec1 = lhs_content.ToAsciiVector(); + if (rhs_content.IsFlat()) { + if (rhs_content.IsAscii()) { + Vector vec2 = rhs_content.ToAsciiVector(); return CompareRawStringContents(vec1, vec2); } else { VectorIterator buf1(vec1); - VectorIterator ib(rhs->ToUC16Vector()); + VectorIterator 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 vec1 = lhs->ToUC16Vector(); - if (rhs->IsFlat()) { - if (rhs->IsAsciiRepresentation()) { + Vector vec1 = lhs_content.ToUC16Vector(); + if (rhs_content.IsFlat()) { + if (rhs_content.IsAscii()) { VectorIterator buf1(vec1); - VectorIterator ib(rhs->ToAsciiVector()); + VectorIterator ib(rhs_content.ToAsciiVector()); return CompareStringContents(&buf1, &ib); } else { - Vector vec2(rhs->ToUC16Vector()); + Vector vec2(rhs_content.ToUC16Vector()); return CompareRawStringContents(vec1, vec2); } } else { @@ -5983,8 +5969,10 @@ bool String::IsEqualTo(Vector str) { bool String::IsAsciiEqualTo(Vector 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(str[i])) return false; @@ -5996,8 +5984,9 @@ bool String::IsAsciiEqualTo(Vector str) { bool String::IsTwoByteEqualTo(Vector 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; diff --git a/deps/v8/src/objects.h b/deps/v8/src/objects.h index 93f7a1d119..fc5d2e7ecc 100644 --- a/deps/v8/src/objects.h +++ b/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 ToAsciiVector() { + ASSERT_EQ(ASCII, state_); + return Vector::cast(buffer_); + } + // Return the two-byte content of the string. Only use if IsTwoByte() + // returns true. + Vector ToUC16Vector() { + ASSERT_EQ(TWO_BYTE, state_); + return Vector::cast(buffer_); + } + + private: + enum State { NON_FLAT, ASCII, TWO_BYTE }; + + // Constructors only used by String::GetFlatContent(). + explicit FlatContent(Vector chars) + : buffer_(Vector::cast(chars)), + state_(ASCII) { } + explicit FlatContent(Vector chars) + : buffer_(Vector::cast(chars)), + state_(TWO_BYTE) { } + FlatContent() : buffer_(), state_(NON_FLAT) { } + + Vector 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 ToAsciiVector(); - Vector 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. diff --git a/deps/v8/src/profile-generator.cc b/deps/v8/src/profile-generator.cc index 07426f2939..db9f8928de 100644 --- a/deps/v8/src/profile-generator.cc +++ b/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 diff --git a/deps/v8/src/profile-generator.h b/deps/v8/src/profile-generator.h index d1c2b3804a..9ab44a1e21 100644 --- a/deps/v8/src/profile-generator.h +++ b/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_ diff --git a/deps/v8/src/runtime.cc b/deps/v8/src/runtime.cc index f629970ff2..fd866bf85b 100644 --- a/deps/v8/src/runtime.cc +++ b/deps/v8/src/runtime.cc @@ -2663,21 +2663,22 @@ class CompiledReplacement { void CompiledReplacement::Compile(Handle replacement, int capture_count, 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; - - ParseReplacementPattern(&parts_, - replacement->ToUC16Vector(), - capture_count, - subject_length); + String::FlatContent content = replacement->GetFlatContent(); + ASSERT(content.IsFlat()); + if (content.IsAscii()) { + ParseReplacementPattern(&parts_, + content.ToAsciiVector(), + capture_count, + subject_length); + } else { + ASSERT(content.IsTwoByte()); + ParseReplacementPattern(&parts_, + content.ToUC16Vector(), + capture_count, + subject_length); + } } Isolate* isolate = replacement->GetIsolate(); // 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 // 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 pat_vector = seq_pat->ToAsciiVector(); - if (seq_sub->IsAsciiRepresentation()) { + if (seq_pat.IsAscii()) { + Vector 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 pat_vector = seq_pat->ToUC16Vector(); - if (seq_sub->IsAsciiRepresentation()) { + Vector 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 pat_vector = pat->ToAsciiVector(); - if (sub->IsAsciiRepresentation()) { - position = StringMatchBackwards(sub->ToAsciiVector(), + if (pat_content.IsAscii()) { + Vector 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 pat_vector = pat->ToUC16Vector(); - if (sub->IsAsciiRepresentation()) { - position = StringMatchBackwards(sub->ToAsciiVector(), + Vector 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 subject_vector = subject->ToAsciiVector(); - if (pattern->IsAsciiRepresentation()) { + String::FlatContent subject_content = subject->GetFlatContent(); + String::FlatContent pattern_content = pattern->GetFlatContent(); + if (subject_content.IsAscii()) { + Vector 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 subject_vector = subject->ToUC16Vector(); - if (pattern->IsAsciiRepresentation()) { + Vector 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(isolate, - str->ToUC16Vector()); + flat.ToUC16Vector()); } else { return QuoteJsonString(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(isolate, - str->ToUC16Vector()); + flat.ToUC16Vector()); } else { return QuoteJsonString(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(isolate, write_cursor, - str->ToUC16Vector()); + content.ToUC16Vector()); } else { write_cursor = WriteQuoteJsonString(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 subject_vector = subject->ToAsciiVector(); - if (pattern->IsAsciiRepresentation()) { - Vector 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 subject_vector = subject_content.ToAsciiVector(); + if (pattern_content.IsAscii()) { + Vector 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 subject_vector = subject->ToUC16Vector(); + Vector 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,36 +6093,39 @@ 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(Min(s->length(), limit)); Handle 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::cast(obj), isolate); - - Vector chars = s->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(), - chars.start(), - *elements, - length); - - for (int i = num_copied_from_cache; i < length; ++i) { - Handle str = LookupSingleCharacterStringFromCode(chars[i]); - elements->set(i, *str); + String::FlatContent content = s->GetFlatContent(); + if (content.IsAscii()) { + Vector chars = content.ToAsciiVector(); + // Note, this will initialize all elements (not only the prefix) + // to prevent GC from seeing partially initialized array. + position = CopyCachedAsciiCharsToArray(isolate->heap(), + chars.start(), + *elements, + length); + } else { + MemsetPointer(elements->data_start(), + isolate->heap()->undefined_value(), + length); } } else { elements = isolate->factory()->NewFixedArray(length); - for (int i = 0; i < length; ++i) { - Handle str = LookupSingleCharacterStringFromCode(s->Get(i)); - elements->set(i, *str); - } + } + for (int i = position; i < length; ++i) { + Handle str = LookupSingleCharacterStringFromCode(s->Get(i)); + elements->set(i, *str); } #ifdef DEBUG @@ -6921,22 +6936,24 @@ static Object* FlatStringCompare(String* x, String* y) { equal_prefix_result = Smi::FromInt(LESS); } int r; - if (x->IsAsciiRepresentation()) { - Vector x_chars = x->ToAsciiVector(); - if (y->IsAsciiRepresentation()) { - Vector y_chars = y->ToAsciiVector(); + String::FlatContent x_content = x->GetFlatContent(); + String::FlatContent y_content = y->GetFlatContent(); + if (x_content.IsAscii()) { + Vector x_chars = x_content.ToAsciiVector(); + if (y_content.IsAscii()) { + Vector y_chars = y_content.ToAsciiVector(); r = CompareChars(x_chars.start(), y_chars.start(), prefix_length); } else { - Vector y_chars = y->ToUC16Vector(); + Vector y_chars = y_content.ToUC16Vector(); r = CompareChars(x_chars.start(), y_chars.start(), prefix_length); } } else { - Vector x_chars = x->ToUC16Vector(); - if (y->IsAsciiRepresentation()) { - Vector y_chars = y->ToAsciiVector(); + Vector x_chars = x_content.ToUC16Vector(); + if (y_content.IsAscii()) { + Vector y_chars = y_content.ToAsciiVector(); r = CompareChars(x_chars.start(), y_chars.start(), prefix_length); } else { - Vector y_chars = y->ToUC16Vector(); + Vector 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 chars = format->ToAsciiVector(); + String::FlatContent format_content = format->GetFlatContent(); + RUNTIME_ASSERT(format_content.IsAscii()); + Vector chars = format_content.ToAsciiVector(); LOGGER->LogRuntime(chars, elms); return isolate->heap()->undefined_value(); } diff --git a/deps/v8/src/scanner.cc b/deps/v8/src/scanner.cc old mode 100755 new mode 100644 diff --git a/deps/v8/src/small-pointer-list.h b/deps/v8/src/small-pointer-list.h index 6291d9ee86..6c5ce890d2 100644 --- a/deps/v8/src/small-pointer-list.h +++ b/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(list), kPointerAlignment)); + data_ = reinterpret_cast(list) | kListTag; + } + + void Clear() { + data_ = kEmptyTag; + } + bool is_empty() const { return length() == 0; } int length() const { diff --git a/deps/v8/src/string.js b/deps/v8/src/string.js index e0f20c2f69..08fccc4f05 100644 --- a/deps/v8/src/string.js +++ b/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; } } } diff --git a/deps/v8/src/stub-cache.cc b/deps/v8/src/stub-cache.cc index 79cd7a0d22..13b0b633b1 100644 --- a/deps/v8/src/stub-cache.cc +++ b/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++) { diff --git a/deps/v8/src/stub-cache.h b/deps/v8/src/stub-cache.h index ffe4241ec1..a97a4cdab2 100644 --- a/deps/v8/src/stub-cache.h +++ b/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); diff --git a/deps/v8/src/type-info.cc b/deps/v8/src/type-info.cc index e10c5f40e4..bdf7bc3c86 100644 --- a/deps/v8/src/type-info.cc +++ b/deps/v8/src/type-info.cc @@ -159,23 +159,26 @@ Handle TypeFeedbackOracle::StoreMonomorphicReceiverType(Expression* expr) { } -ZoneMapList* TypeFeedbackOracle::LoadReceiverTypes(Property* expr, - Handle name) { +void TypeFeedbackOracle::LoadReceiverTypes(Property* expr, + Handle 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 name) { +void TypeFeedbackOracle::StoreReceiverTypes(Assignment* expr, + Handle 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, - Handle name, - CallKind call_kind) { +void TypeFeedbackOracle::CallReceiverTypes(Call* expr, + Handle name, + 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, - Handle name, - Code::Flags flags) { +void TypeFeedbackOracle::CollectReceiverTypes(unsigned ast_id, + Handle name, + Code::Flags flags, + SmallMapList* types) { Isolate* isolate = Isolate::Current(); Handle 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::cast(object)->ic_state() == MEGAMORPHIC); - return NULL; } else if (object->IsMap()) { - ZoneMapList* types = new ZoneMapList(1); types->Add(Handle::cast(object)); - return types; } else if (Handle::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 = GetInfo(ast_id); if (!object->IsCode()) return; Handle code = Handle::cast(object); diff --git a/deps/v8/src/type-info.h b/deps/v8/src/type-info.h index dee4c34c92..448e4c94e7 100644 --- a/deps/v8/src/type-info.h +++ b/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 LoadMonomorphicReceiverType(Property* expr); Handle StoreMonomorphicReceiverType(Expression* expr); - ZoneMapList* LoadReceiverTypes(Property* expr, Handle name); - ZoneMapList* StoreReceiverTypes(Assignment* expr, Handle name); - ZoneMapList* CallReceiverTypes(Call* expr, - Handle name, - CallKind call_kind); + void LoadReceiverTypes(Property* expr, + Handle name, + SmallMapList* types); + void StoreReceiverTypes(Assignment* expr, + Handle name, + SmallMapList* types); + void CallReceiverTypes(Call* expr, + Handle name, + CallKind call_kind, + SmallMapList* types); void CollectKeyedReceiverTypes(unsigned ast_id, - ZoneMapList* types); + SmallMapList* types); CheckType GetCallCheckType(Call* expr); Handle GetPrototypeForPrimitiveCheck(CheckType check); @@ -252,9 +259,10 @@ class TypeFeedbackOracle BASE_EMBEDDED { TypeInfo IncrementType(CountOperation* expr); private: - ZoneMapList* CollectReceiverTypes(unsigned ast_id, - Handle name, - Code::Flags flags); + void CollectReceiverTypes(unsigned ast_id, + Handle name, + Code::Flags flags, + SmallMapList* types); void SetInfo(unsigned ast_id, Object* target); diff --git a/deps/v8/src/version.cc b/deps/v8/src/version.cc index e3cecdf99d..fd168e3869 100644 --- a/deps/v8/src/version.cc +++ b/deps/v8/src/version.cc @@ -34,7 +34,7 @@ // cannot be changed without changing the SCons build script. #define MAJOR_VERSION 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.) diff --git a/deps/v8/src/zone.h b/deps/v8/src/zone.h index faad3b7ccd..4dfd01d358 100644 --- a/deps/v8/src/zone.h +++ b/deps/v8/src/zone.h @@ -200,10 +200,6 @@ class ZoneList: public List { }; -// Introduce a convenience type for zone lists of map handles. -typedef ZoneList > 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. diff --git a/deps/v8/test/cctest/test-api.cc b/deps/v8/test/cctest/test-api.cc index 3ed6b523f0..aeb4cbe522 100644 --- a/deps/v8/test/cctest/test-api.cc +++ b/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 result = CompileRun(init_code); + Local indexof = CompileRun("str2.indexOf('els')"); + Local lastindexof = CompileRun("str2.lastIndexOf('dab')"); + CHECK(result->IsString()); i::Handle 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('e'), reresult->Int32Value()); } diff --git a/deps/v8/test/cctest/test-heap-profiler.cc b/deps/v8/test/cctest/test-heap-profiler.cc index 169e6dcbdb..24d96193a2 100644 --- a/deps/v8/test/cctest/test-heap-profiler.cc +++ b/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 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 js_global = + env->Global()->GetPrototype().As(); + v8::Local obj1 = js_global->Get(v8_str("obj1")).As(); + i::Handle js_obj1 = v8::Utils::OpenHandle(*obj1); + CHECK_EQ(0, StringCmp( + "Constructor1", i::V8HeapExplorer::GetConstructorName(*js_obj1))); + v8::Local obj2 = js_global->Get(v8_str("obj2")).As(); + i::Handle js_obj2 = v8::Utils::OpenHandle(*obj2); + CHECK_EQ(0, StringCmp( + "Constructor2", i::V8HeapExplorer::GetConstructorName(*js_obj2))); + v8::Local obj3 = js_global->Get(v8_str("obj3")).As(); + i::Handle js_obj3 = v8::Utils::OpenHandle(*obj3); + CHECK_EQ(0, StringCmp( + "Constructor3", i::V8HeapExplorer::GetConstructorName(*js_obj3))); + v8::Local obj4 = js_global->Get(v8_str("obj4")).As(); + i::Handle js_obj4 = v8::Utils::OpenHandle(*obj4); + CHECK_EQ(0, StringCmp( + "Constructor4", i::V8HeapExplorer::GetConstructorName(*js_obj4))); + v8::Local obj5 = js_global->Get(v8_str("obj5")).As(); + i::Handle js_obj5 = v8::Utils::OpenHandle(*obj5); + CHECK_EQ(0, StringCmp( + "Object", i::V8HeapExplorer::GetConstructorName(*js_obj5))); + v8::Local obj6 = js_global->Get(v8_str("obj6")).As(); + i::Handle js_obj6 = v8::Utils::OpenHandle(*obj6); + CHECK_EQ(0, StringCmp( + "Object", i::V8HeapExplorer::GetConstructorName(*js_obj6))); +} diff --git a/deps/v8/test/message/replacement-marker-as-argument.js b/deps/v8/test/message/replacement-marker-as-argument.js new file mode 100644 index 0000000000..9036654d98 --- /dev/null +++ b/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; \ No newline at end of file diff --git a/deps/v8/test/message/replacement-marker-as-argument.out b/deps/v8/test/message/replacement-marker-as-argument.out new file mode 100644 index 0000000000..a91fe5b7e2 --- /dev/null +++ b/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 # which has only a getter +o["%%3"] = 10; + ^ +TypeError: Cannot set property %%3 of # which has only a getter + at *%(basename)s:31:9 diff --git a/deps/v8/test/mjsunit/string-split.js b/deps/v8/test/mjsunit/string-split.js index 6fcf55799e..bc50945135 100644 --- a/deps/v8/test/mjsunit/string-split.js +++ b/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)); +}