Update V8 to r6190 as required by WebKit r75315
Change-Id: I0b2f598e4d8748df417ad350fc47a1c465ad1fef
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
index dfc4891..bb2461c 100644
--- a/src/arm/lithium-codegen-arm.cc
+++ b/src/arm/lithium-codegen-arm.cc
@@ -598,7 +598,7 @@
DoubleRegister dbl_scratch = d0;
LUnallocated marker_operand(LUnallocated::NONE);
- Register core_scratch = r9;
+ Register core_scratch = scratch0();
bool destroys_core_scratch = false;
LGapResolver resolver(move->move_operands(), &marker_operand);
@@ -730,7 +730,53 @@
void LCodeGen::DoCallStub(LCallStub* instr) {
- Abort("DoCallStub unimplemented.");
+ ASSERT(ToRegister(instr->result()).is(r0));
+ switch (instr->hydrogen()->major_key()) {
+ case CodeStub::RegExpConstructResult: {
+ RegExpConstructResultStub stub;
+ CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+ break;
+ }
+ case CodeStub::RegExpExec: {
+ RegExpExecStub stub;
+ CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+ break;
+ }
+ case CodeStub::SubString: {
+ SubStringStub stub;
+ CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+ break;
+ }
+ case CodeStub::StringCharAt: {
+ Abort("StringCharAtStub unimplemented.");
+ break;
+ }
+ case CodeStub::MathPow: {
+ Abort("MathPowStub unimplemented.");
+ break;
+ }
+ case CodeStub::NumberToString: {
+ NumberToStringStub stub;
+ CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+ break;
+ }
+ case CodeStub::StringAdd: {
+ StringAddStub stub(NO_STRING_ADD_FLAGS);
+ CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+ break;
+ }
+ case CodeStub::StringCompare: {
+ StringCompareStub stub;
+ CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+ break;
+ }
+ case CodeStub::TranscendentalCache: {
+ Abort("TranscendentalCache unimplemented.");
+ break;
+ }
+ default:
+ UNREACHABLE();
+ }
}
@@ -750,8 +796,8 @@
void LCodeGen::DoMulI(LMulI* instr) {
+ Register scratch = scratch0();
Register left = ToRegister(instr->left());
- Register scratch = r9;
Register right = EmitLoadRegister(instr->right(), scratch);
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero) &&
@@ -813,6 +859,7 @@
void LCodeGen::DoShiftI(LShiftI* instr) {
+ Register scratch = scratch0();
LOperand* left = instr->left();
LOperand* right = instr->right();
ASSERT(left->Equals(instr->result()));
@@ -820,21 +867,21 @@
Register result = ToRegister(left);
if (right->IsRegister()) {
// Mask the right operand.
- __ and_(r9, ToRegister(right), Operand(0x1F));
+ __ and_(scratch, ToRegister(right), Operand(0x1F));
switch (instr->op()) {
case Token::SAR:
- __ mov(result, Operand(result, ASR, r9));
+ __ mov(result, Operand(result, ASR, scratch));
break;
case Token::SHR:
if (instr->can_deopt()) {
- __ mov(result, Operand(result, LSR, r9), SetCC);
+ __ mov(result, Operand(result, LSR, scratch), SetCC);
DeoptimizeIf(mi, instr->environment());
} else {
- __ mov(result, Operand(result, LSR, r9));
+ __ mov(result, Operand(result, LSR, scratch));
}
break;
case Token::SHL:
- __ mov(result, Operand(result, LSL, r9));
+ __ mov(result, Operand(result, LSL, scratch));
break;
default:
UNREACHABLE();
@@ -898,24 +945,18 @@
}
-void LCodeGen::DoArrayLength(LArrayLength* instr) {
+void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) {
Register result = ToRegister(instr->result());
+ Register array = ToRegister(instr->input());
+ __ ldr(result, FieldMemOperand(array, JSArray::kLengthOffset));
+}
- if (instr->hydrogen()->value()->IsLoadElements()) {
- // We load the length directly from the elements array.
- Register elements = ToRegister(instr->input());
- __ ldr(result, FieldMemOperand(elements, FixedArray::kLengthOffset));
- } else {
- // Check that the receiver really is an array.
- Register array = ToRegister(instr->input());
- Register temporary = ToRegister(instr->temporary());
- __ CompareObjectType(array, temporary, temporary, JS_ARRAY_TYPE);
- DeoptimizeIf(ne, instr->environment());
- // Load length directly from the array.
- __ ldr(result, FieldMemOperand(array, JSArray::kLengthOffset));
- }
- Abort("DoArrayLength untested.");
+void LCodeGen::DoFixedArrayLength(LFixedArrayLength* instr) {
+ Register result = ToRegister(instr->result());
+ Register array = ToRegister(instr->input());
+ __ ldr(result, FieldMemOperand(array, FixedArray::kLengthOffset));
+ Abort("DoFixedArrayLength untested.");
}
@@ -1065,11 +1106,10 @@
// Test for double values. Zero is false.
Label call_stub;
DoubleRegister dbl_scratch = d0;
- Register core_scratch = r9;
- ASSERT(!reg.is(core_scratch));
- __ ldr(core_scratch, FieldMemOperand(reg, HeapObject::kMapOffset));
+ Register scratch = scratch0();
+ __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset));
__ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
- __ cmp(core_scratch, Operand(ip));
+ __ cmp(scratch, Operand(ip));
__ b(ne, &call_stub);
__ sub(ip, reg, Operand(kHeapObjectTag));
__ vldr(dbl_scratch, ip, HeapNumber::kValueOffset);
@@ -1176,11 +1216,41 @@
void LCodeGen::DoIsNull(LIsNull* instr) {
- Abort("DoIsNull unimplemented.");
+ Register reg = ToRegister(instr->input());
+ Register result = ToRegister(instr->result());
+
+ __ LoadRoot(ip, Heap::kNullValueRootIndex);
+ __ cmp(reg, ip);
+ if (instr->is_strict()) {
+ __ LoadRoot(result, Heap::kTrueValueRootIndex, eq);
+ __ LoadRoot(result, Heap::kFalseValueRootIndex, ne);
+ } else {
+ Label true_value, false_value, done;
+ __ b(eq, &true_value);
+ __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
+ __ cmp(ip, reg);
+ __ b(eq, &true_value);
+ __ tst(reg, Operand(kSmiTagMask));
+ __ b(eq, &false_value);
+ // Check for undetectable objects by looking in the bit field in
+ // the map. The object has already been smi checked.
+ Register scratch = result;
+ __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset));
+ __ ldrb(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset));
+ __ tst(scratch, Operand(1 << Map::kIsUndetectable));
+ __ b(ne, &true_value);
+ __ bind(&false_value);
+ __ LoadRoot(result, Heap::kFalseValueRootIndex);
+ __ jmp(&done);
+ __ bind(&true_value);
+ __ LoadRoot(result, Heap::kTrueValueRootIndex);
+ __ bind(&done);
+ }
}
void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) {
+ Register scratch = scratch0();
Register reg = ToRegister(instr->input());
// TODO(fsc): If the expression is known to be a smi, then it's
@@ -1204,7 +1274,6 @@
__ b(eq, false_label);
// Check for undetectable objects by looking in the bit field in
// the map. The object has already been smi checked.
- Register scratch = ToRegister(instr->temp());
__ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset));
__ ldrb(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset));
__ tst(scratch, Operand(1 << Map::kIsUndetectable));
@@ -1282,8 +1351,8 @@
void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) {
+ Register scratch = scratch0();
Register input = ToRegister(instr->input());
- Register temp = ToRegister(instr->temp());
int true_block = chunk_->LookupDestination(instr->true_block_id());
int false_block = chunk_->LookupDestination(instr->false_block_id());
@@ -1293,7 +1362,7 @@
__ tst(input, Operand(kSmiTagMask));
__ b(eq, false_label);
- __ CompareObjectType(input, temp, temp, instr->TestType());
+ __ CompareObjectType(input, scratch, scratch, instr->TestType());
EmitBranch(true_block, false_block, instr->BranchCondition());
}
@@ -1332,19 +1401,28 @@
void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) {
- Abort("DoCmpMapAndBranch unimplemented.");
+ Register reg = ToRegister(instr->input());
+ Register temp = ToRegister(instr->temp());
+ int true_block = instr->true_block_id();
+ int false_block = instr->false_block_id();
+
+ __ ldr(temp, FieldMemOperand(reg, HeapObject::kMapOffset));
+ __ cmp(temp, Operand(instr->map()));
+ EmitBranch(true_block, false_block, eq);
}
void LCodeGen::DoInstanceOf(LInstanceOf* instr) {
- // We expect object and function in registers r1 and r0.
+ ASSERT(ToRegister(instr->left()).is(r0)); // Object is in r0.
+ ASSERT(ToRegister(instr->right()).is(r1)); // Function is in r1.
+
InstanceofStub stub(InstanceofStub::kArgsInRegisters);
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
Label true_value, done;
__ tst(r0, r0);
- __ mov(r0, Operand(Factory::false_value()), LeaveCC, eq);
- __ mov(r0, Operand(Factory::true_value()), LeaveCC, ne);
+ __ mov(r0, Operand(Factory::false_value()), LeaveCC, ne);
+ __ mov(r0, Operand(Factory::true_value()), LeaveCC, eq);
}
@@ -1432,7 +1510,14 @@
void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
- Abort("DoLoadNamedField unimplemented.");
+ Register object = ToRegister(instr->input());
+ Register result = ToRegister(instr->result());
+ if (instr->hydrogen()->is_in_object()) {
+ __ ldr(result, FieldMemOperand(object, instr->hydrogen()->offset()));
+ } else {
+ __ ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset));
+ __ ldr(result, FieldMemOperand(result, instr->hydrogen()->offset()));
+ }
}
@@ -1447,6 +1532,50 @@
}
+void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) {
+ Register scratch = scratch0();
+ Register function = ToRegister(instr->function());
+ Register result = ToRegister(instr->result());
+
+ // Check that the function really is a function. Load map into the
+ // result register.
+ __ CompareObjectType(function, result, scratch, JS_FUNCTION_TYPE);
+ DeoptimizeIf(ne, instr->environment());
+
+ // Make sure that the function has an instance prototype.
+ Label non_instance;
+ __ ldrb(scratch, FieldMemOperand(result, Map::kBitFieldOffset));
+ __ tst(scratch, Operand(1 << Map::kHasNonInstancePrototype));
+ __ b(ne, &non_instance);
+
+ // Get the prototype or initial map from the function.
+ __ ldr(result,
+ FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
+
+ // Check that the function has a prototype or an initial map.
+ __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
+ __ cmp(result, ip);
+ DeoptimizeIf(eq, instr->environment());
+
+ // If the function does not have an initial map, we're done.
+ Label done;
+ __ CompareObjectType(result, scratch, scratch, MAP_TYPE);
+ __ b(ne, &done);
+
+ // Get the prototype from the initial map.
+ __ ldr(result, FieldMemOperand(result, Map::kPrototypeOffset));
+ __ jmp(&done);
+
+ // Non-instance prototype: Fetch prototype from constructor field
+ // in initial map.
+ __ bind(&non_instance);
+ __ ldr(result, FieldMemOperand(result, Map::kConstructorOffset));
+
+ // All done.
+ __ bind(&done);
+}
+
+
void LCodeGen::DoLoadElements(LLoadElements* instr) {
Abort("DoLoadElements unimplemented.");
}
@@ -1544,7 +1673,9 @@
void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) {
- Abort("DoCallConstantFunction unimplemented.");
+ ASSERT(ToRegister(instr->result()).is(r0));
+ __ mov(r1, Operand(instr->function()));
+ CallKnownFunction(instr->function(), instr->arity(), instr);
}
@@ -1604,7 +1735,13 @@
void LCodeGen::DoCallFunction(LCallFunction* instr) {
- Abort("DoCallFunction unimplemented.");
+ ASSERT(ToRegister(instr->result()).is(r0));
+
+ int arity = instr->arity();
+ CallFunctionStub stub(arity, NOT_IN_LOOP, RECEIVER_MIGHT_BE_VALUE);
+ CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+ __ Drop(1);
+ __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
}
@@ -1652,7 +1789,8 @@
void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
- Abort("DoBoundsCheck unimplemented.");
+ __ cmp(ToRegister(instr->index()), ToOperand(instr->length()));
+ DeoptimizeIf(hs, instr->environment());
}
@@ -1757,10 +1895,10 @@
};
DoubleRegister input_reg = ToDoubleRegister(instr->input());
+ Register scratch = scratch0();
Register reg = ToRegister(instr->result());
Register temp1 = ToRegister(instr->temp1());
Register temp2 = ToRegister(instr->temp2());
- Register scratch = r9;
DeferredNumberTagD* deferred = new DeferredNumberTagD(this, instr);
if (FLAG_inline_new) {
@@ -1808,8 +1946,7 @@
void LCodeGen::EmitNumberUntagD(Register input_reg,
DoubleRegister result_reg,
LEnvironment* env) {
- Register core_scratch = r9;
- ASSERT(!input_reg.is(core_scratch));
+ Register scratch = scratch0();
SwVfpRegister flt_scratch = s0;
ASSERT(!result_reg.is(d0));
@@ -1820,9 +1957,9 @@
__ b(eq, &load_smi);
// Heap number map check.
- __ ldr(core_scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
+ __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
__ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
- __ cmp(core_scratch, Operand(ip));
+ __ cmp(scratch, Operand(ip));
__ b(eq, &heap_number);
__ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
@@ -1864,16 +2001,15 @@
void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
Label done;
Register input_reg = ToRegister(instr->input());
- Register core_scratch = r9;
- ASSERT(!input_reg.is(core_scratch));
+ Register scratch = scratch0();
DoubleRegister dbl_scratch = d0;
SwVfpRegister flt_scratch = s0;
DoubleRegister dbl_tmp = ToDoubleRegister(instr->temp());
// Heap number map check.
- __ ldr(core_scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
+ __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
__ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
- __ cmp(core_scratch, Operand(ip));
+ __ cmp(scratch, Operand(ip));
if (instr->truncating()) {
Label heap_number;
@@ -1985,33 +2121,99 @@
void LCodeGen::DoCheckMap(LCheckMap* instr) {
+ Register scratch = scratch0();
LOperand* input = instr->input();
ASSERT(input->IsRegister());
Register reg = ToRegister(input);
- __ ldr(r9, FieldMemOperand(reg, HeapObject::kMapOffset));
- __ cmp(r9, Operand(instr->hydrogen()->map()));
+ __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset));
+ __ cmp(scratch, Operand(instr->hydrogen()->map()));
DeoptimizeIf(ne, instr->environment());
}
void LCodeGen::LoadPrototype(Register result,
Handle<JSObject> prototype) {
- Abort("LoadPrototype unimplemented.");
+ if (Heap::InNewSpace(*prototype)) {
+ Handle<JSGlobalPropertyCell> cell =
+ Factory::NewJSGlobalPropertyCell(prototype);
+ __ mov(result, Operand(cell));
+ } else {
+ __ mov(result, Operand(prototype));
+ }
}
void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) {
- Abort("DoCheckPrototypeMaps unimplemented.");
+ Register temp1 = ToRegister(instr->temp1());
+ Register temp2 = ToRegister(instr->temp2());
+
+ Handle<JSObject> holder = instr->holder();
+ Handle<Map> receiver_map = instr->receiver_map();
+ Handle<JSObject> current_prototype(JSObject::cast(receiver_map->prototype()));
+
+ // Load prototype object.
+ LoadPrototype(temp1, current_prototype);
+
+ // Check prototype maps up to the holder.
+ while (!current_prototype.is_identical_to(holder)) {
+ __ ldr(temp2, FieldMemOperand(temp1, HeapObject::kMapOffset));
+ __ cmp(temp2, Operand(Handle<Map>(current_prototype->map())));
+ DeoptimizeIf(ne, instr->environment());
+ current_prototype =
+ Handle<JSObject>(JSObject::cast(current_prototype->GetPrototype()));
+ // Load next prototype object.
+ LoadPrototype(temp1, current_prototype);
+ }
+
+ // Check the holder map.
+ __ ldr(temp2, FieldMemOperand(temp1, HeapObject::kMapOffset));
+ __ cmp(temp2, Operand(Handle<Map>(current_prototype->map())));
+ DeoptimizeIf(ne, instr->environment());
}
void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) {
- Abort("DoArrayLiteral unimplemented.");
+ __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
+ __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset));
+ __ mov(r2, Operand(Smi::FromInt(instr->hydrogen()->literal_index())));
+ __ mov(r1, Operand(instr->hydrogen()->constant_elements()));
+ __ Push(r3, r2, r1);
+
+ // Pick the right runtime function or stub to call.
+ int length = instr->hydrogen()->length();
+ if (instr->hydrogen()->IsCopyOnWrite()) {
+ ASSERT(instr->hydrogen()->depth() == 1);
+ FastCloneShallowArrayStub::Mode mode =
+ FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS;
+ FastCloneShallowArrayStub stub(mode, length);
+ CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+ } else if (instr->hydrogen()->depth() > 1) {
+ CallRuntime(Runtime::kCreateArrayLiteral, 3, instr);
+ } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) {
+ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3, instr);
+ } else {
+ FastCloneShallowArrayStub::Mode mode =
+ FastCloneShallowArrayStub::CLONE_ELEMENTS;
+ FastCloneShallowArrayStub stub(mode, length);
+ CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+ }
}
void LCodeGen::DoObjectLiteral(LObjectLiteral* instr) {
- Abort("DoObjectLiteral unimplemented.");
+ __ ldr(r4, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
+ __ ldr(r4, FieldMemOperand(r4, JSFunction::kLiteralsOffset));
+ __ mov(r3, Operand(Smi::FromInt(instr->hydrogen()->literal_index())));
+ __ mov(r2, Operand(instr->hydrogen()->constant_properties()));
+ __ mov(r1, Operand(Smi::FromInt(instr->hydrogen()->fast_elements() ? 1 : 0)));
+ __ Push(r4, r3, r2, r1);
+
+ // Pick the right runtime function to call.
+ if (instr->hydrogen()->depth() > 1) {
+ CallRuntime(Runtime::kCreateObjectLiteral, 4, instr);
+ } else {
+ CallRuntime(Runtime::kCreateObjectLiteralShallow, 4, instr);
+ }
}
@@ -2056,8 +2258,7 @@
Register input,
Handle<String> type_name) {
Condition final_branch_condition = no_condition;
- Register core_scratch = r9;
- ASSERT(!input.is(core_scratch));
+ Register scratch = scratch0();
if (type_name->Equals(Heap::number_symbol())) {
__ tst(input, Operand(kSmiTagMask));
__ b(eq, true_label);
@@ -2073,7 +2274,7 @@
__ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset));
__ tst(ip, Operand(1 << Map::kIsUndetectable));
__ b(ne, false_label);
- __ CompareInstanceType(input, core_scratch, FIRST_NONSTRING_TYPE);
+ __ CompareInstanceType(input, scratch, FIRST_NONSTRING_TYPE);
final_branch_condition = lo;
} else if (type_name->Equals(Heap::boolean_symbol())) {
@@ -2099,10 +2300,10 @@
} else if (type_name->Equals(Heap::function_symbol())) {
__ tst(input, Operand(kSmiTagMask));
__ b(eq, false_label);
- __ CompareObjectType(input, input, core_scratch, JS_FUNCTION_TYPE);
+ __ CompareObjectType(input, input, scratch, JS_FUNCTION_TYPE);
__ b(eq, true_label);
// Regular expressions => 'function' (they are callable).
- __ CompareInstanceType(input, core_scratch, JS_REGEXP_TYPE);
+ __ CompareInstanceType(input, scratch, JS_REGEXP_TYPE);
final_branch_condition = eq;
} else if (type_name->Equals(Heap::object_symbol())) {
@@ -2112,16 +2313,16 @@
__ cmp(input, ip);
__ b(eq, true_label);
// Regular expressions => 'function', not 'object'.
- __ CompareObjectType(input, input, core_scratch, JS_REGEXP_TYPE);
+ __ CompareObjectType(input, input, scratch, JS_REGEXP_TYPE);
__ b(eq, false_label);
// Check for undetectable objects => false.
__ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset));
__ tst(ip, Operand(1 << Map::kIsUndetectable));
__ b(ne, false_label);
// Check for JS objects => true.
- __ CompareInstanceType(input, core_scratch, FIRST_JS_OBJECT_TYPE);
+ __ CompareInstanceType(input, scratch, FIRST_JS_OBJECT_TYPE);
__ b(lo, false_label);
- __ CompareInstanceType(input, core_scratch, LAST_JS_OBJECT_TYPE);
+ __ CompareInstanceType(input, scratch, LAST_JS_OBJECT_TYPE);
final_branch_condition = ls;
} else {