Update V8 to r5214 as required by WebKit r65072.
Change-Id: I387277a00cc0949597c0f69a8e4f2da60213c8f2
diff --git a/src/arm/assembler-arm-inl.h b/src/arm/assembler-arm-inl.h
index 114ec23..5be5770 100644
--- a/src/arm/assembler-arm-inl.h
+++ b/src/arm/assembler-arm-inl.h
@@ -120,9 +120,8 @@
void RelocInfo::set_call_address(Address target) {
- ASSERT(IsPatchedReturnSequence());
- // The 2 instructions offset assumes patched return sequence.
- ASSERT(IsJSReturn(rmode()));
+ ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) ||
+ (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence()));
Memory::Address_at(pc_ + 2 * Assembler::kInstrSize) = target;
}
@@ -132,16 +131,15 @@
}
-Object** RelocInfo::call_object_address() {
- ASSERT(IsPatchedReturnSequence());
- // The 2 instructions offset assumes patched return sequence.
- ASSERT(IsJSReturn(rmode()));
- return reinterpret_cast<Object**>(pc_ + 2 * Assembler::kInstrSize);
+void RelocInfo::set_call_object(Object* target) {
+ *call_object_address() = target;
}
-void RelocInfo::set_call_object(Object* target) {
- *call_object_address() = target;
+Object** RelocInfo::call_object_address() {
+ ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) ||
+ (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence()));
+ return reinterpret_cast<Object**>(pc_ + 2 * Assembler::kInstrSize);
}
diff --git a/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc
index 1271e80..4bcf1a0 100644
--- a/src/arm/codegen-arm.cc
+++ b/src/arm/codegen-arm.cc
@@ -1628,6 +1628,7 @@
// The function and its two arguments have been dropped.
frame_->Drop(); // Drop the receiver as well.
frame_->EmitPush(r0);
+ frame_->SpillAll(); // A spilled frame is also jumping to label done.
// Stack now has 1 element:
// sp[0]: result
__ bind(&done);
@@ -3279,13 +3280,13 @@
FixedArray::kHeaderSize + node->literal_index() * kPointerSize;
__ ldr(literal, FieldMemOperand(tmp, literal_offset));
- JumpTarget done;
+ JumpTarget materialized;
__ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
__ cmp(literal, ip);
// This branch locks the virtual frame at the done label to match the
// one we have here, where the literal register is not on the stack and
// nothing is spilled.
- done.Branch(ne);
+ materialized.Branch(ne);
// If the entry is undefined we call the runtime system to compute
// the literal.
@@ -3300,11 +3301,23 @@
frame_->CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
__ Move(literal, r0);
- // This call to bind will get us back to the virtual frame we had before
- // where things are not spilled and the literal register is not on the stack.
- done.Bind();
- // Push the literal.
+ materialized.Bind();
+
frame_->EmitPush(literal);
+ int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
+ frame_->EmitPush(Operand(Smi::FromInt(size)));
+ frame_->CallRuntime(Runtime::kAllocateInNewSpace, 1);
+ // TODO(lrn): Use AllocateInNewSpace macro with fallback to runtime.
+ // r0 is newly allocated space.
+
+ // Reuse literal variable with (possibly) a new register, still holding
+ // the materialized boilerplate.
+ literal = frame_->PopToRegister(r0);
+
+ __ CopyFields(r0, literal, tmp.bit(), size / kPointerSize);
+
+ // Push the clone.
+ frame_->EmitPush(r0);
ASSERT_EQ(original_height + 1, frame_->height());
}
@@ -5323,6 +5336,44 @@
}
+void CodeGenerator::GenerateIsRegExpEquivalent(ZoneList<Expression*>* args) {
+ ASSERT(args->length() == 2);
+
+ // Load the two objects into registers and perform the comparison.
+ Load(args->at(0));
+ Load(args->at(1));
+ Register right = frame_->PopToRegister();
+ Register left = frame_->PopToRegister(right);
+ Register tmp = frame_->scratch0();
+ Register tmp2 = frame_->scratch1();
+
+ // Jumps to done must have the eq flag set if the test is successful
+ // and clear if the test has failed.
+ Label done;
+
+ // Fail if either is a non-HeapObject.
+ __ cmp(left, Operand(right));
+ __ b(eq, &done);
+ __ and_(tmp, left, Operand(right));
+ __ eor(tmp, tmp, Operand(kSmiTagMask));
+ __ tst(tmp, Operand(kSmiTagMask));
+ __ b(ne, &done);
+ __ ldr(tmp, FieldMemOperand(left, HeapObject::kMapOffset));
+ __ ldrb(tmp2, FieldMemOperand(tmp, Map::kInstanceTypeOffset));
+ __ cmp(tmp2, Operand(JS_REGEXP_TYPE));
+ __ b(ne, &done);
+ __ ldr(tmp2, FieldMemOperand(right, HeapObject::kMapOffset));
+ __ cmp(tmp, Operand(tmp2));
+ __ b(ne, &done);
+ __ ldr(tmp, FieldMemOperand(left, JSRegExp::kDataOffset));
+ __ ldr(tmp2, FieldMemOperand(right, JSRegExp::kDataOffset));
+ __ cmp(tmp, tmp2);
+ __ bind(&done);
+ cc_reg_ = eq;
+}
+
+
+
void CodeGenerator::VisitCallRuntime(CallRuntime* node) {
#ifdef DEBUG
int original_height = frame_->height();
@@ -6907,10 +6958,7 @@
__ str(r2, FieldMemOperand(r0, JSArray::kElementsOffset));
// Copy the elements array.
- for (int i = 0; i < elements_size; i += kPointerSize) {
- __ ldr(r1, FieldMemOperand(r3, i));
- __ str(r1, FieldMemOperand(r2, i));
- }
+ __ CopyFields(r2, r3, r1.bit(), elements_size / kPointerSize);
}
// Return and remove the on-stack parameters.
@@ -9779,10 +9827,7 @@
__ ldr(r4, MemOperand(r4, offset));
// Copy the JS object part.
- for (int i = 0; i < JSObject::kHeaderSize; i += kPointerSize) {
- __ ldr(r3, FieldMemOperand(r4, i));
- __ str(r3, FieldMemOperand(r0, i));
- }
+ __ CopyFields(r0, r4, r3.bit(), JSObject::kHeaderSize / kPointerSize);
// Setup the callee in-object property.
STATIC_ASSERT(Heap::arguments_callee_index == 0);
diff --git a/src/arm/codegen-arm.h b/src/arm/codegen-arm.h
index 492e000..bfe2080 100644
--- a/src/arm/codegen-arm.h
+++ b/src/arm/codegen-arm.h
@@ -544,6 +544,8 @@
void GenerateMathCos(ZoneList<Expression*>* args);
void GenerateMathSqrt(ZoneList<Expression*>* args);
+ void GenerateIsRegExpEquivalent(ZoneList<Expression*>* args);
+
// Simple condition analysis.
enum ConditionAnalysis {
ALWAYS_TRUE,
diff --git a/src/arm/debug-arm.cc b/src/arm/debug-arm.cc
index 65f5eea..e87d265 100644
--- a/src/arm/debug-arm.cc
+++ b/src/arm/debug-arm.cc
@@ -296,9 +296,10 @@
#undef __
-void Debug::SetUpFrameDropperFrame(StackFrame* bottom_js_frame,
- Handle<Code> code) {
+Object** Debug::SetUpFrameDropperFrame(StackFrame* bottom_js_frame,
+ Handle<Code> code) {
UNREACHABLE();
+ return NULL;
}
const int Debug::kFrameDropperFrameSize = -1;
diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc
index 7d90ed9..ea5a8f2 100644
--- a/src/arm/full-codegen-arm.cc
+++ b/src/arm/full-codegen-arm.cc
@@ -224,7 +224,7 @@
// Here we use masm_-> instead of the __ macro to avoid the code coverage
// tool from instrumenting as we rely on the code size here.
int32_t sp_delta = (scope()->num_parameters() + 1) * kPointerSize;
- CodeGenerator::RecordPositions(masm_, function()->end_position());
+ CodeGenerator::RecordPositions(masm_, function()->end_position() - 1);
__ RecordJSReturn();
masm_->mov(sp, fp);
masm_->ldm(ia_w, sp, fp.bit() | lr.bit());
@@ -1104,13 +1104,13 @@
void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
Comment cmnt(masm_, "[ RegExpLiteral");
- Label done;
+ Label materialized;
// Registers will be used as follows:
// r4 = JS function, literals array
// r3 = literal index
// r2 = RegExp pattern
// r1 = RegExp flags
- // r0 = temp + return value (RegExp literal)
+ // r0 = temp + materialized value (RegExp literal)
__ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
__ ldr(r4, FieldMemOperand(r0, JSFunction::kLiteralsOffset));
int literal_offset =
@@ -1118,13 +1118,24 @@
__ ldr(r0, FieldMemOperand(r4, literal_offset));
__ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
__ cmp(r0, ip);
- __ b(ne, &done);
+ __ b(ne, &materialized);
__ mov(r3, Operand(Smi::FromInt(expr->literal_index())));
__ mov(r2, Operand(expr->pattern()));
__ mov(r1, Operand(expr->flags()));
__ Push(r4, r3, r2, r1);
__ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
- __ bind(&done);
+ __ bind(&materialized);
+ int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
+ __ push(r0);
+ __ mov(r0, Operand(Smi::FromInt(size)));
+ __ push(r0);
+ __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
+ // After this, registers are used as follows:
+ // r0: Newly allocated regexp.
+ // r1: Materialized regexp
+ // r2: temp.
+ __ pop(r1);
+ __ CopyFields(r0, r1, r2.bit(), size / kPointerSize);
Apply(context_, r0);
}
@@ -2566,6 +2577,47 @@
}
+void FullCodeGenerator::EmitIsRegExpEquivalent(ZoneList<Expression*>* args) {
+ ASSERT_EQ(2, args->length());
+
+ Register right = r0;
+ Register left = r1;
+ Register tmp = r2;
+ Register tmp2 = r3;
+
+ VisitForValue(args->at(0), kStack);
+ VisitForValue(args->at(1), kAccumulator);
+ __ pop(left);
+
+ Label done, fail, ok;
+ __ cmp(left, Operand(right));
+ __ b(eq, &ok);
+ // Fail if either is a non-HeapObject.
+ __ and_(tmp, left, Operand(right));
+ __ tst(tmp, Operand(kSmiTagMask));
+ __ b(eq, &fail);
+ __ ldr(tmp, FieldMemOperand(left, HeapObject::kMapOffset));
+ __ ldrb(tmp2, FieldMemOperand(tmp, Map::kInstanceTypeOffset));
+ __ cmp(tmp2, Operand(JS_REGEXP_TYPE));
+ __ b(ne, &fail);
+ __ ldr(tmp2, FieldMemOperand(right, HeapObject::kMapOffset));
+ __ cmp(tmp, Operand(tmp2));
+ __ b(ne, &fail);
+ __ ldr(tmp, FieldMemOperand(left, JSRegExp::kDataOffset));
+ __ ldr(tmp2, FieldMemOperand(right, JSRegExp::kDataOffset));
+ __ cmp(tmp, tmp2);
+ __ b(eq, &ok);
+ __ bind(&fail);
+ __ LoadRoot(r0, Heap::kFalseValueRootIndex);
+ __ jmp(&done);
+ __ bind(&ok);
+ __ LoadRoot(r0, Heap::kTrueValueRootIndex);
+ __ bind(&done);
+
+ Apply(context_, r0);
+}
+
+
void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
Handle<String> name = expr->name();
if (name->length() > 0 && name->Get(0) == '_') {
diff --git a/src/arm/ic-arm.cc b/src/arm/ic-arm.cc
index e7e3de3..1fd7098 100644
--- a/src/arm/ic-arm.cc
+++ b/src/arm/ic-arm.cc
@@ -1105,7 +1105,7 @@
// -- r0 : key
// -- r1 : receiver
// -----------------------------------
- Label slow, check_string, index_smi, index_string;
+ Label slow, check_string, index_smi, index_string, property_array_property;
Label check_pixel_array, probe_dictionary, check_number_dictionary;
Register key = r0;
@@ -1193,7 +1193,7 @@
__ cmp(r0, r5);
__ b(ne, &slow);
- // Get field offset and check that it is an in-object property.
+ // Get field offset.
// r0 : key
// r1 : receiver
// r2 : receiver's map
@@ -1203,11 +1203,10 @@
__ mov(r4, Operand(cache_field_offsets));
__ ldr(r5, MemOperand(r4, r3, LSL, kPointerSizeLog2));
__ ldrb(r6, FieldMemOperand(r2, Map::kInObjectPropertiesOffset));
- __ cmp(r5, r6);
- __ b(ge, &slow);
+ __ sub(r5, r5, r6, SetCC);
+ __ b(ge, &property_array_property);
// Load in-object property.
- __ sub(r5, r5, r6); // Index from end of object.
__ ldrb(r6, FieldMemOperand(r2, Map::kInstanceSizeOffset));
__ add(r6, r6, r5); // Index from start of object.
__ sub(r1, r1, Operand(kHeapObjectTag)); // Remove the heap tag.
@@ -1215,6 +1214,14 @@
__ IncrementCounter(&Counters::keyed_load_generic_lookup_cache, 1, r2, r3);
__ Ret();
+ // Load property array property.
+ __ bind(&property_array_property);
+ __ ldr(r1, FieldMemOperand(r1, JSObject::kPropertiesOffset));
+ __ add(r1, r1, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
+ __ ldr(r0, MemOperand(r1, r5, LSL, kPointerSizeLog2));
+ __ IncrementCounter(&Counters::keyed_load_generic_lookup_cache, 1, r2, r3);
+ __ Ret();
+
// Do a quick inline probe of the receiver's dictionary, if it
// exists.
__ bind(&probe_dictionary);
diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc
index ad22cd9..9c25ccd 100644
--- a/src/arm/macro-assembler-arm.cc
+++ b/src/arm/macro-assembler-arm.cc
@@ -1728,6 +1728,34 @@
}
+// Copies a fixed number of fields of heap objects from src to dst.
+void MacroAssembler::CopyFields(Register dst,
+ Register src,
+ RegList temps,
+ int field_count) {
+ // At least one bit set in the first 15 registers.
+ ASSERT((temps & ((1 << 15) - 1)) != 0);
+ ASSERT((temps & dst.bit()) == 0);
+ ASSERT((temps & src.bit()) == 0);
+ // Primitive implementation using only one temporary register.
+
+ Register tmp = no_reg;
+ // Find a temp register in temps list.
+ for (int i = 0; i < 15; i++) {
+ if ((temps & (1 << i)) != 0) {
+ tmp.set_code(i);
+ break;
+ }
+ }
+ ASSERT(!tmp.is(no_reg));
+
+ for (int i = 0; i < field_count; i++) {
+ ldr(tmp, FieldMemOperand(src, i * kPointerSize));
+ str(tmp, FieldMemOperand(dst, i * kPointerSize));
+ }
+}
+
+
void MacroAssembler::CountLeadingZeros(Register zeros, // Answer.
Register source, // Input.
Register scratch) {
diff --git a/src/arm/macro-assembler-arm.h b/src/arm/macro-assembler-arm.h
index 9949fac..37a1b1c 100644
--- a/src/arm/macro-assembler-arm.h
+++ b/src/arm/macro-assembler-arm.h
@@ -393,6 +393,8 @@
Register heap_number_map,
Label* gc_required);
+ // Copies a fixed number of fields of heap objects from src to dst.
+ void CopyFields(Register dst, Register src, RegList temps, int field_count);
// ---------------------------------------------------------------------------
// Support functions.
diff --git a/src/arm/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc
index ff3007c..8c8e702 100644
--- a/src/arm/stub-cache-arm.cc
+++ b/src/arm/stub-cache-arm.cc
@@ -1252,9 +1252,11 @@
}
-void CallStubCompiler::GenerateMissBranch() {
- Handle<Code> ic = ComputeCallMiss(arguments().immediate(), kind_);
- __ Jump(ic, RelocInfo::CODE_TARGET);
+Object* CallStubCompiler::GenerateMissBranch() {
+ Object* obj = StubCache::ComputeCallMiss(arguments().immediate(), kind_);
+ if (obj->IsFailure()) return obj;
+ __ Jump(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET);
+ return obj;
}
@@ -1286,7 +1288,8 @@
// Handle call cache miss.
__ bind(&miss);
- GenerateMissBranch();
+ Object* obj = GenerateMissBranch();
+ if (obj->IsFailure()) return obj;
// Return the generated code.
return GetCode(FIELD, name);
@@ -1337,7 +1340,8 @@
// Handle call cache miss.
__ bind(&miss);
- GenerateMissBranch();
+ Object* obj = GenerateMissBranch();
+ if (obj->IsFailure()) return obj;
// Return the generated code.
return GetCode(function);
@@ -1388,7 +1392,8 @@
// Handle call cache miss.
__ bind(&miss);
- GenerateMissBranch();
+ Object* obj = GenerateMissBranch();
+ if (obj->IsFailure()) return obj;
// Return the generated code.
return GetCode(function);
@@ -1561,7 +1566,8 @@
}
__ bind(&miss_in_smi_check);
- GenerateMissBranch();
+ Object* obj = GenerateMissBranch();
+ if (obj->IsFailure()) return obj;
// Return the generated code.
return GetCode(function);
@@ -1610,7 +1616,8 @@
// Handle call cache miss.
__ bind(&miss);
- GenerateMissBranch();
+ Object* obj = GenerateMissBranch();
+ if (obj->IsFailure()) return obj;
// Return the generated code.
return GetCode(INTERCEPTOR, name);
@@ -1694,7 +1701,8 @@
// Handle call cache miss.
__ bind(&miss);
__ IncrementCounter(&Counters::call_global_inline_miss, 1, r1, r3);
- GenerateMissBranch();
+ Object* obj = GenerateMissBranch();
+ if (obj->IsFailure()) return obj;
// Return the generated code.
return GetCode(NORMAL, name);
diff --git a/src/arm/virtual-frame-arm.cc b/src/arm/virtual-frame-arm.cc
index 2ddfd0f..da76edf 100644
--- a/src/arm/virtual-frame-arm.cc
+++ b/src/arm/virtual-frame-arm.cc
@@ -562,9 +562,10 @@
case R1_R0_TOS:
MergeTOSTo(R1_R0_TOS);
return r0;
+ default:
+ UNREACHABLE();
+ return no_reg;
}
- UNREACHABLE();
- return no_reg;
}
diff --git a/src/arm/virtual-frame-arm.h b/src/arm/virtual-frame-arm.h
index 8eedf22..82b4d08 100644
--- a/src/arm/virtual-frame-arm.h
+++ b/src/arm/virtual-frame-arm.h
@@ -501,7 +501,7 @@
}
inline void RaiseHeight(int count, unsigned known_smi_map = 0) {
- ASSERT(known_smi_map < (1u << count));
+ ASSERT(count >= 32 || known_smi_map < (1u << count));
element_count_ += count;
if (count >= kTOSKnownSmiMapSize) {
tos_known_smi_map_ = known_smi_map;