| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved.7 | 1 // Copyright 2012 the V8 project authors. All rights reserved.7 |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 77 GenerateDeferredCode() && | 77 GenerateDeferredCode() && |
| 78 GenerateDeoptJumpTable() && | 78 GenerateDeoptJumpTable() && |
| 79 GenerateSafepointTable(); | 79 GenerateSafepointTable(); |
| 80 } | 80 } |
| 81 | 81 |
| 82 | 82 |
| 83 void LCodeGen::FinishCode(Handle<Code> code) { | 83 void LCodeGen::FinishCode(Handle<Code> code) { |
| 84 ASSERT(is_done()); | 84 ASSERT(is_done()); |
| 85 code->set_stack_slots(GetStackSlotCount()); | 85 code->set_stack_slots(GetStackSlotCount()); |
| 86 code->set_safepoint_table_offset(safepoints_.GetCodeOffset()); | 86 code->set_safepoint_table_offset(safepoints_.GetCodeOffset()); |
| 87 RegisterDependentCodeForEmbeddedMaps(code); | 87 if (code->is_optimized_code()) RegisterWeakObjectsInOptimizedCode(code); |
| 88 PopulateDeoptimizationData(code); | 88 PopulateDeoptimizationData(code); |
| 89 info()->CommitDependencies(code); | 89 info()->CommitDependencies(code); |
| 90 } | 90 } |
| 91 | 91 |
| 92 | 92 |
| 93 void LChunkBuilder::Abort(BailoutReason reason) { | 93 void LChunkBuilder::Abort(BailoutReason reason) { |
| 94 info()->set_bailout_reason(reason); | 94 info()->set_bailout_reason(reason); |
| 95 status_ = ABORTED; | 95 status_ = ABORTED; |
| 96 } | 96 } |
| 97 | 97 |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 172 __ Prologue(info()->IsStub() ? BUILD_STUB_FRAME : BUILD_FUNCTION_FRAME); | 172 __ Prologue(info()->IsStub() ? BUILD_STUB_FRAME : BUILD_FUNCTION_FRAME); |
| 173 frame_is_built_ = true; | 173 frame_is_built_ = true; |
| 174 info_->AddNoFrameRange(0, masm_->pc_offset()); | 174 info_->AddNoFrameRange(0, masm_->pc_offset()); |
| 175 } | 175 } |
| 176 | 176 |
| 177 // Reserve space for the stack slots needed by the code. | 177 // Reserve space for the stack slots needed by the code. |
| 178 int slots = GetStackSlotCount(); | 178 int slots = GetStackSlotCount(); |
| 179 if (slots > 0) { | 179 if (slots > 0) { |
| 180 if (FLAG_debug_code) { | 180 if (FLAG_debug_code) { |
| 181 __ Subu(sp, sp, Operand(slots * kPointerSize)); | 181 __ Subu(sp, sp, Operand(slots * kPointerSize)); |
| 182 __ push(a0); | 182 __ Push(a0, a1); |
| 183 __ push(a1); | |
| 184 __ Addu(a0, sp, Operand(slots * kPointerSize)); | 183 __ Addu(a0, sp, Operand(slots * kPointerSize)); |
| 185 __ li(a1, Operand(kSlotsZapValue)); | 184 __ li(a1, Operand(kSlotsZapValue)); |
| 186 Label loop; | 185 Label loop; |
| 187 __ bind(&loop); | 186 __ bind(&loop); |
| 188 __ Subu(a0, a0, Operand(kPointerSize)); | 187 __ Subu(a0, a0, Operand(kPointerSize)); |
| 189 __ sw(a1, MemOperand(a0, 2 * kPointerSize)); | 188 __ sw(a1, MemOperand(a0, 2 * kPointerSize)); |
| 190 __ Branch(&loop, ne, a0, Operand(sp)); | 189 __ Branch(&loop, ne, a0, Operand(sp)); |
| 191 __ pop(a1); | 190 __ Pop(a0, a1); |
| 192 __ pop(a0); | |
| 193 } else { | 191 } else { |
| 194 __ Subu(sp, sp, Operand(slots * kPointerSize)); | 192 __ Subu(sp, sp, Operand(slots * kPointerSize)); |
| 195 } | 193 } |
| 196 } | 194 } |
| 197 | 195 |
| 198 if (info()->saves_caller_doubles()) { | 196 if (info()->saves_caller_doubles()) { |
| 199 SaveCallerDoubles(); | 197 SaveCallerDoubles(); |
| 200 } | 198 } |
| 201 | 199 |
| 202 // Possibly allocate a local context. | 200 // Possibly allocate a local context. |
| 203 int heap_slots = info()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; | 201 int heap_slots = info()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; |
| 204 if (heap_slots > 0) { | 202 if (heap_slots > 0) { |
| 205 Comment(";;; Allocate local context"); | 203 Comment(";;; Allocate local context"); |
| 206 // Argument to NewContext is the function, which is in a1. | 204 // Argument to NewContext is the function, which is in a1. |
| 207 __ push(a1); | |
| 208 if (heap_slots <= FastNewContextStub::kMaximumSlots) { | 205 if (heap_slots <= FastNewContextStub::kMaximumSlots) { |
| 209 FastNewContextStub stub(heap_slots); | 206 FastNewContextStub stub(heap_slots); |
| 210 __ CallStub(&stub); | 207 __ CallStub(&stub); |
| 211 } else { | 208 } else { |
| 209 __ push(a1); |
| 212 __ CallRuntime(Runtime::kNewFunctionContext, 1); | 210 __ CallRuntime(Runtime::kNewFunctionContext, 1); |
| 213 } | 211 } |
| 214 RecordSafepoint(Safepoint::kNoLazyDeopt); | 212 RecordSafepoint(Safepoint::kNoLazyDeopt); |
| 215 // Context is returned in both v0 and cp. It replaces the context | 213 // Context is returned in both v0. It replaces the context passed to us. |
| 216 // passed to us. It's saved in the stack and kept live in cp. | 214 // It's saved in the stack and kept live in cp. |
| 217 __ sw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 215 __ mov(cp, v0); |
| 216 __ sw(v0, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 218 // Copy any necessary parameters into the context. | 217 // Copy any necessary parameters into the context. |
| 219 int num_parameters = scope()->num_parameters(); | 218 int num_parameters = scope()->num_parameters(); |
| 220 for (int i = 0; i < num_parameters; i++) { | 219 for (int i = 0; i < num_parameters; i++) { |
| 221 Variable* var = scope()->parameter(i); | 220 Variable* var = scope()->parameter(i); |
| 222 if (var->IsContextSlot()) { | 221 if (var->IsContextSlot()) { |
| 223 int parameter_offset = StandardFrameConstants::kCallerSPOffset + | 222 int parameter_offset = StandardFrameConstants::kCallerSPOffset + |
| 224 (num_parameters - 1 - i) * kPointerSize; | 223 (num_parameters - 1 - i) * kPointerSize; |
| 225 // Load parameter from stack. | 224 // Load parameter from stack. |
| 226 __ lw(a0, MemOperand(fp, parameter_offset)); | 225 __ lw(a0, MemOperand(fp, parameter_offset)); |
| 227 // Store it in the context. | 226 // Store it in the context. |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 261 | 260 |
| 262 | 261 |
| 263 bool LCodeGen::GenerateDeferredCode() { | 262 bool LCodeGen::GenerateDeferredCode() { |
| 264 ASSERT(is_generating()); | 263 ASSERT(is_generating()); |
| 265 if (deferred_.length() > 0) { | 264 if (deferred_.length() > 0) { |
| 266 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { | 265 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { |
| 267 LDeferredCode* code = deferred_[i]; | 266 LDeferredCode* code = deferred_[i]; |
| 268 | 267 |
| 269 HValue* value = | 268 HValue* value = |
| 270 instructions_->at(code->instruction_index())->hydrogen_value(); | 269 instructions_->at(code->instruction_index())->hydrogen_value(); |
| 271 RecordAndWritePosition(value->position()); | 270 RecordAndWritePosition( |
| 271 chunk()->graph()->SourcePositionToScriptPosition(value->position())); |
| 272 | 272 |
| 273 Comment(";;; <@%d,#%d> " | 273 Comment(";;; <@%d,#%d> " |
| 274 "-------------------- Deferred %s --------------------", | 274 "-------------------- Deferred %s --------------------", |
| 275 code->instruction_index(), | 275 code->instruction_index(), |
| 276 code->instr()->hydrogen_value()->id(), | 276 code->instr()->hydrogen_value()->id(), |
| 277 code->instr()->Mnemonic()); | 277 code->instr()->Mnemonic()); |
| 278 __ bind(code->entry()); | 278 __ bind(code->entry()); |
| 279 if (NeedsDeferredFrame()) { | 279 if (NeedsDeferredFrame()) { |
| 280 Comment(";;; Build frame"); | 280 Comment(";;; Build frame"); |
| 281 ASSERT(!frame_is_built_); | 281 ASSERT(!frame_is_built_); |
| (...skipping 571 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 853 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { | 853 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { |
| 854 int length = deoptimizations_.length(); | 854 int length = deoptimizations_.length(); |
| 855 if (length == 0) return; | 855 if (length == 0) return; |
| 856 Handle<DeoptimizationInputData> data = | 856 Handle<DeoptimizationInputData> data = |
| 857 factory()->NewDeoptimizationInputData(length, TENURED); | 857 factory()->NewDeoptimizationInputData(length, TENURED); |
| 858 | 858 |
| 859 Handle<ByteArray> translations = | 859 Handle<ByteArray> translations = |
| 860 translations_.CreateByteArray(isolate()->factory()); | 860 translations_.CreateByteArray(isolate()->factory()); |
| 861 data->SetTranslationByteArray(*translations); | 861 data->SetTranslationByteArray(*translations); |
| 862 data->SetInlinedFunctionCount(Smi::FromInt(inlined_function_count_)); | 862 data->SetInlinedFunctionCount(Smi::FromInt(inlined_function_count_)); |
| 863 data->SetOptimizationId(Smi::FromInt(info_->optimization_id())); |
| 864 if (info_->IsOptimizing()) { |
| 865 // Reference to shared function info does not change between phases. |
| 866 AllowDeferredHandleDereference allow_handle_dereference; |
| 867 data->SetSharedFunctionInfo(*info_->shared_info()); |
| 868 } else { |
| 869 data->SetSharedFunctionInfo(Smi::FromInt(0)); |
| 870 } |
| 863 | 871 |
| 864 Handle<FixedArray> literals = | 872 Handle<FixedArray> literals = |
| 865 factory()->NewFixedArray(deoptimization_literals_.length(), TENURED); | 873 factory()->NewFixedArray(deoptimization_literals_.length(), TENURED); |
| 866 { AllowDeferredHandleDereference copy_handles; | 874 { AllowDeferredHandleDereference copy_handles; |
| 867 for (int i = 0; i < deoptimization_literals_.length(); i++) { | 875 for (int i = 0; i < deoptimization_literals_.length(); i++) { |
| 868 literals->set(i, *deoptimization_literals_[i]); | 876 literals->set(i, *deoptimization_literals_[i]); |
| 869 } | 877 } |
| 870 data->SetLiteralArray(*literals); | 878 data->SetLiteralArray(*literals); |
| 871 } | 879 } |
| 872 | 880 |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1023 | 1031 |
| 1024 void LCodeGen::DoParameter(LParameter* instr) { | 1032 void LCodeGen::DoParameter(LParameter* instr) { |
| 1025 // Nothing to do. | 1033 // Nothing to do. |
| 1026 } | 1034 } |
| 1027 | 1035 |
| 1028 | 1036 |
| 1029 void LCodeGen::DoCallStub(LCallStub* instr) { | 1037 void LCodeGen::DoCallStub(LCallStub* instr) { |
| 1030 ASSERT(ToRegister(instr->context()).is(cp)); | 1038 ASSERT(ToRegister(instr->context()).is(cp)); |
| 1031 ASSERT(ToRegister(instr->result()).is(v0)); | 1039 ASSERT(ToRegister(instr->result()).is(v0)); |
| 1032 switch (instr->hydrogen()->major_key()) { | 1040 switch (instr->hydrogen()->major_key()) { |
| 1033 case CodeStub::RegExpConstructResult: { | |
| 1034 RegExpConstructResultStub stub; | |
| 1035 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | |
| 1036 break; | |
| 1037 } | |
| 1038 case CodeStub::RegExpExec: { | 1041 case CodeStub::RegExpExec: { |
| 1039 RegExpExecStub stub; | 1042 RegExpExecStub stub; |
| 1040 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 1043 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 1041 break; | 1044 break; |
| 1042 } | 1045 } |
| 1043 case CodeStub::SubString: { | 1046 case CodeStub::SubString: { |
| 1044 SubStringStub stub; | 1047 SubStringStub stub; |
| 1045 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 1048 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 1046 break; | 1049 break; |
| 1047 } | 1050 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1058 | 1061 |
| 1059 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { | 1062 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { |
| 1060 GenerateOsrPrologue(); | 1063 GenerateOsrPrologue(); |
| 1061 } | 1064 } |
| 1062 | 1065 |
| 1063 | 1066 |
| 1064 void LCodeGen::DoModI(LModI* instr) { | 1067 void LCodeGen::DoModI(LModI* instr) { |
| 1065 HMod* hmod = instr->hydrogen(); | 1068 HMod* hmod = instr->hydrogen(); |
| 1066 HValue* left = hmod->left(); | 1069 HValue* left = hmod->left(); |
| 1067 HValue* right = hmod->right(); | 1070 HValue* right = hmod->right(); |
| 1068 if (hmod->HasPowerOf2Divisor()) { | 1071 if (hmod->RightIsPowerOf2()) { |
| 1069 const Register left_reg = ToRegister(instr->left()); | 1072 const Register left_reg = ToRegister(instr->left()); |
| 1070 const Register result_reg = ToRegister(instr->result()); | 1073 const Register result_reg = ToRegister(instr->result()); |
| 1071 | 1074 |
| 1072 // Note: The code below even works when right contains kMinInt. | 1075 // Note: The code below even works when right contains kMinInt. |
| 1073 int32_t divisor = Abs(right->GetInteger32Constant()); | 1076 int32_t divisor = Abs(right->GetInteger32Constant()); |
| 1074 | 1077 |
| 1075 Label left_is_not_negative, done; | 1078 Label left_is_not_negative, done; |
| 1076 if (left->CanBeNegative()) { | 1079 if (left->CanBeNegative()) { |
| 1077 __ Branch(left_reg.is(result_reg) ? PROTECT : USE_DELAY_SLOT, | 1080 __ Branch(left_reg.is(result_reg) ? PROTECT : USE_DELAY_SLOT, |
| 1078 &left_is_not_negative, ge, left_reg, Operand(zero_reg)); | 1081 &left_is_not_negative, ge, left_reg, Operand(zero_reg)); |
| (...skipping 569 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1648 } | 1651 } |
| 1649 | 1652 |
| 1650 | 1653 |
| 1651 void LCodeGen::DoMapEnumLength(LMapEnumLength* instr) { | 1654 void LCodeGen::DoMapEnumLength(LMapEnumLength* instr) { |
| 1652 Register result = ToRegister(instr->result()); | 1655 Register result = ToRegister(instr->result()); |
| 1653 Register map = ToRegister(instr->value()); | 1656 Register map = ToRegister(instr->value()); |
| 1654 __ EnumLength(result, map); | 1657 __ EnumLength(result, map); |
| 1655 } | 1658 } |
| 1656 | 1659 |
| 1657 | 1660 |
| 1658 void LCodeGen::DoElementsKind(LElementsKind* instr) { | |
| 1659 Register result = ToRegister(instr->result()); | |
| 1660 Register input = ToRegister(instr->value()); | |
| 1661 | |
| 1662 // Load map into |result|. | |
| 1663 __ lw(result, FieldMemOperand(input, HeapObject::kMapOffset)); | |
| 1664 // Load the map's "bit field 2" into |result|. We only need the first byte, | |
| 1665 // but the following bit field extraction takes care of that anyway. | |
| 1666 __ lbu(result, FieldMemOperand(result, Map::kBitField2Offset)); | |
| 1667 // Retrieve elements_kind from bit field 2. | |
| 1668 __ Ext(result, result, Map::kElementsKindShift, Map::kElementsKindBitCount); | |
| 1669 } | |
| 1670 | |
| 1671 | |
| 1672 void LCodeGen::DoValueOf(LValueOf* instr) { | |
| 1673 Register input = ToRegister(instr->value()); | |
| 1674 Register result = ToRegister(instr->result()); | |
| 1675 Register map = ToRegister(instr->temp()); | |
| 1676 Label done; | |
| 1677 | |
| 1678 if (!instr->hydrogen()->value()->IsHeapObject()) { | |
| 1679 // If the object is a smi return the object. | |
| 1680 __ Move(result, input); | |
| 1681 __ JumpIfSmi(input, &done); | |
| 1682 } | |
| 1683 | |
| 1684 // If the object is not a value type, return the object. | |
| 1685 __ GetObjectType(input, map, map); | |
| 1686 __ Branch(&done, ne, map, Operand(JS_VALUE_TYPE)); | |
| 1687 __ lw(result, FieldMemOperand(input, JSValue::kValueOffset)); | |
| 1688 | |
| 1689 __ bind(&done); | |
| 1690 } | |
| 1691 | |
| 1692 | |
| 1693 void LCodeGen::DoDateField(LDateField* instr) { | 1661 void LCodeGen::DoDateField(LDateField* instr) { |
| 1694 Register object = ToRegister(instr->date()); | 1662 Register object = ToRegister(instr->date()); |
| 1695 Register result = ToRegister(instr->result()); | 1663 Register result = ToRegister(instr->result()); |
| 1696 Register scratch = ToRegister(instr->temp()); | 1664 Register scratch = ToRegister(instr->temp()); |
| 1697 Smi* index = instr->index(); | 1665 Smi* index = instr->index(); |
| 1698 Label runtime, done; | 1666 Label runtime, done; |
| 1699 ASSERT(object.is(a0)); | 1667 ASSERT(object.is(a0)); |
| 1700 ASSERT(result.is(v0)); | 1668 ASSERT(result.is(v0)); |
| 1701 ASSERT(!scratch.is(scratch0())); | 1669 ASSERT(!scratch.is(scratch0())); |
| 1702 ASSERT(!scratch.is(object)); | 1670 ASSERT(!scratch.is(object)); |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1799 | 1767 |
| 1800 MemOperand operand = BuildSeqStringOperand(string, instr->index(), encoding); | 1768 MemOperand operand = BuildSeqStringOperand(string, instr->index(), encoding); |
| 1801 if (encoding == String::ONE_BYTE_ENCODING) { | 1769 if (encoding == String::ONE_BYTE_ENCODING) { |
| 1802 __ sb(value, operand); | 1770 __ sb(value, operand); |
| 1803 } else { | 1771 } else { |
| 1804 __ sh(value, operand); | 1772 __ sh(value, operand); |
| 1805 } | 1773 } |
| 1806 } | 1774 } |
| 1807 | 1775 |
| 1808 | 1776 |
| 1809 void LCodeGen::DoThrow(LThrow* instr) { | |
| 1810 __ push(ToRegister(instr->value())); | |
| 1811 ASSERT(ToRegister(instr->context()).is(cp)); | |
| 1812 CallRuntime(Runtime::kThrow, 1, instr); | |
| 1813 | |
| 1814 if (FLAG_debug_code) { | |
| 1815 __ stop("Unreachable code."); | |
| 1816 } | |
| 1817 } | |
| 1818 | |
| 1819 | |
| 1820 void LCodeGen::DoAddI(LAddI* instr) { | 1777 void LCodeGen::DoAddI(LAddI* instr) { |
| 1821 LOperand* left = instr->left(); | 1778 LOperand* left = instr->left(); |
| 1822 LOperand* right = instr->right(); | 1779 LOperand* right = instr->right(); |
| 1823 LOperand* result = instr->result(); | 1780 LOperand* result = instr->result(); |
| 1824 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); | 1781 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); |
| 1825 | 1782 |
| 1826 if (!can_overflow) { | 1783 if (!can_overflow) { |
| 1827 if (right->IsStackSlot() || right->IsArgument()) { | 1784 if (right->IsStackSlot() || right->IsArgument()) { |
| 1828 Register right_reg = EmitLoadRegister(right, at); | 1785 Register right_reg = EmitLoadRegister(right, at); |
| 1829 __ Addu(ToRegister(result), ToRegister(left), Operand(right_reg)); | 1786 __ Addu(ToRegister(result), ToRegister(left), Operand(right_reg)); |
| (...skipping 828 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2658 __ lw(map, FieldMemOperand(object, HeapObject::kMapOffset)); | 2615 __ lw(map, FieldMemOperand(object, HeapObject::kMapOffset)); |
| 2659 | 2616 |
| 2660 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_); | 2617 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_); |
| 2661 __ bind(deferred->map_check()); // Label for calculating code patching. | 2618 __ bind(deferred->map_check()); // Label for calculating code patching. |
| 2662 // We use Factory::the_hole_value() on purpose instead of loading from the | 2619 // We use Factory::the_hole_value() on purpose instead of loading from the |
| 2663 // root array to force relocation to be able to later patch with | 2620 // root array to force relocation to be able to later patch with |
| 2664 // the cached map. | 2621 // the cached map. |
| 2665 Handle<Cell> cell = factory()->NewCell(factory()->the_hole_value()); | 2622 Handle<Cell> cell = factory()->NewCell(factory()->the_hole_value()); |
| 2666 __ li(at, Operand(Handle<Object>(cell))); | 2623 __ li(at, Operand(Handle<Object>(cell))); |
| 2667 __ lw(at, FieldMemOperand(at, PropertyCell::kValueOffset)); | 2624 __ lw(at, FieldMemOperand(at, PropertyCell::kValueOffset)); |
| 2668 __ Branch(&cache_miss, ne, map, Operand(at)); | 2625 __ BranchShort(&cache_miss, ne, map, Operand(at)); |
| 2669 // We use Factory::the_hole_value() on purpose instead of loading from the | 2626 // We use Factory::the_hole_value() on purpose instead of loading from the |
| 2670 // root array to force relocation to be able to later patch | 2627 // root array to force relocation to be able to later patch |
| 2671 // with true or false. | 2628 // with true or false. The distance from map check has to be constant. |
| 2672 __ li(result, Operand(factory()->the_hole_value()), CONSTANT_SIZE); | 2629 __ li(result, Operand(factory()->the_hole_value()), CONSTANT_SIZE); |
| 2673 __ Branch(&done); | 2630 __ Branch(&done); |
| 2674 | 2631 |
| 2675 // The inlined call site cache did not match. Check null and string before | 2632 // The inlined call site cache did not match. Check null and string before |
| 2676 // calling the deferred code. | 2633 // calling the deferred code. |
| 2677 __ bind(&cache_miss); | 2634 __ bind(&cache_miss); |
| 2678 // Null is not instance of anything. | 2635 // Null is not instance of anything. |
| 2679 __ LoadRoot(temp, Heap::kNullValueRootIndex); | 2636 __ LoadRoot(temp, Heap::kNullValueRootIndex); |
| 2680 __ Branch(&false_result, eq, object, Operand(temp)); | 2637 __ Branch(&false_result, eq, object, Operand(temp)); |
| 2681 | 2638 |
| (...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2992 __ bind(&done); | 2949 __ bind(&done); |
| 2993 } | 2950 } |
| 2994 | 2951 |
| 2995 | 2952 |
| 2996 void LCodeGen::DoLoadRoot(LLoadRoot* instr) { | 2953 void LCodeGen::DoLoadRoot(LLoadRoot* instr) { |
| 2997 Register result = ToRegister(instr->result()); | 2954 Register result = ToRegister(instr->result()); |
| 2998 __ LoadRoot(result, instr->index()); | 2955 __ LoadRoot(result, instr->index()); |
| 2999 } | 2956 } |
| 3000 | 2957 |
| 3001 | 2958 |
| 3002 void LCodeGen::DoLoadExternalArrayPointer( | |
| 3003 LLoadExternalArrayPointer* instr) { | |
| 3004 Register to_reg = ToRegister(instr->result()); | |
| 3005 Register from_reg = ToRegister(instr->object()); | |
| 3006 __ lw(to_reg, FieldMemOperand(from_reg, | |
| 3007 ExternalArray::kExternalPointerOffset)); | |
| 3008 } | |
| 3009 | |
| 3010 | |
| 3011 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { | 2959 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { |
| 3012 Register arguments = ToRegister(instr->arguments()); | 2960 Register arguments = ToRegister(instr->arguments()); |
| 3013 Register result = ToRegister(instr->result()); | 2961 Register result = ToRegister(instr->result()); |
| 3014 // There are two words between the frame pointer and the last argument. | 2962 // There are two words between the frame pointer and the last argument. |
| 3015 // Subtracting from length accounts for one of them add one more. | 2963 // Subtracting from length accounts for one of them add one more. |
| 3016 if (instr->length()->IsConstantOperand()) { | 2964 if (instr->length()->IsConstantOperand()) { |
| 3017 int const_length = ToInteger32(LConstantOperand::cast(instr->length())); | 2965 int const_length = ToInteger32(LConstantOperand::cast(instr->length())); |
| 3018 if (instr->index()->IsConstantOperand()) { | 2966 if (instr->index()->IsConstantOperand()) { |
| 3019 int const_index = ToInteger32(LConstantOperand::cast(instr->index())); | 2967 int const_index = ToInteger32(LConstantOperand::cast(instr->index())); |
| 3020 int index = (const_length - const_index) + 1; | 2968 int index = (const_length - const_index) + 1; |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3067 } else { | 3015 } else { |
| 3068 key = ToRegister(instr->key()); | 3016 key = ToRegister(instr->key()); |
| 3069 } | 3017 } |
| 3070 int element_size_shift = ElementsKindToShiftSize(elements_kind); | 3018 int element_size_shift = ElementsKindToShiftSize(elements_kind); |
| 3071 int shift_size = (instr->hydrogen()->key()->representation().IsSmi()) | 3019 int shift_size = (instr->hydrogen()->key()->representation().IsSmi()) |
| 3072 ? (element_size_shift - kSmiTagSize) : element_size_shift; | 3020 ? (element_size_shift - kSmiTagSize) : element_size_shift; |
| 3073 int additional_offset = IsFixedTypedArrayElementsKind(elements_kind) | 3021 int additional_offset = IsFixedTypedArrayElementsKind(elements_kind) |
| 3074 ? FixedTypedArrayBase::kDataOffset - kHeapObjectTag | 3022 ? FixedTypedArrayBase::kDataOffset - kHeapObjectTag |
| 3075 : 0; | 3023 : 0; |
| 3076 | 3024 |
| 3077 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || | 3025 if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS || |
| 3078 elements_kind == FLOAT32_ELEMENTS || | 3026 elements_kind == FLOAT32_ELEMENTS || |
| 3079 elements_kind == EXTERNAL_DOUBLE_ELEMENTS || | 3027 elements_kind == EXTERNAL_FLOAT64_ELEMENTS || |
| 3080 elements_kind == FLOAT64_ELEMENTS) { | 3028 elements_kind == FLOAT64_ELEMENTS) { |
| 3081 int base_offset = | 3029 int base_offset = |
| 3082 (instr->additional_index() << element_size_shift) + additional_offset; | 3030 (instr->additional_index() << element_size_shift) + additional_offset; |
| 3083 FPURegister result = ToDoubleRegister(instr->result()); | 3031 FPURegister result = ToDoubleRegister(instr->result()); |
| 3084 if (key_is_constant) { | 3032 if (key_is_constant) { |
| 3085 __ Addu(scratch0(), external_pointer, constant_key << element_size_shift); | 3033 __ Addu(scratch0(), external_pointer, constant_key << element_size_shift); |
| 3086 } else { | 3034 } else { |
| 3087 __ sll(scratch0(), key, shift_size); | 3035 __ sll(scratch0(), key, shift_size); |
| 3088 __ Addu(scratch0(), scratch0(), external_pointer); | 3036 __ Addu(scratch0(), scratch0(), external_pointer); |
| 3089 } | 3037 } |
| 3090 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || | 3038 if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS || |
| 3091 elements_kind == FLOAT32_ELEMENTS) { | 3039 elements_kind == FLOAT32_ELEMENTS) { |
| 3092 __ lwc1(result, MemOperand(scratch0(), base_offset)); | 3040 __ lwc1(result, MemOperand(scratch0(), base_offset)); |
| 3093 __ cvt_d_s(result, result); | 3041 __ cvt_d_s(result, result); |
| 3094 } else { // loading doubles, not floats. | 3042 } else { // loading doubles, not floats. |
| 3095 __ ldc1(result, MemOperand(scratch0(), base_offset)); | 3043 __ ldc1(result, MemOperand(scratch0(), base_offset)); |
| 3096 } | 3044 } |
| 3097 } else { | 3045 } else { |
| 3098 Register result = ToRegister(instr->result()); | 3046 Register result = ToRegister(instr->result()); |
| 3099 MemOperand mem_operand = PrepareKeyedOperand( | 3047 MemOperand mem_operand = PrepareKeyedOperand( |
| 3100 key, external_pointer, key_is_constant, constant_key, | 3048 key, external_pointer, key_is_constant, constant_key, |
| 3101 element_size_shift, shift_size, | 3049 element_size_shift, shift_size, |
| 3102 instr->additional_index(), additional_offset); | 3050 instr->additional_index(), additional_offset); |
| 3103 switch (elements_kind) { | 3051 switch (elements_kind) { |
| 3104 case EXTERNAL_BYTE_ELEMENTS: | 3052 case EXTERNAL_INT8_ELEMENTS: |
| 3105 case INT8_ELEMENTS: | 3053 case INT8_ELEMENTS: |
| 3106 __ lb(result, mem_operand); | 3054 __ lb(result, mem_operand); |
| 3107 break; | 3055 break; |
| 3108 case EXTERNAL_PIXEL_ELEMENTS: | 3056 case EXTERNAL_UINT8_CLAMPED_ELEMENTS: |
| 3109 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 3057 case EXTERNAL_UINT8_ELEMENTS: |
| 3110 case UINT8_ELEMENTS: | 3058 case UINT8_ELEMENTS: |
| 3111 case UINT8_CLAMPED_ELEMENTS: | 3059 case UINT8_CLAMPED_ELEMENTS: |
| 3112 __ lbu(result, mem_operand); | 3060 __ lbu(result, mem_operand); |
| 3113 break; | 3061 break; |
| 3114 case EXTERNAL_SHORT_ELEMENTS: | 3062 case EXTERNAL_INT16_ELEMENTS: |
| 3115 case INT16_ELEMENTS: | 3063 case INT16_ELEMENTS: |
| 3116 __ lh(result, mem_operand); | 3064 __ lh(result, mem_operand); |
| 3117 break; | 3065 break; |
| 3118 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 3066 case EXTERNAL_UINT16_ELEMENTS: |
| 3119 case UINT16_ELEMENTS: | 3067 case UINT16_ELEMENTS: |
| 3120 __ lhu(result, mem_operand); | 3068 __ lhu(result, mem_operand); |
| 3121 break; | 3069 break; |
| 3122 case EXTERNAL_INT_ELEMENTS: | 3070 case EXTERNAL_INT32_ELEMENTS: |
| 3123 case INT32_ELEMENTS: | 3071 case INT32_ELEMENTS: |
| 3124 __ lw(result, mem_operand); | 3072 __ lw(result, mem_operand); |
| 3125 break; | 3073 break; |
| 3126 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 3074 case EXTERNAL_UINT32_ELEMENTS: |
| 3127 case UINT32_ELEMENTS: | 3075 case UINT32_ELEMENTS: |
| 3128 __ lw(result, mem_operand); | 3076 __ lw(result, mem_operand); |
| 3129 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { | 3077 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { |
| 3130 DeoptimizeIf(Ugreater_equal, instr->environment(), | 3078 DeoptimizeIf(Ugreater_equal, instr->environment(), |
| 3131 result, Operand(0x80000000)); | 3079 result, Operand(0x80000000)); |
| 3132 } | 3080 } |
| 3133 break; | 3081 break; |
| 3134 case FLOAT32_ELEMENTS: | 3082 case FLOAT32_ELEMENTS: |
| 3135 case FLOAT64_ELEMENTS: | 3083 case FLOAT64_ELEMENTS: |
| 3136 case EXTERNAL_FLOAT_ELEMENTS: | 3084 case EXTERNAL_FLOAT32_ELEMENTS: |
| 3137 case EXTERNAL_DOUBLE_ELEMENTS: | 3085 case EXTERNAL_FLOAT64_ELEMENTS: |
| 3138 case FAST_DOUBLE_ELEMENTS: | 3086 case FAST_DOUBLE_ELEMENTS: |
| 3139 case FAST_ELEMENTS: | 3087 case FAST_ELEMENTS: |
| 3140 case FAST_SMI_ELEMENTS: | 3088 case FAST_SMI_ELEMENTS: |
| 3141 case FAST_HOLEY_DOUBLE_ELEMENTS: | 3089 case FAST_HOLEY_DOUBLE_ELEMENTS: |
| 3142 case FAST_HOLEY_ELEMENTS: | 3090 case FAST_HOLEY_ELEMENTS: |
| 3143 case FAST_HOLEY_SMI_ELEMENTS: | 3091 case FAST_HOLEY_SMI_ELEMENTS: |
| 3144 case DICTIONARY_ELEMENTS: | 3092 case DICTIONARY_ELEMENTS: |
| 3145 case NON_STRICT_ARGUMENTS_ELEMENTS: | 3093 case NON_STRICT_ARGUMENTS_ELEMENTS: |
| 3146 UNREACHABLE(); | 3094 UNREACHABLE(); |
| 3147 break; | 3095 break; |
| (...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3356 Register receiver = ToRegister(instr->receiver()); | 3304 Register receiver = ToRegister(instr->receiver()); |
| 3357 Register function = ToRegister(instr->function()); | 3305 Register function = ToRegister(instr->function()); |
| 3358 Register result = ToRegister(instr->result()); | 3306 Register result = ToRegister(instr->result()); |
| 3359 Register scratch = scratch0(); | 3307 Register scratch = scratch0(); |
| 3360 | 3308 |
| 3361 // If the receiver is null or undefined, we have to pass the global | 3309 // If the receiver is null or undefined, we have to pass the global |
| 3362 // object as a receiver to normal functions. Values have to be | 3310 // object as a receiver to normal functions. Values have to be |
| 3363 // passed unchanged to builtins and strict-mode functions. | 3311 // passed unchanged to builtins and strict-mode functions. |
| 3364 Label global_object, result_in_receiver; | 3312 Label global_object, result_in_receiver; |
| 3365 | 3313 |
| 3366 // Do not transform the receiver to object for strict mode | 3314 if (!instr->hydrogen()->known_function()) { |
| 3367 // functions. | 3315 // Do not transform the receiver to object for strict mode |
| 3368 __ lw(scratch, | 3316 // functions. |
| 3369 FieldMemOperand(function, JSFunction::kSharedFunctionInfoOffset)); | 3317 __ lw(scratch, |
| 3370 __ lw(scratch, | 3318 FieldMemOperand(function, JSFunction::kSharedFunctionInfoOffset)); |
| 3371 FieldMemOperand(scratch, SharedFunctionInfo::kCompilerHintsOffset)); | 3319 __ lw(scratch, |
| 3320 FieldMemOperand(scratch, SharedFunctionInfo::kCompilerHintsOffset)); |
| 3372 | 3321 |
| 3373 // Do not transform the receiver to object for builtins. | 3322 // Do not transform the receiver to object for builtins. |
| 3374 int32_t strict_mode_function_mask = | 3323 int32_t strict_mode_function_mask = |
| 3375 1 << (SharedFunctionInfo::kStrictModeFunction + kSmiTagSize); | 3324 1 << (SharedFunctionInfo::kStrictModeFunction + kSmiTagSize); |
| 3376 int32_t native_mask = 1 << (SharedFunctionInfo::kNative + kSmiTagSize); | 3325 int32_t native_mask = 1 << (SharedFunctionInfo::kNative + kSmiTagSize); |
| 3377 __ And(scratch, scratch, Operand(strict_mode_function_mask | native_mask)); | 3326 __ And(scratch, scratch, Operand(strict_mode_function_mask | native_mask)); |
| 3378 __ Branch(&result_in_receiver, ne, scratch, Operand(zero_reg)); | 3327 __ Branch(&result_in_receiver, ne, scratch, Operand(zero_reg)); |
| 3328 } |
| 3379 | 3329 |
| 3380 // Normal function. Replace undefined or null with global receiver. | 3330 // Normal function. Replace undefined or null with global receiver. |
| 3381 __ LoadRoot(scratch, Heap::kNullValueRootIndex); | 3331 __ LoadRoot(scratch, Heap::kNullValueRootIndex); |
| 3382 __ Branch(&global_object, eq, receiver, Operand(scratch)); | 3332 __ Branch(&global_object, eq, receiver, Operand(scratch)); |
| 3383 __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex); | 3333 __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex); |
| 3384 __ Branch(&global_object, eq, receiver, Operand(scratch)); | 3334 __ Branch(&global_object, eq, receiver, Operand(scratch)); |
| 3385 | 3335 |
| 3386 // Deoptimize if the receiver is not a JS object. | 3336 // Deoptimize if the receiver is not a JS object. |
| 3387 __ SmiTst(receiver, scratch); | 3337 __ SmiTst(receiver, scratch); |
| 3388 DeoptimizeIf(eq, instr->environment(), scratch, Operand(zero_reg)); | 3338 DeoptimizeIf(eq, instr->environment(), scratch, Operand(zero_reg)); |
| 3389 | 3339 |
| 3390 __ GetObjectType(receiver, scratch, scratch); | 3340 __ GetObjectType(receiver, scratch, scratch); |
| 3391 DeoptimizeIf(lt, instr->environment(), | 3341 DeoptimizeIf(lt, instr->environment(), |
| 3392 scratch, Operand(FIRST_SPEC_OBJECT_TYPE)); | 3342 scratch, Operand(FIRST_SPEC_OBJECT_TYPE)); |
| 3343 |
| 3393 __ Branch(&result_in_receiver); | 3344 __ Branch(&result_in_receiver); |
| 3394 | |
| 3395 __ bind(&global_object); | 3345 __ bind(&global_object); |
| 3396 __ lw(receiver, FieldMemOperand(function, JSFunction::kContextOffset)); | 3346 __ lw(result, FieldMemOperand(function, JSFunction::kContextOffset)); |
| 3397 __ lw(receiver, | 3347 __ lw(result, |
| 3398 ContextOperand(receiver, Context::GLOBAL_OBJECT_INDEX)); | 3348 ContextOperand(result, Context::GLOBAL_OBJECT_INDEX)); |
| 3399 __ lw(receiver, | 3349 __ lw(result, |
| 3400 FieldMemOperand(receiver, GlobalObject::kGlobalReceiverOffset)); | 3350 FieldMemOperand(result, GlobalObject::kGlobalReceiverOffset)); |
| 3401 | 3351 |
| 3402 if (result.is(receiver)) { | 3352 if (result.is(receiver)) { |
| 3403 __ bind(&result_in_receiver); | 3353 __ bind(&result_in_receiver); |
| 3404 } else { | 3354 } else { |
| 3405 Label result_ok; | 3355 Label result_ok; |
| 3406 __ Branch(&result_ok); | 3356 __ Branch(&result_ok); |
| 3407 __ bind(&result_in_receiver); | 3357 __ bind(&result_in_receiver); |
| 3408 __ mov(result, receiver); | 3358 __ mov(result, receiver); |
| 3409 __ bind(&result_ok); | 3359 __ bind(&result_ok); |
| 3410 } | 3360 } |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3486 Register result = ToRegister(instr->result()); | 3436 Register result = ToRegister(instr->result()); |
| 3487 if (info()->IsOptimizing()) { | 3437 if (info()->IsOptimizing()) { |
| 3488 __ lw(result, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 3438 __ lw(result, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 3489 } else { | 3439 } else { |
| 3490 // If there is no frame, the context must be in cp. | 3440 // If there is no frame, the context must be in cp. |
| 3491 ASSERT(result.is(cp)); | 3441 ASSERT(result.is(cp)); |
| 3492 } | 3442 } |
| 3493 } | 3443 } |
| 3494 | 3444 |
| 3495 | 3445 |
| 3496 void LCodeGen::DoOuterContext(LOuterContext* instr) { | |
| 3497 Register context = ToRegister(instr->context()); | |
| 3498 Register result = ToRegister(instr->result()); | |
| 3499 __ lw(result, | |
| 3500 MemOperand(context, Context::SlotOffset(Context::PREVIOUS_INDEX))); | |
| 3501 } | |
| 3502 | |
| 3503 | |
| 3504 void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) { | 3446 void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) { |
| 3505 ASSERT(ToRegister(instr->context()).is(cp)); | 3447 ASSERT(ToRegister(instr->context()).is(cp)); |
| 3506 __ li(scratch0(), instr->hydrogen()->pairs()); | 3448 __ li(scratch0(), instr->hydrogen()->pairs()); |
| 3507 __ li(scratch1(), Operand(Smi::FromInt(instr->hydrogen()->flags()))); | 3449 __ li(scratch1(), Operand(Smi::FromInt(instr->hydrogen()->flags()))); |
| 3508 // The context is the first argument. | 3450 // The context is the first argument. |
| 3509 __ Push(cp, scratch0(), scratch1()); | 3451 __ Push(cp, scratch0(), scratch1()); |
| 3510 CallRuntime(Runtime::kDeclareGlobals, 3, instr); | 3452 CallRuntime(Runtime::kDeclareGlobals, 3, instr); |
| 3511 } | 3453 } |
| 3512 | 3454 |
| 3513 | 3455 |
| 3514 void LCodeGen::DoGlobalObject(LGlobalObject* instr) { | |
| 3515 Register context = ToRegister(instr->context()); | |
| 3516 Register result = ToRegister(instr->result()); | |
| 3517 __ lw(result, ContextOperand(context, Context::GLOBAL_OBJECT_INDEX)); | |
| 3518 } | |
| 3519 | |
| 3520 | |
| 3521 void LCodeGen::DoGlobalReceiver(LGlobalReceiver* instr) { | |
| 3522 Register global = ToRegister(instr->global_object()); | |
| 3523 Register result = ToRegister(instr->result()); | |
| 3524 __ lw(result, FieldMemOperand(global, GlobalObject::kGlobalReceiverOffset)); | |
| 3525 } | |
| 3526 | |
| 3527 | |
| 3528 void LCodeGen::CallKnownFunction(Handle<JSFunction> function, | 3456 void LCodeGen::CallKnownFunction(Handle<JSFunction> function, |
| 3529 int formal_parameter_count, | 3457 int formal_parameter_count, |
| 3530 int arity, | 3458 int arity, |
| 3531 LInstruction* instr, | 3459 LInstruction* instr, |
| 3532 A1State a1_state) { | 3460 A1State a1_state) { |
| 3533 bool dont_adapt_arguments = | 3461 bool dont_adapt_arguments = |
| 3534 formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel; | 3462 formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel; |
| 3535 bool can_invoke_directly = | 3463 bool can_invoke_directly = |
| 3536 dont_adapt_arguments || formal_parameter_count == arity; | 3464 dont_adapt_arguments || formal_parameter_count == arity; |
| 3537 | 3465 |
| (...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3829 ASSERT(ToDoubleRegister(instr->left()).is(f2)); | 3757 ASSERT(ToDoubleRegister(instr->left()).is(f2)); |
| 3830 ASSERT(ToDoubleRegister(instr->result()).is(f0)); | 3758 ASSERT(ToDoubleRegister(instr->result()).is(f0)); |
| 3831 | 3759 |
| 3832 if (exponent_type.IsSmi()) { | 3760 if (exponent_type.IsSmi()) { |
| 3833 MathPowStub stub(MathPowStub::TAGGED); | 3761 MathPowStub stub(MathPowStub::TAGGED); |
| 3834 __ CallStub(&stub); | 3762 __ CallStub(&stub); |
| 3835 } else if (exponent_type.IsTagged()) { | 3763 } else if (exponent_type.IsTagged()) { |
| 3836 Label no_deopt; | 3764 Label no_deopt; |
| 3837 __ JumpIfSmi(a2, &no_deopt); | 3765 __ JumpIfSmi(a2, &no_deopt); |
| 3838 __ lw(t3, FieldMemOperand(a2, HeapObject::kMapOffset)); | 3766 __ lw(t3, FieldMemOperand(a2, HeapObject::kMapOffset)); |
| 3767 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); |
| 3839 DeoptimizeIf(ne, instr->environment(), t3, Operand(at)); | 3768 DeoptimizeIf(ne, instr->environment(), t3, Operand(at)); |
| 3840 __ bind(&no_deopt); | 3769 __ bind(&no_deopt); |
| 3841 MathPowStub stub(MathPowStub::TAGGED); | 3770 MathPowStub stub(MathPowStub::TAGGED); |
| 3842 __ CallStub(&stub); | 3771 __ CallStub(&stub); |
| 3843 } else if (exponent_type.IsInteger32()) { | 3772 } else if (exponent_type.IsInteger32()) { |
| 3844 MathPowStub stub(MathPowStub::INTEGER); | 3773 MathPowStub stub(MathPowStub::INTEGER); |
| 3845 __ CallStub(&stub); | 3774 __ CallStub(&stub); |
| 3846 } else { | 3775 } else { |
| 3847 ASSERT(exponent_type.IsDouble()); | 3776 ASSERT(exponent_type.IsDouble()); |
| 3848 MathPowStub stub(MathPowStub::DOUBLE); | 3777 MathPowStub stub(MathPowStub::DOUBLE); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 3867 | 3796 |
| 3868 void LCodeGen::DoMathLog(LMathLog* instr) { | 3797 void LCodeGen::DoMathLog(LMathLog* instr) { |
| 3869 __ PrepareCallCFunction(0, 1, scratch0()); | 3798 __ PrepareCallCFunction(0, 1, scratch0()); |
| 3870 __ MovToFloatParameter(ToDoubleRegister(instr->value())); | 3799 __ MovToFloatParameter(ToDoubleRegister(instr->value())); |
| 3871 __ CallCFunction(ExternalReference::math_log_double_function(isolate()), | 3800 __ CallCFunction(ExternalReference::math_log_double_function(isolate()), |
| 3872 0, 1); | 3801 0, 1); |
| 3873 __ MovFromFloatResult(ToDoubleRegister(instr->result())); | 3802 __ MovFromFloatResult(ToDoubleRegister(instr->result())); |
| 3874 } | 3803 } |
| 3875 | 3804 |
| 3876 | 3805 |
| 3806 void LCodeGen::DoMathClz32(LMathClz32* instr) { |
| 3807 Register input = ToRegister(instr->value()); |
| 3808 Register result = ToRegister(instr->result()); |
| 3809 __ Clz(result, input); |
| 3810 } |
| 3811 |
| 3812 |
| 3877 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { | 3813 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { |
| 3878 ASSERT(ToRegister(instr->context()).is(cp)); | 3814 ASSERT(ToRegister(instr->context()).is(cp)); |
| 3879 ASSERT(ToRegister(instr->function()).is(a1)); | 3815 ASSERT(ToRegister(instr->function()).is(a1)); |
| 3880 ASSERT(instr->HasPointerMap()); | 3816 ASSERT(instr->HasPointerMap()); |
| 3881 | 3817 |
| 3882 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); | 3818 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); |
| 3883 if (known_function.is_null()) { | 3819 if (known_function.is_null()) { |
| 3884 LPointerMap* pointers = instr->pointer_map(); | 3820 LPointerMap* pointers = instr->pointer_map(); |
| 3885 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); | 3821 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); |
| 3886 ParameterCount count(instr->arity()); | 3822 ParameterCount count(instr->arity()); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3935 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); | 3871 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); |
| 3936 } | 3872 } |
| 3937 | 3873 |
| 3938 | 3874 |
| 3939 void LCodeGen::DoCallFunction(LCallFunction* instr) { | 3875 void LCodeGen::DoCallFunction(LCallFunction* instr) { |
| 3940 ASSERT(ToRegister(instr->context()).is(cp)); | 3876 ASSERT(ToRegister(instr->context()).is(cp)); |
| 3941 ASSERT(ToRegister(instr->function()).is(a1)); | 3877 ASSERT(ToRegister(instr->function()).is(a1)); |
| 3942 ASSERT(ToRegister(instr->result()).is(v0)); | 3878 ASSERT(ToRegister(instr->result()).is(v0)); |
| 3943 | 3879 |
| 3944 int arity = instr->arity(); | 3880 int arity = instr->arity(); |
| 3945 CallFunctionStub stub(arity, NO_CALL_FUNCTION_FLAGS); | 3881 CallFunctionStub stub(arity, instr->hydrogen()->function_flags()); |
| 3946 if (instr->hydrogen()->IsTailCall()) { | 3882 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 3947 if (NeedsEagerFrame()) __ mov(sp, fp); | |
| 3948 __ Jump(stub.GetCode(isolate()), RelocInfo::CODE_TARGET); | |
| 3949 } else { | |
| 3950 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | |
| 3951 } | |
| 3952 } | 3883 } |
| 3953 | 3884 |
| 3954 | 3885 |
| 3955 void LCodeGen::DoCallNew(LCallNew* instr) { | 3886 void LCodeGen::DoCallNew(LCallNew* instr) { |
| 3956 ASSERT(ToRegister(instr->context()).is(cp)); | 3887 ASSERT(ToRegister(instr->context()).is(cp)); |
| 3957 ASSERT(ToRegister(instr->constructor()).is(a1)); | 3888 ASSERT(ToRegister(instr->constructor()).is(a1)); |
| 3958 ASSERT(ToRegister(instr->result()).is(v0)); | 3889 ASSERT(ToRegister(instr->result()).is(v0)); |
| 3959 | 3890 |
| 3960 __ li(a0, Operand(instr->arity())); | 3891 __ li(a0, Operand(instr->arity())); |
| 3961 // No cell in a2 for construct type feedback in optimized code | 3892 // No cell in a2 for construct type feedback in optimized code |
| 3962 Handle<Object> undefined_value(isolate()->factory()->undefined_value()); | 3893 Handle<Object> undefined_value(isolate()->factory()->undefined_value()); |
| 3963 __ li(a2, Operand(undefined_value)); | 3894 __ li(a2, Operand(undefined_value)); |
| 3964 CallConstructStub stub(NO_CALL_FUNCTION_FLAGS); | 3895 CallConstructStub stub(NO_CALL_FUNCTION_FLAGS); |
| 3965 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); | 3896 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); |
| 3966 } | 3897 } |
| 3967 | 3898 |
| 3968 | 3899 |
| 3969 void LCodeGen::DoCallNewArray(LCallNewArray* instr) { | 3900 void LCodeGen::DoCallNewArray(LCallNewArray* instr) { |
| 3970 ASSERT(ToRegister(instr->context()).is(cp)); | 3901 ASSERT(ToRegister(instr->context()).is(cp)); |
| 3971 ASSERT(ToRegister(instr->constructor()).is(a1)); | 3902 ASSERT(ToRegister(instr->constructor()).is(a1)); |
| 3972 ASSERT(ToRegister(instr->result()).is(v0)); | 3903 ASSERT(ToRegister(instr->result()).is(v0)); |
| 3973 | 3904 |
| 3974 __ li(a0, Operand(instr->arity())); | 3905 __ li(a0, Operand(instr->arity())); |
| 3975 __ li(a2, Operand(instr->hydrogen()->property_cell())); | 3906 __ li(a2, Operand(factory()->undefined_value())); |
| 3976 ElementsKind kind = instr->hydrogen()->elements_kind(); | 3907 ElementsKind kind = instr->hydrogen()->elements_kind(); |
| 3977 AllocationSiteOverrideMode override_mode = | 3908 AllocationSiteOverrideMode override_mode = |
| 3978 (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE) | 3909 (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE) |
| 3979 ? DISABLE_ALLOCATION_SITES | 3910 ? DISABLE_ALLOCATION_SITES |
| 3980 : DONT_OVERRIDE; | 3911 : DONT_OVERRIDE; |
| 3981 | 3912 |
| 3982 if (instr->arity() == 0) { | 3913 if (instr->arity() == 0) { |
| 3983 ArrayNoArgumentConstructorStub stub(kind, override_mode); | 3914 ArrayNoArgumentConstructorStub stub(kind, override_mode); |
| 3984 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); | 3915 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); |
| 3985 } else if (instr->arity() == 1) { | 3916 } else if (instr->arity() == 1) { |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4045 int offset = access.offset(); | 3976 int offset = access.offset(); |
| 4046 | 3977 |
| 4047 if (access.IsExternalMemory()) { | 3978 if (access.IsExternalMemory()) { |
| 4048 Register value = ToRegister(instr->value()); | 3979 Register value = ToRegister(instr->value()); |
| 4049 MemOperand operand = MemOperand(object, offset); | 3980 MemOperand operand = MemOperand(object, offset); |
| 4050 __ Store(value, operand, representation); | 3981 __ Store(value, operand, representation); |
| 4051 return; | 3982 return; |
| 4052 } | 3983 } |
| 4053 | 3984 |
| 4054 Handle<Map> transition = instr->transition(); | 3985 Handle<Map> transition = instr->transition(); |
| 3986 SmiCheck check_needed = |
| 3987 instr->hydrogen()->value()->IsHeapObject() |
| 3988 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
| 4055 | 3989 |
| 4056 if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { | 3990 if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { |
| 4057 Register value = ToRegister(instr->value()); | 3991 Register value = ToRegister(instr->value()); |
| 4058 if (!instr->hydrogen()->value()->type().IsHeapObject()) { | 3992 if (!instr->hydrogen()->value()->type().IsHeapObject()) { |
| 4059 __ SmiTst(value, scratch); | 3993 __ SmiTst(value, scratch); |
| 4060 DeoptimizeIf(eq, instr->environment(), scratch, Operand(zero_reg)); | 3994 DeoptimizeIf(eq, instr->environment(), scratch, Operand(zero_reg)); |
| 3995 |
| 3996 // We know that value is a smi now, so we can omit the check below. |
| 3997 check_needed = OMIT_SMI_CHECK; |
| 4061 } | 3998 } |
| 4062 } else if (FLAG_track_double_fields && representation.IsDouble()) { | 3999 } else if (representation.IsDouble()) { |
| 4063 ASSERT(transition.is_null()); | 4000 ASSERT(transition.is_null()); |
| 4064 ASSERT(access.IsInobject()); | 4001 ASSERT(access.IsInobject()); |
| 4065 ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); | 4002 ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); |
| 4066 DoubleRegister value = ToDoubleRegister(instr->value()); | 4003 DoubleRegister value = ToDoubleRegister(instr->value()); |
| 4067 __ sdc1(value, FieldMemOperand(object, offset)); | 4004 __ sdc1(value, FieldMemOperand(object, offset)); |
| 4068 return; | 4005 return; |
| 4069 } | 4006 } |
| 4070 | 4007 |
| 4071 if (!transition.is_null()) { | 4008 if (!transition.is_null()) { |
| 4072 __ li(scratch, Operand(transition)); | 4009 __ li(scratch, Operand(transition)); |
| 4073 __ sw(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); | 4010 __ sw(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); |
| 4074 if (instr->hydrogen()->NeedsWriteBarrierForMap()) { | 4011 if (instr->hydrogen()->NeedsWriteBarrierForMap()) { |
| 4075 Register temp = ToRegister(instr->temp()); | 4012 Register temp = ToRegister(instr->temp()); |
| 4076 // Update the write barrier for the map field. | 4013 // Update the write barrier for the map field. |
| 4077 __ RecordWriteField(object, | 4014 __ RecordWriteField(object, |
| 4078 HeapObject::kMapOffset, | 4015 HeapObject::kMapOffset, |
| 4079 scratch, | 4016 scratch, |
| 4080 temp, | 4017 temp, |
| 4081 GetRAState(), | 4018 GetRAState(), |
| 4082 kSaveFPRegs, | 4019 kSaveFPRegs, |
| 4083 OMIT_REMEMBERED_SET, | 4020 OMIT_REMEMBERED_SET, |
| 4084 OMIT_SMI_CHECK); | 4021 OMIT_SMI_CHECK); |
| 4085 } | 4022 } |
| 4086 } | 4023 } |
| 4087 | 4024 |
| 4088 // Do the store. | 4025 // Do the store. |
| 4089 Register value = ToRegister(instr->value()); | 4026 Register value = ToRegister(instr->value()); |
| 4090 ASSERT(!object.is(value)); | |
| 4091 SmiCheck check_needed = | |
| 4092 instr->hydrogen()->value()->IsHeapObject() | |
| 4093 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; | |
| 4094 if (access.IsInobject()) { | 4027 if (access.IsInobject()) { |
| 4095 MemOperand operand = FieldMemOperand(object, offset); | 4028 MemOperand operand = FieldMemOperand(object, offset); |
| 4096 __ Store(value, operand, representation); | 4029 __ Store(value, operand, representation); |
| 4097 if (instr->hydrogen()->NeedsWriteBarrier()) { | 4030 if (instr->hydrogen()->NeedsWriteBarrier()) { |
| 4098 // Update the write barrier for the object for in-object properties. | 4031 // Update the write barrier for the object for in-object properties. |
| 4099 __ RecordWriteField(object, | 4032 __ RecordWriteField(object, |
| 4100 offset, | 4033 offset, |
| 4101 value, | 4034 value, |
| 4102 scratch, | 4035 scratch, |
| 4103 GetRAState(), | 4036 GetRAState(), |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4192 } else { | 4125 } else { |
| 4193 key = ToRegister(instr->key()); | 4126 key = ToRegister(instr->key()); |
| 4194 } | 4127 } |
| 4195 int element_size_shift = ElementsKindToShiftSize(elements_kind); | 4128 int element_size_shift = ElementsKindToShiftSize(elements_kind); |
| 4196 int shift_size = (instr->hydrogen()->key()->representation().IsSmi()) | 4129 int shift_size = (instr->hydrogen()->key()->representation().IsSmi()) |
| 4197 ? (element_size_shift - kSmiTagSize) : element_size_shift; | 4130 ? (element_size_shift - kSmiTagSize) : element_size_shift; |
| 4198 int additional_offset = IsFixedTypedArrayElementsKind(elements_kind) | 4131 int additional_offset = IsFixedTypedArrayElementsKind(elements_kind) |
| 4199 ? FixedTypedArrayBase::kDataOffset - kHeapObjectTag | 4132 ? FixedTypedArrayBase::kDataOffset - kHeapObjectTag |
| 4200 : 0; | 4133 : 0; |
| 4201 | 4134 |
| 4202 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || | 4135 if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS || |
| 4203 elements_kind == FLOAT32_ELEMENTS || | 4136 elements_kind == FLOAT32_ELEMENTS || |
| 4204 elements_kind == EXTERNAL_DOUBLE_ELEMENTS || | 4137 elements_kind == EXTERNAL_FLOAT64_ELEMENTS || |
| 4205 elements_kind == FLOAT64_ELEMENTS) { | 4138 elements_kind == FLOAT64_ELEMENTS) { |
| 4206 int base_offset = | 4139 int base_offset = |
| 4207 (instr->additional_index() << element_size_shift) + additional_offset; | 4140 (instr->additional_index() << element_size_shift) + additional_offset; |
| 4208 Register address = scratch0(); | 4141 Register address = scratch0(); |
| 4209 FPURegister value(ToDoubleRegister(instr->value())); | 4142 FPURegister value(ToDoubleRegister(instr->value())); |
| 4210 if (key_is_constant) { | 4143 if (key_is_constant) { |
| 4211 if (constant_key != 0) { | 4144 if (constant_key != 0) { |
| 4212 __ Addu(address, external_pointer, | 4145 __ Addu(address, external_pointer, |
| 4213 Operand(constant_key << element_size_shift)); | 4146 Operand(constant_key << element_size_shift)); |
| 4214 } else { | 4147 } else { |
| 4215 address = external_pointer; | 4148 address = external_pointer; |
| 4216 } | 4149 } |
| 4217 } else { | 4150 } else { |
| 4218 __ sll(address, key, shift_size); | 4151 __ sll(address, key, shift_size); |
| 4219 __ Addu(address, external_pointer, address); | 4152 __ Addu(address, external_pointer, address); |
| 4220 } | 4153 } |
| 4221 | 4154 |
| 4222 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || | 4155 if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS || |
| 4223 elements_kind == FLOAT32_ELEMENTS) { | 4156 elements_kind == FLOAT32_ELEMENTS) { |
| 4224 __ cvt_s_d(double_scratch0(), value); | 4157 __ cvt_s_d(double_scratch0(), value); |
| 4225 __ swc1(double_scratch0(), MemOperand(address, base_offset)); | 4158 __ swc1(double_scratch0(), MemOperand(address, base_offset)); |
| 4226 } else { // Storing doubles, not floats. | 4159 } else { // Storing doubles, not floats. |
| 4227 __ sdc1(value, MemOperand(address, base_offset)); | 4160 __ sdc1(value, MemOperand(address, base_offset)); |
| 4228 } | 4161 } |
| 4229 } else { | 4162 } else { |
| 4230 Register value(ToRegister(instr->value())); | 4163 Register value(ToRegister(instr->value())); |
| 4231 MemOperand mem_operand = PrepareKeyedOperand( | 4164 MemOperand mem_operand = PrepareKeyedOperand( |
| 4232 key, external_pointer, key_is_constant, constant_key, | 4165 key, external_pointer, key_is_constant, constant_key, |
| 4233 element_size_shift, shift_size, | 4166 element_size_shift, shift_size, |
| 4234 instr->additional_index(), additional_offset); | 4167 instr->additional_index(), additional_offset); |
| 4235 switch (elements_kind) { | 4168 switch (elements_kind) { |
| 4236 case EXTERNAL_PIXEL_ELEMENTS: | 4169 case EXTERNAL_UINT8_CLAMPED_ELEMENTS: |
| 4237 case EXTERNAL_BYTE_ELEMENTS: | 4170 case EXTERNAL_INT8_ELEMENTS: |
| 4238 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 4171 case EXTERNAL_UINT8_ELEMENTS: |
| 4239 case UINT8_ELEMENTS: | 4172 case UINT8_ELEMENTS: |
| 4240 case UINT8_CLAMPED_ELEMENTS: | 4173 case UINT8_CLAMPED_ELEMENTS: |
| 4241 case INT8_ELEMENTS: | 4174 case INT8_ELEMENTS: |
| 4242 __ sb(value, mem_operand); | 4175 __ sb(value, mem_operand); |
| 4243 break; | 4176 break; |
| 4244 case EXTERNAL_SHORT_ELEMENTS: | 4177 case EXTERNAL_INT16_ELEMENTS: |
| 4245 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 4178 case EXTERNAL_UINT16_ELEMENTS: |
| 4246 case INT16_ELEMENTS: | 4179 case INT16_ELEMENTS: |
| 4247 case UINT16_ELEMENTS: | 4180 case UINT16_ELEMENTS: |
| 4248 __ sh(value, mem_operand); | 4181 __ sh(value, mem_operand); |
| 4249 break; | 4182 break; |
| 4250 case EXTERNAL_INT_ELEMENTS: | 4183 case EXTERNAL_INT32_ELEMENTS: |
| 4251 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 4184 case EXTERNAL_UINT32_ELEMENTS: |
| 4252 case INT32_ELEMENTS: | 4185 case INT32_ELEMENTS: |
| 4253 case UINT32_ELEMENTS: | 4186 case UINT32_ELEMENTS: |
| 4254 __ sw(value, mem_operand); | 4187 __ sw(value, mem_operand); |
| 4255 break; | 4188 break; |
| 4256 case FLOAT32_ELEMENTS: | 4189 case FLOAT32_ELEMENTS: |
| 4257 case FLOAT64_ELEMENTS: | 4190 case FLOAT64_ELEMENTS: |
| 4258 case EXTERNAL_FLOAT_ELEMENTS: | 4191 case EXTERNAL_FLOAT32_ELEMENTS: |
| 4259 case EXTERNAL_DOUBLE_ELEMENTS: | 4192 case EXTERNAL_FLOAT64_ELEMENTS: |
| 4260 case FAST_DOUBLE_ELEMENTS: | 4193 case FAST_DOUBLE_ELEMENTS: |
| 4261 case FAST_ELEMENTS: | 4194 case FAST_ELEMENTS: |
| 4262 case FAST_SMI_ELEMENTS: | 4195 case FAST_SMI_ELEMENTS: |
| 4263 case FAST_HOLEY_DOUBLE_ELEMENTS: | 4196 case FAST_HOLEY_DOUBLE_ELEMENTS: |
| 4264 case FAST_HOLEY_ELEMENTS: | 4197 case FAST_HOLEY_ELEMENTS: |
| 4265 case FAST_HOLEY_SMI_ELEMENTS: | 4198 case FAST_HOLEY_SMI_ELEMENTS: |
| 4266 case DICTIONARY_ELEMENTS: | 4199 case DICTIONARY_ELEMENTS: |
| 4267 case NON_STRICT_ARGUMENTS_ELEMENTS: | 4200 case NON_STRICT_ARGUMENTS_ELEMENTS: |
| 4268 UNREACHABLE(); | 4201 UNREACHABLE(); |
| 4269 break; | 4202 break; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4301 } | 4234 } |
| 4302 | 4235 |
| 4303 if (instr->NeedsCanonicalization()) { | 4236 if (instr->NeedsCanonicalization()) { |
| 4304 Label is_nan; | 4237 Label is_nan; |
| 4305 // Check for NaN. All NaNs must be canonicalized. | 4238 // Check for NaN. All NaNs must be canonicalized. |
| 4306 __ BranchF(NULL, &is_nan, eq, value, value); | 4239 __ BranchF(NULL, &is_nan, eq, value, value); |
| 4307 __ Branch(¬_nan); | 4240 __ Branch(¬_nan); |
| 4308 | 4241 |
| 4309 // Only load canonical NaN if the comparison above set the overflow. | 4242 // Only load canonical NaN if the comparison above set the overflow. |
| 4310 __ bind(&is_nan); | 4243 __ bind(&is_nan); |
| 4311 __ Move(double_scratch, | 4244 __ LoadRoot(at, Heap::kNanValueRootIndex); |
| 4312 FixedDoubleArray::canonical_not_the_hole_nan_as_double()); | 4245 __ ldc1(double_scratch, FieldMemOperand(at, HeapNumber::kValueOffset)); |
| 4313 __ sdc1(double_scratch, MemOperand(scratch, instr->additional_index() << | 4246 __ sdc1(double_scratch, MemOperand(scratch, instr->additional_index() << |
| 4314 element_size_shift)); | 4247 element_size_shift)); |
| 4315 __ Branch(&done); | 4248 __ Branch(&done); |
| 4316 } | 4249 } |
| 4317 | 4250 |
| 4318 __ bind(¬_nan); | 4251 __ bind(¬_nan); |
| 4319 __ sdc1(value, MemOperand(scratch, instr->additional_index() << | 4252 __ sdc1(value, MemOperand(scratch, instr->additional_index() << |
| 4320 element_size_shift)); | 4253 element_size_shift)); |
| 4321 __ bind(&done); | 4254 __ bind(&done); |
| 4322 } | 4255 } |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4437 Label no_memento_found; | 4370 Label no_memento_found; |
| 4438 __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found, | 4371 __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found, |
| 4439 ne, &no_memento_found); | 4372 ne, &no_memento_found); |
| 4440 DeoptimizeIf(al, instr->environment()); | 4373 DeoptimizeIf(al, instr->environment()); |
| 4441 __ bind(&no_memento_found); | 4374 __ bind(&no_memento_found); |
| 4442 } | 4375 } |
| 4443 | 4376 |
| 4444 | 4377 |
| 4445 void LCodeGen::DoStringAdd(LStringAdd* instr) { | 4378 void LCodeGen::DoStringAdd(LStringAdd* instr) { |
| 4446 ASSERT(ToRegister(instr->context()).is(cp)); | 4379 ASSERT(ToRegister(instr->context()).is(cp)); |
| 4447 if (FLAG_new_string_add) { | 4380 ASSERT(ToRegister(instr->left()).is(a1)); |
| 4448 ASSERT(ToRegister(instr->left()).is(a1)); | 4381 ASSERT(ToRegister(instr->right()).is(a0)); |
| 4449 ASSERT(ToRegister(instr->right()).is(a0)); | 4382 StringAddStub stub(instr->hydrogen()->flags(), |
| 4450 NewStringAddStub stub(instr->hydrogen()->flags(), | 4383 instr->hydrogen()->pretenure_flag()); |
| 4451 isolate()->heap()->GetPretenureMode()); | 4384 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 4452 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | |
| 4453 } else { | |
| 4454 __ push(ToRegister(instr->left())); | |
| 4455 __ push(ToRegister(instr->right())); | |
| 4456 StringAddStub stub(instr->hydrogen()->flags()); | |
| 4457 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | |
| 4458 } | |
| 4459 } | 4385 } |
| 4460 | 4386 |
| 4461 | 4387 |
| 4462 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { | 4388 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { |
| 4463 class DeferredStringCharCodeAt V8_FINAL : public LDeferredCode { | 4389 class DeferredStringCharCodeAt V8_FINAL : public LDeferredCode { |
| 4464 public: | 4390 public: |
| 4465 DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr) | 4391 DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr) |
| 4466 : LDeferredCode(codegen), instr_(instr) { } | 4392 : LDeferredCode(codegen), instr_(instr) { } |
| 4467 virtual void Generate() V8_OVERRIDE { | 4393 virtual void Generate() V8_OVERRIDE { |
| 4468 codegen()->DoDeferredStringCharCodeAt(instr_); | 4394 codegen()->DoDeferredStringCharCodeAt(instr_); |
| (...skipping 410 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4879 // Heap number map check. | 4805 // Heap number map check. |
| 4880 __ lw(scratch1, FieldMemOperand(input_reg, HeapObject::kMapOffset)); | 4806 __ lw(scratch1, FieldMemOperand(input_reg, HeapObject::kMapOffset)); |
| 4881 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); | 4807 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); |
| 4882 // This 'at' value and scratch1 map value are used for tests in both clauses | 4808 // This 'at' value and scratch1 map value are used for tests in both clauses |
| 4883 // of the if. | 4809 // of the if. |
| 4884 | 4810 |
| 4885 if (instr->truncating()) { | 4811 if (instr->truncating()) { |
| 4886 // Performs a truncating conversion of a floating point number as used by | 4812 // Performs a truncating conversion of a floating point number as used by |
| 4887 // the JS bitwise operations. | 4813 // the JS bitwise operations. |
| 4888 Label no_heap_number, check_bools, check_false; | 4814 Label no_heap_number, check_bools, check_false; |
| 4889 __ Branch(&no_heap_number, ne, scratch1, Operand(at)); // HeapNumber map? | 4815 // Check HeapNumber map. |
| 4890 __ mov(scratch2, input_reg); | 4816 __ Branch(USE_DELAY_SLOT, &no_heap_number, ne, scratch1, Operand(at)); |
| 4817 __ mov(scratch2, input_reg); // In delay slot. |
| 4891 __ TruncateHeapNumberToI(input_reg, scratch2); | 4818 __ TruncateHeapNumberToI(input_reg, scratch2); |
| 4892 __ Branch(&done); | 4819 __ Branch(&done); |
| 4893 | 4820 |
| 4894 // Check for Oddballs. Undefined/False is converted to zero and True to one | 4821 // Check for Oddballs. Undefined/False is converted to zero and True to one |
| 4895 // for truncating conversions. | 4822 // for truncating conversions. |
| 4896 __ bind(&no_heap_number); | 4823 __ bind(&no_heap_number); |
| 4897 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); | 4824 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); |
| 4898 __ Branch(&check_bools, ne, input_reg, Operand(at)); | 4825 __ Branch(&check_bools, ne, input_reg, Operand(at)); |
| 4899 ASSERT(ToRegister(instr->result()).is(input_reg)); | 4826 ASSERT(ToRegister(instr->result()).is(input_reg)); |
| 4900 __ Branch(USE_DELAY_SLOT, &done); | 4827 __ Branch(USE_DELAY_SLOT, &done); |
| (...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5281 if (instr->hydrogen()->IsOldPointerSpaceAllocation()) { | 5208 if (instr->hydrogen()->IsOldPointerSpaceAllocation()) { |
| 5282 ASSERT(!instr->hydrogen()->IsOldDataSpaceAllocation()); | 5209 ASSERT(!instr->hydrogen()->IsOldDataSpaceAllocation()); |
| 5283 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); | 5210 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); |
| 5284 flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_POINTER_SPACE); | 5211 flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_POINTER_SPACE); |
| 5285 } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) { | 5212 } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) { |
| 5286 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); | 5213 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); |
| 5287 flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_DATA_SPACE); | 5214 flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_DATA_SPACE); |
| 5288 } | 5215 } |
| 5289 if (instr->size()->IsConstantOperand()) { | 5216 if (instr->size()->IsConstantOperand()) { |
| 5290 int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); | 5217 int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); |
| 5291 __ Allocate(size, result, scratch, scratch2, deferred->entry(), flags); | 5218 if (size <= Page::kMaxRegularHeapObjectSize) { |
| 5219 __ Allocate(size, result, scratch, scratch2, deferred->entry(), flags); |
| 5220 } else { |
| 5221 __ jmp(deferred->entry()); |
| 5222 } |
| 5292 } else { | 5223 } else { |
| 5293 Register size = ToRegister(instr->size()); | 5224 Register size = ToRegister(instr->size()); |
| 5294 __ Allocate(size, | 5225 __ Allocate(size, |
| 5295 result, | 5226 result, |
| 5296 scratch, | 5227 scratch, |
| 5297 scratch2, | 5228 scratch2, |
| 5298 deferred->entry(), | 5229 deferred->entry(), |
| 5299 flags); | 5230 flags); |
| 5300 } | 5231 } |
| 5301 | 5232 |
| (...skipping 520 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5822 __ Subu(scratch, result, scratch); | 5753 __ Subu(scratch, result, scratch); |
| 5823 __ lw(result, FieldMemOperand(scratch, | 5754 __ lw(result, FieldMemOperand(scratch, |
| 5824 FixedArray::kHeaderSize - kPointerSize)); | 5755 FixedArray::kHeaderSize - kPointerSize)); |
| 5825 __ bind(&done); | 5756 __ bind(&done); |
| 5826 } | 5757 } |
| 5827 | 5758 |
| 5828 | 5759 |
| 5829 #undef __ | 5760 #undef __ |
| 5830 | 5761 |
| 5831 } } // namespace v8::internal | 5762 } } // namespace v8::internal |
| OLD | NEW |