| Index: src/arm/lithium-codegen-arm.cc
|
| ===================================================================
|
| --- src/arm/lithium-codegen-arm.cc (revision 6170)
|
| +++ src/arm/lithium-codegen-arm.cc (working copy)
|
| @@ -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 {
|
|
|