| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 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 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 80 GenerateDeferredCode() && | 80 GenerateDeferredCode() && |
| 81 GenerateJumpTable() && | 81 GenerateJumpTable() && |
| 82 GenerateSafepointTable(); | 82 GenerateSafepointTable(); |
| 83 } | 83 } |
| 84 | 84 |
| 85 | 85 |
| 86 void LCodeGen::FinishCode(Handle<Code> code) { | 86 void LCodeGen::FinishCode(Handle<Code> code) { |
| 87 ASSERT(is_done()); | 87 ASSERT(is_done()); |
| 88 code->set_stack_slots(GetStackSlotCount()); | 88 code->set_stack_slots(GetStackSlotCount()); |
| 89 code->set_safepoint_table_offset(safepoints_.GetCodeOffset()); | 89 code->set_safepoint_table_offset(safepoints_.GetCodeOffset()); |
| 90 RegisterDependentCodeForEmbeddedMaps(code); | 90 if (code->is_optimized_code()) RegisterWeakObjectsInOptimizedCode(code); |
| 91 PopulateDeoptimizationData(code); | 91 PopulateDeoptimizationData(code); |
| 92 info()->CommitDependencies(code); | 92 info()->CommitDependencies(code); |
| 93 } | 93 } |
| 94 | 94 |
| 95 | 95 |
| 96 void LChunkBuilder::Abort(BailoutReason reason) { | 96 void LChunkBuilder::Abort(BailoutReason reason) { |
| 97 info()->set_bailout_reason(reason); | 97 info()->set_bailout_reason(reason); |
| 98 status_ = ABORTED; | 98 status_ = ABORTED; |
| 99 } | 99 } |
| 100 | 100 |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 211 if (info()->saves_caller_doubles()) { | 211 if (info()->saves_caller_doubles()) { |
| 212 SaveCallerDoubles(); | 212 SaveCallerDoubles(); |
| 213 } | 213 } |
| 214 } | 214 } |
| 215 | 215 |
| 216 // Possibly allocate a local context. | 216 // Possibly allocate a local context. |
| 217 int heap_slots = info_->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; | 217 int heap_slots = info_->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; |
| 218 if (heap_slots > 0) { | 218 if (heap_slots > 0) { |
| 219 Comment(";;; Allocate local context"); | 219 Comment(";;; Allocate local context"); |
| 220 // Argument to NewContext is the function, which is still in rdi. | 220 // Argument to NewContext is the function, which is still in rdi. |
| 221 __ push(rdi); | |
| 222 if (heap_slots <= FastNewContextStub::kMaximumSlots) { | 221 if (heap_slots <= FastNewContextStub::kMaximumSlots) { |
| 223 FastNewContextStub stub(heap_slots); | 222 FastNewContextStub stub(heap_slots); |
| 224 __ CallStub(&stub); | 223 __ CallStub(&stub); |
| 225 } else { | 224 } else { |
| 225 __ push(rdi); |
| 226 __ CallRuntime(Runtime::kNewFunctionContext, 1); | 226 __ CallRuntime(Runtime::kNewFunctionContext, 1); |
| 227 } | 227 } |
| 228 RecordSafepoint(Safepoint::kNoLazyDeopt); | 228 RecordSafepoint(Safepoint::kNoLazyDeopt); |
| 229 // Context is returned in both rax and rsi. It replaces the context | 229 // Context is returned in rax. It replaces the context passed to us. |
| 230 // passed to us. It's saved in the stack and kept live in rsi. | 230 // It's saved in the stack and kept live in rsi. |
| 231 __ movp(Operand(rbp, StandardFrameConstants::kContextOffset), rsi); | 231 __ movp(rsi, rax); |
| 232 __ movp(Operand(rbp, StandardFrameConstants::kContextOffset), rax); |
| 232 | 233 |
| 233 // Copy any necessary parameters into the context. | 234 // Copy any necessary parameters into the context. |
| 234 int num_parameters = scope()->num_parameters(); | 235 int num_parameters = scope()->num_parameters(); |
| 235 for (int i = 0; i < num_parameters; i++) { | 236 for (int i = 0; i < num_parameters; i++) { |
| 236 Variable* var = scope()->parameter(i); | 237 Variable* var = scope()->parameter(i); |
| 237 if (var->IsContextSlot()) { | 238 if (var->IsContextSlot()) { |
| 238 int parameter_offset = StandardFrameConstants::kCallerSPOffset + | 239 int parameter_offset = StandardFrameConstants::kCallerSPOffset + |
| 239 (num_parameters - 1 - i) * kPointerSize; | 240 (num_parameters - 1 - i) * kPointerSize; |
| 240 // Load parameter from stack. | 241 // Load parameter from stack. |
| 241 __ movp(rax, Operand(rbp, parameter_offset)); | 242 __ movp(rax, Operand(rbp, parameter_offset)); |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 320 | 321 |
| 321 | 322 |
| 322 bool LCodeGen::GenerateDeferredCode() { | 323 bool LCodeGen::GenerateDeferredCode() { |
| 323 ASSERT(is_generating()); | 324 ASSERT(is_generating()); |
| 324 if (deferred_.length() > 0) { | 325 if (deferred_.length() > 0) { |
| 325 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { | 326 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { |
| 326 LDeferredCode* code = deferred_[i]; | 327 LDeferredCode* code = deferred_[i]; |
| 327 | 328 |
| 328 HValue* value = | 329 HValue* value = |
| 329 instructions_->at(code->instruction_index())->hydrogen_value(); | 330 instructions_->at(code->instruction_index())->hydrogen_value(); |
| 330 RecordAndWritePosition(value->position()); | 331 RecordAndWritePosition( |
| 332 chunk()->graph()->SourcePositionToScriptPosition(value->position())); |
| 331 | 333 |
| 332 Comment(";;; <@%d,#%d> " | 334 Comment(";;; <@%d,#%d> " |
| 333 "-------------------- Deferred %s --------------------", | 335 "-------------------- Deferred %s --------------------", |
| 334 code->instruction_index(), | 336 code->instruction_index(), |
| 335 code->instr()->hydrogen_value()->id(), | 337 code->instr()->hydrogen_value()->id(), |
| 336 code->instr()->Mnemonic()); | 338 code->instr()->Mnemonic()); |
| 337 __ bind(code->entry()); | 339 __ bind(code->entry()); |
| 338 if (NeedsDeferredFrame()) { | 340 if (NeedsDeferredFrame()) { |
| 339 Comment(";;; Build frame"); | 341 Comment(";;; Build frame"); |
| 340 ASSERT(!frame_is_built_); | 342 ASSERT(!frame_is_built_); |
| (...skipping 442 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 783 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { | 785 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { |
| 784 int length = deoptimizations_.length(); | 786 int length = deoptimizations_.length(); |
| 785 if (length == 0) return; | 787 if (length == 0) return; |
| 786 Handle<DeoptimizationInputData> data = | 788 Handle<DeoptimizationInputData> data = |
| 787 factory()->NewDeoptimizationInputData(length, TENURED); | 789 factory()->NewDeoptimizationInputData(length, TENURED); |
| 788 | 790 |
| 789 Handle<ByteArray> translations = | 791 Handle<ByteArray> translations = |
| 790 translations_.CreateByteArray(isolate()->factory()); | 792 translations_.CreateByteArray(isolate()->factory()); |
| 791 data->SetTranslationByteArray(*translations); | 793 data->SetTranslationByteArray(*translations); |
| 792 data->SetInlinedFunctionCount(Smi::FromInt(inlined_function_count_)); | 794 data->SetInlinedFunctionCount(Smi::FromInt(inlined_function_count_)); |
| 795 data->SetOptimizationId(Smi::FromInt(info_->optimization_id())); |
| 796 if (info_->IsOptimizing()) { |
| 797 // Reference to shared function info does not change between phases. |
| 798 AllowDeferredHandleDereference allow_handle_dereference; |
| 799 data->SetSharedFunctionInfo(*info_->shared_info()); |
| 800 } else { |
| 801 data->SetSharedFunctionInfo(Smi::FromInt(0)); |
| 802 } |
| 793 | 803 |
| 794 Handle<FixedArray> literals = | 804 Handle<FixedArray> literals = |
| 795 factory()->NewFixedArray(deoptimization_literals_.length(), TENURED); | 805 factory()->NewFixedArray(deoptimization_literals_.length(), TENURED); |
| 796 { AllowDeferredHandleDereference copy_handles; | 806 { AllowDeferredHandleDereference copy_handles; |
| 797 for (int i = 0; i < deoptimization_literals_.length(); i++) { | 807 for (int i = 0; i < deoptimization_literals_.length(); i++) { |
| 798 literals->set(i, *deoptimization_literals_[i]); | 808 literals->set(i, *deoptimization_literals_[i]); |
| 799 } | 809 } |
| 800 data->SetLiteralArray(*literals); | 810 data->SetLiteralArray(*literals); |
| 801 } | 811 } |
| 802 | 812 |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 944 | 954 |
| 945 void LCodeGen::DoParameter(LParameter* instr) { | 955 void LCodeGen::DoParameter(LParameter* instr) { |
| 946 // Nothing to do. | 956 // Nothing to do. |
| 947 } | 957 } |
| 948 | 958 |
| 949 | 959 |
| 950 void LCodeGen::DoCallStub(LCallStub* instr) { | 960 void LCodeGen::DoCallStub(LCallStub* instr) { |
| 951 ASSERT(ToRegister(instr->context()).is(rsi)); | 961 ASSERT(ToRegister(instr->context()).is(rsi)); |
| 952 ASSERT(ToRegister(instr->result()).is(rax)); | 962 ASSERT(ToRegister(instr->result()).is(rax)); |
| 953 switch (instr->hydrogen()->major_key()) { | 963 switch (instr->hydrogen()->major_key()) { |
| 954 case CodeStub::RegExpConstructResult: { | |
| 955 RegExpConstructResultStub stub; | |
| 956 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | |
| 957 break; | |
| 958 } | |
| 959 case CodeStub::RegExpExec: { | 964 case CodeStub::RegExpExec: { |
| 960 RegExpExecStub stub; | 965 RegExpExecStub stub; |
| 961 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 966 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 962 break; | 967 break; |
| 963 } | 968 } |
| 964 case CodeStub::SubString: { | 969 case CodeStub::SubString: { |
| 965 SubStringStub stub; | 970 SubStringStub stub; |
| 966 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 971 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 967 break; | 972 break; |
| 968 } | 973 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 979 | 984 |
| 980 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { | 985 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { |
| 981 GenerateOsrPrologue(); | 986 GenerateOsrPrologue(); |
| 982 } | 987 } |
| 983 | 988 |
| 984 | 989 |
| 985 void LCodeGen::DoModI(LModI* instr) { | 990 void LCodeGen::DoModI(LModI* instr) { |
| 986 HMod* hmod = instr->hydrogen(); | 991 HMod* hmod = instr->hydrogen(); |
| 987 HValue* left = hmod->left(); | 992 HValue* left = hmod->left(); |
| 988 HValue* right = hmod->right(); | 993 HValue* right = hmod->right(); |
| 989 if (hmod->HasPowerOf2Divisor()) { | 994 if (hmod->RightIsPowerOf2()) { |
| 990 // TODO(svenpanne) We should really do the strength reduction on the | 995 // TODO(svenpanne) We should really do the strength reduction on the |
| 991 // Hydrogen level. | 996 // Hydrogen level. |
| 992 Register left_reg = ToRegister(instr->left()); | 997 Register left_reg = ToRegister(instr->left()); |
| 993 ASSERT(left_reg.is(ToRegister(instr->result()))); | 998 ASSERT(left_reg.is(ToRegister(instr->result()))); |
| 994 | 999 |
| 995 // Note: The code below even works when right contains kMinInt. | 1000 // Note: The code below even works when right contains kMinInt. |
| 996 int32_t divisor = Abs(right->GetInteger32Constant()); | 1001 int32_t divisor = Abs(right->GetInteger32Constant()); |
| 997 | 1002 |
| 998 Label left_is_not_negative, done; | 1003 Label left_is_not_negative, done; |
| 999 if (left->CanBeNegative()) { | 1004 if (left->CanBeNegative()) { |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1145 // Result just fit in r64, because it's int32 * uint32. | 1150 // Result just fit in r64, because it's int32 * uint32. |
| 1146 __ imul(reg2, reg1); | 1151 __ imul(reg2, reg1); |
| 1147 | 1152 |
| 1148 __ addq(reg2, Immediate(1 << 30)); | 1153 __ addq(reg2, Immediate(1 << 30)); |
| 1149 __ sar(reg2, Immediate(shift)); | 1154 __ sar(reg2, Immediate(shift)); |
| 1150 } | 1155 } |
| 1151 } | 1156 } |
| 1152 | 1157 |
| 1153 | 1158 |
| 1154 void LCodeGen::DoDivI(LDivI* instr) { | 1159 void LCodeGen::DoDivI(LDivI* instr) { |
| 1155 if (!instr->is_flooring() && instr->hydrogen()->HasPowerOf2Divisor()) { | 1160 if (!instr->is_flooring() && instr->hydrogen()->RightIsPowerOf2()) { |
| 1156 Register dividend = ToRegister(instr->left()); | 1161 Register dividend = ToRegister(instr->left()); |
| 1157 int32_t divisor = | 1162 HDiv* hdiv = instr->hydrogen(); |
| 1158 HConstant::cast(instr->hydrogen()->right())->Integer32Value(); | 1163 int32_t divisor = hdiv->right()->GetInteger32Constant(); |
| 1159 int32_t test_value = 0; | 1164 Register result = ToRegister(instr->result()); |
| 1160 int32_t power = 0; | 1165 ASSERT(!result.is(dividend)); |
| 1161 | 1166 |
| 1162 if (divisor > 0) { | 1167 // Check for (0 / -x) that will produce negative zero. |
| 1163 test_value = divisor - 1; | 1168 if (hdiv->left()->RangeCanInclude(0) && divisor < 0 && |
| 1164 power = WhichPowerOf2(divisor); | 1169 hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1165 } else { | 1170 __ testl(dividend, dividend); |
| 1166 // Check for (0 / -x) that will produce negative zero. | 1171 DeoptimizeIf(zero, instr->environment()); |
| 1167 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | |
| 1168 __ testl(dividend, dividend); | |
| 1169 DeoptimizeIf(zero, instr->environment()); | |
| 1170 } | |
| 1171 // Check for (kMinInt / -1). | |
| 1172 if (divisor == -1 && instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | |
| 1173 __ cmpl(dividend, Immediate(kMinInt)); | |
| 1174 DeoptimizeIf(zero, instr->environment()); | |
| 1175 } | |
| 1176 test_value = - divisor - 1; | |
| 1177 power = WhichPowerOf2(-divisor); | |
| 1178 } | 1172 } |
| 1179 | 1173 // Check for (kMinInt / -1). |
| 1180 if (test_value != 0) { | 1174 if (hdiv->left()->RangeCanInclude(kMinInt) && divisor == -1 && |
| 1181 if (instr->hydrogen()->CheckFlag( | 1175 hdiv->CheckFlag(HValue::kCanOverflow)) { |
| 1182 HInstruction::kAllUsesTruncatingToInt32)) { | 1176 __ cmpl(dividend, Immediate(kMinInt)); |
| 1183 Label done, negative; | 1177 DeoptimizeIf(zero, instr->environment()); |
| 1184 __ cmpl(dividend, Immediate(0)); | |
| 1185 __ j(less, &negative, Label::kNear); | |
| 1186 __ sarl(dividend, Immediate(power)); | |
| 1187 if (divisor < 0) __ negl(dividend); | |
| 1188 __ jmp(&done, Label::kNear); | |
| 1189 | |
| 1190 __ bind(&negative); | |
| 1191 __ negl(dividend); | |
| 1192 __ sarl(dividend, Immediate(power)); | |
| 1193 if (divisor > 0) __ negl(dividend); | |
| 1194 __ bind(&done); | |
| 1195 return; // Don't fall through to "__ neg" below. | |
| 1196 } else { | |
| 1197 // Deoptimize if remainder is not 0. | |
| 1198 __ testl(dividend, Immediate(test_value)); | |
| 1199 DeoptimizeIf(not_zero, instr->environment()); | |
| 1200 __ sarl(dividend, Immediate(power)); | |
| 1201 } | |
| 1202 } | 1178 } |
| 1203 | 1179 // Deoptimize if remainder will not be 0. |
| 1204 if (divisor < 0) __ negl(dividend); | 1180 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { |
| 1205 | 1181 __ testl(dividend, Immediate(Abs(divisor) - 1)); |
| 1182 DeoptimizeIf(not_zero, instr->environment()); |
| 1183 } |
| 1184 __ Move(result, dividend); |
| 1185 int32_t shift = WhichPowerOf2(Abs(divisor)); |
| 1186 if (shift > 0) { |
| 1187 // The arithmetic shift is always OK, the 'if' is an optimization only. |
| 1188 if (shift > 1) __ sarl(result, Immediate(31)); |
| 1189 __ shrl(result, Immediate(32 - shift)); |
| 1190 __ addl(result, dividend); |
| 1191 __ sarl(result, Immediate(shift)); |
| 1192 } |
| 1193 if (divisor < 0) __ negl(result); |
| 1206 return; | 1194 return; |
| 1207 } | 1195 } |
| 1208 | 1196 |
| 1209 LOperand* right = instr->right(); | 1197 LOperand* right = instr->right(); |
| 1210 ASSERT(ToRegister(instr->result()).is(rax)); | 1198 ASSERT(ToRegister(instr->result()).is(rax)); |
| 1211 ASSERT(ToRegister(instr->left()).is(rax)); | 1199 ASSERT(ToRegister(instr->left()).is(rax)); |
| 1212 ASSERT(!ToRegister(instr->right()).is(rax)); | 1200 ASSERT(!ToRegister(instr->right()).is(rax)); |
| 1213 ASSERT(!ToRegister(instr->right()).is(rdx)); | 1201 ASSERT(!ToRegister(instr->right()).is(rdx)); |
| 1214 | 1202 |
| 1215 Register left_reg = rax; | 1203 Register left_reg = rax; |
| (...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1571 } | 1559 } |
| 1572 | 1560 |
| 1573 | 1561 |
| 1574 void LCodeGen::DoMapEnumLength(LMapEnumLength* instr) { | 1562 void LCodeGen::DoMapEnumLength(LMapEnumLength* instr) { |
| 1575 Register result = ToRegister(instr->result()); | 1563 Register result = ToRegister(instr->result()); |
| 1576 Register map = ToRegister(instr->value()); | 1564 Register map = ToRegister(instr->value()); |
| 1577 __ EnumLength(result, map); | 1565 __ EnumLength(result, map); |
| 1578 } | 1566 } |
| 1579 | 1567 |
| 1580 | 1568 |
| 1581 void LCodeGen::DoElementsKind(LElementsKind* instr) { | |
| 1582 Register result = ToRegister(instr->result()); | |
| 1583 Register input = ToRegister(instr->value()); | |
| 1584 | |
| 1585 // Load map into |result|. | |
| 1586 __ movp(result, FieldOperand(input, HeapObject::kMapOffset)); | |
| 1587 // Load the map's "bit field 2" into |result|. We only need the first byte. | |
| 1588 __ movzxbq(result, FieldOperand(result, Map::kBitField2Offset)); | |
| 1589 // Retrieve elements_kind from bit field 2. | |
| 1590 __ and_(result, Immediate(Map::kElementsKindMask)); | |
| 1591 __ shr(result, Immediate(Map::kElementsKindShift)); | |
| 1592 } | |
| 1593 | |
| 1594 | |
| 1595 void LCodeGen::DoValueOf(LValueOf* instr) { | |
| 1596 Register input = ToRegister(instr->value()); | |
| 1597 Register result = ToRegister(instr->result()); | |
| 1598 ASSERT(input.is(result)); | |
| 1599 Label done; | |
| 1600 | |
| 1601 if (!instr->hydrogen()->value()->IsHeapObject()) { | |
| 1602 // If the object is a smi return the object. | |
| 1603 __ JumpIfSmi(input, &done, Label::kNear); | |
| 1604 } | |
| 1605 | |
| 1606 // If the object is not a value type, return the object. | |
| 1607 __ CmpObjectType(input, JS_VALUE_TYPE, kScratchRegister); | |
| 1608 __ j(not_equal, &done, Label::kNear); | |
| 1609 __ movp(result, FieldOperand(input, JSValue::kValueOffset)); | |
| 1610 | |
| 1611 __ bind(&done); | |
| 1612 } | |
| 1613 | |
| 1614 | |
| 1615 void LCodeGen::DoDateField(LDateField* instr) { | 1569 void LCodeGen::DoDateField(LDateField* instr) { |
| 1616 Register object = ToRegister(instr->date()); | 1570 Register object = ToRegister(instr->date()); |
| 1617 Register result = ToRegister(instr->result()); | 1571 Register result = ToRegister(instr->result()); |
| 1618 Smi* index = instr->index(); | 1572 Smi* index = instr->index(); |
| 1619 Label runtime, done, not_date_object; | 1573 Label runtime, done, not_date_object; |
| 1620 ASSERT(object.is(result)); | 1574 ASSERT(object.is(result)); |
| 1621 ASSERT(object.is(rax)); | 1575 ASSERT(object.is(rax)); |
| 1622 | 1576 |
| 1623 Condition cc = masm()->CheckSmi(object); | 1577 Condition cc = masm()->CheckSmi(object); |
| 1624 DeoptimizeIf(cc, instr->environment()); | 1578 DeoptimizeIf(cc, instr->environment()); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1635 __ cmpq(kScratchRegister, FieldOperand(object, | 1589 __ cmpq(kScratchRegister, FieldOperand(object, |
| 1636 JSDate::kCacheStampOffset)); | 1590 JSDate::kCacheStampOffset)); |
| 1637 __ j(not_equal, &runtime, Label::kNear); | 1591 __ j(not_equal, &runtime, Label::kNear); |
| 1638 __ movp(result, FieldOperand(object, JSDate::kValueOffset + | 1592 __ movp(result, FieldOperand(object, JSDate::kValueOffset + |
| 1639 kPointerSize * index->value())); | 1593 kPointerSize * index->value())); |
| 1640 __ jmp(&done, Label::kNear); | 1594 __ jmp(&done, Label::kNear); |
| 1641 } | 1595 } |
| 1642 __ bind(&runtime); | 1596 __ bind(&runtime); |
| 1643 __ PrepareCallCFunction(2); | 1597 __ PrepareCallCFunction(2); |
| 1644 __ movp(arg_reg_1, object); | 1598 __ movp(arg_reg_1, object); |
| 1645 __ Move(arg_reg_2, index, RelocInfo::NONE64); | 1599 __ Move(arg_reg_2, index, Assembler::RelocInfoNone()); |
| 1646 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); | 1600 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); |
| 1647 __ bind(&done); | 1601 __ bind(&done); |
| 1648 } | 1602 } |
| 1649 } | 1603 } |
| 1650 | 1604 |
| 1651 | 1605 |
| 1652 Operand LCodeGen::BuildSeqStringOperand(Register string, | 1606 Operand LCodeGen::BuildSeqStringOperand(Register string, |
| 1653 LOperand* index, | 1607 LOperand* index, |
| 1654 String::Encoding encoding) { | 1608 String::Encoding encoding) { |
| 1655 if (index->IsConstantOperand()) { | 1609 if (index->IsConstantOperand()) { |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1725 Register value = ToRegister(instr->value()); | 1679 Register value = ToRegister(instr->value()); |
| 1726 if (encoding == String::ONE_BYTE_ENCODING) { | 1680 if (encoding == String::ONE_BYTE_ENCODING) { |
| 1727 __ movb(operand, value); | 1681 __ movb(operand, value); |
| 1728 } else { | 1682 } else { |
| 1729 __ movw(operand, value); | 1683 __ movw(operand, value); |
| 1730 } | 1684 } |
| 1731 } | 1685 } |
| 1732 } | 1686 } |
| 1733 | 1687 |
| 1734 | 1688 |
| 1735 void LCodeGen::DoThrow(LThrow* instr) { | |
| 1736 __ push(ToRegister(instr->value())); | |
| 1737 ASSERT(ToRegister(instr->context()).is(rsi)); | |
| 1738 CallRuntime(Runtime::kThrow, 1, instr); | |
| 1739 | |
| 1740 if (FLAG_debug_code) { | |
| 1741 Comment("Unreachable code."); | |
| 1742 __ int3(); | |
| 1743 } | |
| 1744 } | |
| 1745 | |
| 1746 | |
| 1747 void LCodeGen::DoAddI(LAddI* instr) { | 1689 void LCodeGen::DoAddI(LAddI* instr) { |
| 1748 LOperand* left = instr->left(); | 1690 LOperand* left = instr->left(); |
| 1749 LOperand* right = instr->right(); | 1691 LOperand* right = instr->right(); |
| 1750 | 1692 |
| 1751 Representation target_rep = instr->hydrogen()->representation(); | 1693 Representation target_rep = instr->hydrogen()->representation(); |
| 1752 bool is_q = target_rep.IsSmi() || target_rep.IsExternal(); | 1694 bool is_q = target_rep.IsSmi() || target_rep.IsExternal(); |
| 1753 | 1695 |
| 1754 if (LAddI::UseLea(instr->hydrogen()) && !left->Equals(instr->result())) { | 1696 if (LAddI::UseLea(instr->hydrogen()) && !left->Equals(instr->result())) { |
| 1755 if (right->IsConstantOperand()) { | 1697 if (right->IsConstantOperand()) { |
| 1756 int32_t offset = ToInteger32(LConstantOperand::cast(right)); | 1698 int32_t offset = ToInteger32(LConstantOperand::cast(right)); |
| (...skipping 1050 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2807 ASSERT(result.is(rax)); | 2749 ASSERT(result.is(rax)); |
| 2808 __ load_rax(ToExternalReference(LConstantOperand::cast(instr->object()))); | 2750 __ load_rax(ToExternalReference(LConstantOperand::cast(instr->object()))); |
| 2809 } else { | 2751 } else { |
| 2810 Register object = ToRegister(instr->object()); | 2752 Register object = ToRegister(instr->object()); |
| 2811 __ Load(result, MemOperand(object, offset), access.representation()); | 2753 __ Load(result, MemOperand(object, offset), access.representation()); |
| 2812 } | 2754 } |
| 2813 return; | 2755 return; |
| 2814 } | 2756 } |
| 2815 | 2757 |
| 2816 Register object = ToRegister(instr->object()); | 2758 Register object = ToRegister(instr->object()); |
| 2817 if (FLAG_track_double_fields && | 2759 if (instr->hydrogen()->representation().IsDouble()) { |
| 2818 instr->hydrogen()->representation().IsDouble()) { | |
| 2819 XMMRegister result = ToDoubleRegister(instr->result()); | 2760 XMMRegister result = ToDoubleRegister(instr->result()); |
| 2820 __ movsd(result, FieldOperand(object, offset)); | 2761 __ movsd(result, FieldOperand(object, offset)); |
| 2821 return; | 2762 return; |
| 2822 } | 2763 } |
| 2823 | 2764 |
| 2824 Register result = ToRegister(instr->result()); | 2765 Register result = ToRegister(instr->result()); |
| 2825 if (!access.IsInobject()) { | 2766 if (!access.IsInobject()) { |
| 2826 __ movp(result, FieldOperand(object, JSObject::kPropertiesOffset)); | 2767 __ movp(result, FieldOperand(object, JSObject::kPropertiesOffset)); |
| 2827 object = result; | 2768 object = result; |
| 2828 } | 2769 } |
| 2829 | 2770 |
| 2830 Representation representation = access.representation(); | 2771 Representation representation = access.representation(); |
| 2831 if (representation.IsSmi() && | 2772 if (representation.IsSmi() && |
| 2832 instr->hydrogen()->representation().IsInteger32()) { | 2773 instr->hydrogen()->representation().IsInteger32()) { |
| 2774 #ifdef DEBUG |
| 2775 Register scratch = kScratchRegister; |
| 2776 __ Load(scratch, FieldOperand(object, offset), representation); |
| 2777 __ AssertSmi(scratch); |
| 2778 #endif |
| 2779 |
| 2833 // Read int value directly from upper half of the smi. | 2780 // Read int value directly from upper half of the smi. |
| 2834 STATIC_ASSERT(kSmiTag == 0); | 2781 STATIC_ASSERT(kSmiTag == 0); |
| 2835 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 32); | 2782 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 32); |
| 2836 offset += kPointerSize / 2; | 2783 offset += kPointerSize / 2; |
| 2837 representation = Representation::Integer32(); | 2784 representation = Representation::Integer32(); |
| 2838 } | 2785 } |
| 2839 __ Load(result, FieldOperand(object, offset), representation); | 2786 __ Load(result, FieldOperand(object, offset), representation); |
| 2840 } | 2787 } |
| 2841 | 2788 |
| 2842 | 2789 |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2891 __ bind(&done); | 2838 __ bind(&done); |
| 2892 } | 2839 } |
| 2893 | 2840 |
| 2894 | 2841 |
| 2895 void LCodeGen::DoLoadRoot(LLoadRoot* instr) { | 2842 void LCodeGen::DoLoadRoot(LLoadRoot* instr) { |
| 2896 Register result = ToRegister(instr->result()); | 2843 Register result = ToRegister(instr->result()); |
| 2897 __ LoadRoot(result, instr->index()); | 2844 __ LoadRoot(result, instr->index()); |
| 2898 } | 2845 } |
| 2899 | 2846 |
| 2900 | 2847 |
| 2901 void LCodeGen::DoLoadExternalArrayPointer( | |
| 2902 LLoadExternalArrayPointer* instr) { | |
| 2903 Register result = ToRegister(instr->result()); | |
| 2904 Register input = ToRegister(instr->object()); | |
| 2905 __ movp(result, FieldOperand(input, | |
| 2906 ExternalPixelArray::kExternalPointerOffset)); | |
| 2907 } | |
| 2908 | |
| 2909 | |
| 2910 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { | 2848 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { |
| 2911 Register arguments = ToRegister(instr->arguments()); | 2849 Register arguments = ToRegister(instr->arguments()); |
| 2912 Register result = ToRegister(instr->result()); | 2850 Register result = ToRegister(instr->result()); |
| 2913 | 2851 |
| 2914 if (instr->length()->IsConstantOperand() && | 2852 if (instr->length()->IsConstantOperand() && |
| 2915 instr->index()->IsConstantOperand()) { | 2853 instr->index()->IsConstantOperand()) { |
| 2916 int32_t const_index = ToInteger32(LConstantOperand::cast(instr->index())); | 2854 int32_t const_index = ToInteger32(LConstantOperand::cast(instr->index())); |
| 2917 int32_t const_length = ToInteger32(LConstantOperand::cast(instr->length())); | 2855 int32_t const_length = ToInteger32(LConstantOperand::cast(instr->length())); |
| 2918 StackArgumentsAccessor args(arguments, const_length, | 2856 StackArgumentsAccessor args(arguments, const_length, |
| 2919 ARGUMENTS_DONT_CONTAIN_RECEIVER); | 2857 ARGUMENTS_DONT_CONTAIN_RECEIVER); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2953 int base_offset = instr->is_fixed_typed_array() | 2891 int base_offset = instr->is_fixed_typed_array() |
| 2954 ? FixedTypedArrayBase::kDataOffset - kHeapObjectTag | 2892 ? FixedTypedArrayBase::kDataOffset - kHeapObjectTag |
| 2955 : 0; | 2893 : 0; |
| 2956 Operand operand(BuildFastArrayOperand( | 2894 Operand operand(BuildFastArrayOperand( |
| 2957 instr->elements(), | 2895 instr->elements(), |
| 2958 key, | 2896 key, |
| 2959 elements_kind, | 2897 elements_kind, |
| 2960 base_offset, | 2898 base_offset, |
| 2961 instr->additional_index())); | 2899 instr->additional_index())); |
| 2962 | 2900 |
| 2963 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || | 2901 if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS || |
| 2964 elements_kind == FLOAT32_ELEMENTS) { | 2902 elements_kind == FLOAT32_ELEMENTS) { |
| 2965 XMMRegister result(ToDoubleRegister(instr->result())); | 2903 XMMRegister result(ToDoubleRegister(instr->result())); |
| 2966 __ movss(result, operand); | 2904 __ movss(result, operand); |
| 2967 __ cvtss2sd(result, result); | 2905 __ cvtss2sd(result, result); |
| 2968 } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS || | 2906 } else if (elements_kind == EXTERNAL_FLOAT64_ELEMENTS || |
| 2969 elements_kind == FLOAT64_ELEMENTS) { | 2907 elements_kind == FLOAT64_ELEMENTS) { |
| 2970 __ movsd(ToDoubleRegister(instr->result()), operand); | 2908 __ movsd(ToDoubleRegister(instr->result()), operand); |
| 2971 } else { | 2909 } else { |
| 2972 Register result(ToRegister(instr->result())); | 2910 Register result(ToRegister(instr->result())); |
| 2973 switch (elements_kind) { | 2911 switch (elements_kind) { |
| 2974 case EXTERNAL_BYTE_ELEMENTS: | 2912 case EXTERNAL_INT8_ELEMENTS: |
| 2975 case INT8_ELEMENTS: | 2913 case INT8_ELEMENTS: |
| 2976 __ movsxbq(result, operand); | 2914 __ movsxbq(result, operand); |
| 2977 break; | 2915 break; |
| 2978 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 2916 case EXTERNAL_UINT8_ELEMENTS: |
| 2979 case EXTERNAL_PIXEL_ELEMENTS: | 2917 case EXTERNAL_UINT8_CLAMPED_ELEMENTS: |
| 2980 case UINT8_ELEMENTS: | 2918 case UINT8_ELEMENTS: |
| 2981 case UINT8_CLAMPED_ELEMENTS: | 2919 case UINT8_CLAMPED_ELEMENTS: |
| 2982 __ movzxbq(result, operand); | 2920 __ movzxbq(result, operand); |
| 2983 break; | 2921 break; |
| 2984 case EXTERNAL_SHORT_ELEMENTS: | 2922 case EXTERNAL_INT16_ELEMENTS: |
| 2985 case INT16_ELEMENTS: | 2923 case INT16_ELEMENTS: |
| 2986 __ movsxwq(result, operand); | 2924 __ movsxwq(result, operand); |
| 2987 break; | 2925 break; |
| 2988 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 2926 case EXTERNAL_UINT16_ELEMENTS: |
| 2989 case UINT16_ELEMENTS: | 2927 case UINT16_ELEMENTS: |
| 2990 __ movzxwq(result, operand); | 2928 __ movzxwq(result, operand); |
| 2991 break; | 2929 break; |
| 2992 case EXTERNAL_INT_ELEMENTS: | 2930 case EXTERNAL_INT32_ELEMENTS: |
| 2993 case INT32_ELEMENTS: | 2931 case INT32_ELEMENTS: |
| 2994 __ movsxlq(result, operand); | 2932 __ movsxlq(result, operand); |
| 2995 break; | 2933 break; |
| 2996 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 2934 case EXTERNAL_UINT32_ELEMENTS: |
| 2997 case UINT32_ELEMENTS: | 2935 case UINT32_ELEMENTS: |
| 2998 __ movl(result, operand); | 2936 __ movl(result, operand); |
| 2999 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { | 2937 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { |
| 3000 __ testl(result, result); | 2938 __ testl(result, result); |
| 3001 DeoptimizeIf(negative, instr->environment()); | 2939 DeoptimizeIf(negative, instr->environment()); |
| 3002 } | 2940 } |
| 3003 break; | 2941 break; |
| 3004 case EXTERNAL_FLOAT_ELEMENTS: | 2942 case EXTERNAL_FLOAT32_ELEMENTS: |
| 3005 case EXTERNAL_DOUBLE_ELEMENTS: | 2943 case EXTERNAL_FLOAT64_ELEMENTS: |
| 3006 case FLOAT32_ELEMENTS: | 2944 case FLOAT32_ELEMENTS: |
| 3007 case FLOAT64_ELEMENTS: | 2945 case FLOAT64_ELEMENTS: |
| 3008 case FAST_ELEMENTS: | 2946 case FAST_ELEMENTS: |
| 3009 case FAST_SMI_ELEMENTS: | 2947 case FAST_SMI_ELEMENTS: |
| 3010 case FAST_DOUBLE_ELEMENTS: | 2948 case FAST_DOUBLE_ELEMENTS: |
| 3011 case FAST_HOLEY_ELEMENTS: | 2949 case FAST_HOLEY_ELEMENTS: |
| 3012 case FAST_HOLEY_SMI_ELEMENTS: | 2950 case FAST_HOLEY_SMI_ELEMENTS: |
| 3013 case FAST_HOLEY_DOUBLE_ELEMENTS: | 2951 case FAST_HOLEY_DOUBLE_ELEMENTS: |
| 3014 case DICTIONARY_ELEMENTS: | 2952 case DICTIONARY_ELEMENTS: |
| 3015 case NON_STRICT_ARGUMENTS_ELEMENTS: | 2953 case NON_STRICT_ARGUMENTS_ELEMENTS: |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3077 } | 3015 } |
| 3078 } | 3016 } |
| 3079 | 3017 |
| 3080 bool requires_hole_check = hinstr->RequiresHoleCheck(); | 3018 bool requires_hole_check = hinstr->RequiresHoleCheck(); |
| 3081 int offset = FixedArray::kHeaderSize - kHeapObjectTag; | 3019 int offset = FixedArray::kHeaderSize - kHeapObjectTag; |
| 3082 Representation representation = hinstr->representation(); | 3020 Representation representation = hinstr->representation(); |
| 3083 | 3021 |
| 3084 if (representation.IsInteger32() && | 3022 if (representation.IsInteger32() && |
| 3085 hinstr->elements_kind() == FAST_SMI_ELEMENTS) { | 3023 hinstr->elements_kind() == FAST_SMI_ELEMENTS) { |
| 3086 ASSERT(!requires_hole_check); | 3024 ASSERT(!requires_hole_check); |
| 3025 #ifdef DEBUG |
| 3026 Register scratch = kScratchRegister; |
| 3027 __ Load(scratch, |
| 3028 BuildFastArrayOperand(instr->elements(), |
| 3029 key, |
| 3030 FAST_ELEMENTS, |
| 3031 offset, |
| 3032 instr->additional_index()), |
| 3033 Representation::Smi()); |
| 3034 __ AssertSmi(scratch); |
| 3035 #endif |
| 3087 // Read int value directly from upper half of the smi. | 3036 // Read int value directly from upper half of the smi. |
| 3088 STATIC_ASSERT(kSmiTag == 0); | 3037 STATIC_ASSERT(kSmiTag == 0); |
| 3089 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 32); | 3038 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 32); |
| 3090 offset += kPointerSize / 2; | 3039 offset += kPointerSize / 2; |
| 3091 } | 3040 } |
| 3092 | 3041 |
| 3093 __ Load(result, | 3042 __ Load(result, |
| 3094 BuildFastArrayOperand(instr->elements(), | 3043 BuildFastArrayOperand(instr->elements(), |
| 3095 key, | 3044 key, |
| 3096 FAST_ELEMENTS, | 3045 FAST_ELEMENTS, |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3214 void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) { | 3163 void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) { |
| 3215 Register receiver = ToRegister(instr->receiver()); | 3164 Register receiver = ToRegister(instr->receiver()); |
| 3216 Register function = ToRegister(instr->function()); | 3165 Register function = ToRegister(instr->function()); |
| 3217 | 3166 |
| 3218 // If the receiver is null or undefined, we have to pass the global | 3167 // If the receiver is null or undefined, we have to pass the global |
| 3219 // object as a receiver to normal functions. Values have to be | 3168 // object as a receiver to normal functions. Values have to be |
| 3220 // passed unchanged to builtins and strict-mode functions. | 3169 // passed unchanged to builtins and strict-mode functions. |
| 3221 Label global_object, receiver_ok; | 3170 Label global_object, receiver_ok; |
| 3222 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear; | 3171 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear; |
| 3223 | 3172 |
| 3224 // Do not transform the receiver to object for strict mode | 3173 if (!instr->hydrogen()->known_function()) { |
| 3225 // functions. | 3174 // Do not transform the receiver to object for strict mode |
| 3226 __ movp(kScratchRegister, | 3175 // functions. |
| 3227 FieldOperand(function, JSFunction::kSharedFunctionInfoOffset)); | 3176 __ movp(kScratchRegister, |
| 3228 __ testb(FieldOperand(kScratchRegister, | 3177 FieldOperand(function, JSFunction::kSharedFunctionInfoOffset)); |
| 3229 SharedFunctionInfo::kStrictModeByteOffset), | 3178 __ testb(FieldOperand(kScratchRegister, |
| 3230 Immediate(1 << SharedFunctionInfo::kStrictModeBitWithinByte)); | 3179 SharedFunctionInfo::kStrictModeByteOffset), |
| 3231 __ j(not_equal, &receiver_ok, dist); | 3180 Immediate(1 << SharedFunctionInfo::kStrictModeBitWithinByte)); |
| 3181 __ j(not_equal, &receiver_ok, dist); |
| 3232 | 3182 |
| 3233 // Do not transform the receiver to object for builtins. | 3183 // Do not transform the receiver to object for builtins. |
| 3234 __ testb(FieldOperand(kScratchRegister, | 3184 __ testb(FieldOperand(kScratchRegister, |
| 3235 SharedFunctionInfo::kNativeByteOffset), | 3185 SharedFunctionInfo::kNativeByteOffset), |
| 3236 Immediate(1 << SharedFunctionInfo::kNativeBitWithinByte)); | 3186 Immediate(1 << SharedFunctionInfo::kNativeBitWithinByte)); |
| 3237 __ j(not_equal, &receiver_ok, dist); | 3187 __ j(not_equal, &receiver_ok, dist); |
| 3188 } |
| 3238 | 3189 |
| 3239 // Normal function. Replace undefined or null with global receiver. | 3190 // Normal function. Replace undefined or null with global receiver. |
| 3240 __ CompareRoot(receiver, Heap::kNullValueRootIndex); | 3191 __ CompareRoot(receiver, Heap::kNullValueRootIndex); |
| 3241 __ j(equal, &global_object, Label::kNear); | 3192 __ j(equal, &global_object, Label::kNear); |
| 3242 __ CompareRoot(receiver, Heap::kUndefinedValueRootIndex); | 3193 __ CompareRoot(receiver, Heap::kUndefinedValueRootIndex); |
| 3243 __ j(equal, &global_object, Label::kNear); | 3194 __ j(equal, &global_object, Label::kNear); |
| 3244 | 3195 |
| 3245 // The receiver should be a JS object. | 3196 // The receiver should be a JS object. |
| 3246 Condition is_smi = __ CheckSmi(receiver); | 3197 Condition is_smi = __ CheckSmi(receiver); |
| 3247 DeoptimizeIf(is_smi, instr->environment()); | 3198 DeoptimizeIf(is_smi, instr->environment()); |
| 3248 __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, kScratchRegister); | 3199 __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, kScratchRegister); |
| 3249 DeoptimizeIf(below, instr->environment()); | 3200 DeoptimizeIf(below, instr->environment()); |
| 3201 |
| 3250 __ jmp(&receiver_ok, Label::kNear); | 3202 __ jmp(&receiver_ok, Label::kNear); |
| 3251 | |
| 3252 __ bind(&global_object); | 3203 __ bind(&global_object); |
| 3253 __ movp(receiver, FieldOperand(function, JSFunction::kContextOffset)); | 3204 __ movp(receiver, FieldOperand(function, JSFunction::kContextOffset)); |
| 3254 __ movp(receiver, | 3205 __ movp(receiver, |
| 3255 Operand(receiver, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); | 3206 Operand(receiver, |
| 3207 Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); |
| 3256 __ movp(receiver, | 3208 __ movp(receiver, |
| 3257 FieldOperand(receiver, GlobalObject::kGlobalReceiverOffset)); | 3209 FieldOperand(receiver, GlobalObject::kGlobalReceiverOffset)); |
| 3210 |
| 3258 __ bind(&receiver_ok); | 3211 __ bind(&receiver_ok); |
| 3259 } | 3212 } |
| 3260 | 3213 |
| 3261 | 3214 |
| 3262 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { | 3215 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { |
| 3263 Register receiver = ToRegister(instr->receiver()); | 3216 Register receiver = ToRegister(instr->receiver()); |
| 3264 Register function = ToRegister(instr->function()); | 3217 Register function = ToRegister(instr->function()); |
| 3265 Register length = ToRegister(instr->length()); | 3218 Register length = ToRegister(instr->length()); |
| 3266 Register elements = ToRegister(instr->elements()); | 3219 Register elements = ToRegister(instr->elements()); |
| 3267 ASSERT(receiver.is(rax)); // Used for parameter count. | 3220 ASSERT(receiver.is(rax)); // Used for parameter count. |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3322 Register result = ToRegister(instr->result()); | 3275 Register result = ToRegister(instr->result()); |
| 3323 if (info()->IsOptimizing()) { | 3276 if (info()->IsOptimizing()) { |
| 3324 __ movp(result, Operand(rbp, StandardFrameConstants::kContextOffset)); | 3277 __ movp(result, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 3325 } else { | 3278 } else { |
| 3326 // If there is no frame, the context must be in rsi. | 3279 // If there is no frame, the context must be in rsi. |
| 3327 ASSERT(result.is(rsi)); | 3280 ASSERT(result.is(rsi)); |
| 3328 } | 3281 } |
| 3329 } | 3282 } |
| 3330 | 3283 |
| 3331 | 3284 |
| 3332 void LCodeGen::DoOuterContext(LOuterContext* instr) { | |
| 3333 Register context = ToRegister(instr->context()); | |
| 3334 Register result = ToRegister(instr->result()); | |
| 3335 __ movp(result, | |
| 3336 Operand(context, Context::SlotOffset(Context::PREVIOUS_INDEX))); | |
| 3337 } | |
| 3338 | |
| 3339 | |
| 3340 void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) { | 3285 void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) { |
| 3341 ASSERT(ToRegister(instr->context()).is(rsi)); | 3286 ASSERT(ToRegister(instr->context()).is(rsi)); |
| 3342 __ push(rsi); // The context is the first argument. | 3287 __ push(rsi); // The context is the first argument. |
| 3343 __ Push(instr->hydrogen()->pairs()); | 3288 __ Push(instr->hydrogen()->pairs()); |
| 3344 __ Push(Smi::FromInt(instr->hydrogen()->flags())); | 3289 __ Push(Smi::FromInt(instr->hydrogen()->flags())); |
| 3345 CallRuntime(Runtime::kDeclareGlobals, 3, instr); | 3290 CallRuntime(Runtime::kDeclareGlobals, 3, instr); |
| 3346 } | 3291 } |
| 3347 | 3292 |
| 3348 | 3293 |
| 3349 void LCodeGen::DoGlobalObject(LGlobalObject* instr) { | |
| 3350 Register context = ToRegister(instr->context()); | |
| 3351 Register result = ToRegister(instr->result()); | |
| 3352 __ movp(result, | |
| 3353 Operand(context, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); | |
| 3354 } | |
| 3355 | |
| 3356 | |
| 3357 void LCodeGen::DoGlobalReceiver(LGlobalReceiver* instr) { | |
| 3358 Register global = ToRegister(instr->global()); | |
| 3359 Register result = ToRegister(instr->result()); | |
| 3360 __ movp(result, FieldOperand(global, GlobalObject::kGlobalReceiverOffset)); | |
| 3361 } | |
| 3362 | |
| 3363 | |
| 3364 void LCodeGen::CallKnownFunction(Handle<JSFunction> function, | 3294 void LCodeGen::CallKnownFunction(Handle<JSFunction> function, |
| 3365 int formal_parameter_count, | 3295 int formal_parameter_count, |
| 3366 int arity, | 3296 int arity, |
| 3367 LInstruction* instr, | 3297 LInstruction* instr, |
| 3368 RDIState rdi_state) { | 3298 RDIState rdi_state) { |
| 3369 bool dont_adapt_arguments = | 3299 bool dont_adapt_arguments = |
| 3370 formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel; | 3300 formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel; |
| 3371 bool can_invoke_directly = | 3301 bool can_invoke_directly = |
| 3372 dont_adapt_arguments || formal_parameter_count == arity; | 3302 dont_adapt_arguments || formal_parameter_count == arity; |
| 3373 | 3303 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 3384 // Set rax to arguments count if adaption is not needed. Assumes that rax | 3314 // Set rax to arguments count if adaption is not needed. Assumes that rax |
| 3385 // is available to write to at this point. | 3315 // is available to write to at this point. |
| 3386 if (dont_adapt_arguments) { | 3316 if (dont_adapt_arguments) { |
| 3387 __ Set(rax, arity); | 3317 __ Set(rax, arity); |
| 3388 } | 3318 } |
| 3389 | 3319 |
| 3390 // Invoke function. | 3320 // Invoke function. |
| 3391 if (function.is_identical_to(info()->closure())) { | 3321 if (function.is_identical_to(info()->closure())) { |
| 3392 __ CallSelf(); | 3322 __ CallSelf(); |
| 3393 } else { | 3323 } else { |
| 3394 __ call(FieldOperand(rdi, JSFunction::kCodeEntryOffset)); | 3324 __ Call(FieldOperand(rdi, JSFunction::kCodeEntryOffset)); |
| 3395 } | 3325 } |
| 3396 | 3326 |
| 3397 // Set up deoptimization. | 3327 // Set up deoptimization. |
| 3398 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT, 0); | 3328 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT, 0); |
| 3399 } else { | 3329 } else { |
| 3400 // We need to adapt arguments. | 3330 // We need to adapt arguments. |
| 3401 SafepointGenerator generator( | 3331 SafepointGenerator generator( |
| 3402 this, pointers, Safepoint::kLazyDeopt); | 3332 this, pointers, Safepoint::kLazyDeopt); |
| 3403 ParameterCount count(arity); | 3333 ParameterCount count(arity); |
| 3404 ParameterCount expected(formal_parameter_count); | 3334 ParameterCount expected(formal_parameter_count); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3449 HConstant* fun_const = HConstant::cast(instr->hydrogen()->function()); | 3379 HConstant* fun_const = HConstant::cast(instr->hydrogen()->function()); |
| 3450 jsfun = Handle<JSFunction>::cast(fun_const->handle(isolate())); | 3380 jsfun = Handle<JSFunction>::cast(fun_const->handle(isolate())); |
| 3451 is_self_call = jsfun.is_identical_to(info()->closure()); | 3381 is_self_call = jsfun.is_identical_to(info()->closure()); |
| 3452 } | 3382 } |
| 3453 | 3383 |
| 3454 if (is_self_call) { | 3384 if (is_self_call) { |
| 3455 __ CallSelf(); | 3385 __ CallSelf(); |
| 3456 } else { | 3386 } else { |
| 3457 Operand target = FieldOperand(rdi, JSFunction::kCodeEntryOffset); | 3387 Operand target = FieldOperand(rdi, JSFunction::kCodeEntryOffset); |
| 3458 generator.BeforeCall(__ CallSize(target)); | 3388 generator.BeforeCall(__ CallSize(target)); |
| 3459 __ call(target); | 3389 __ Call(target); |
| 3460 } | 3390 } |
| 3461 generator.AfterCall(); | 3391 generator.AfterCall(); |
| 3462 } | 3392 } |
| 3463 | 3393 |
| 3464 | 3394 |
| 3465 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { | 3395 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { |
| 3466 Register input_reg = ToRegister(instr->value()); | 3396 Register input_reg = ToRegister(instr->value()); |
| 3467 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), | 3397 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), |
| 3468 Heap::kHeapNumberMapRootIndex); | 3398 Heap::kHeapNumberMapRootIndex); |
| 3469 DeoptimizeIf(not_equal, instr->environment()); | 3399 DeoptimizeIf(not_equal, instr->environment()); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 3489 // Slow case: Call the runtime system to do the number allocation. | 3419 // Slow case: Call the runtime system to do the number allocation. |
| 3490 __ bind(&slow); | 3420 __ bind(&slow); |
| 3491 CallRuntimeFromDeferred( | 3421 CallRuntimeFromDeferred( |
| 3492 Runtime::kAllocateHeapNumber, 0, instr, instr->context()); | 3422 Runtime::kAllocateHeapNumber, 0, instr, instr->context()); |
| 3493 // Set the pointer to the new heap number in tmp. | 3423 // Set the pointer to the new heap number in tmp. |
| 3494 if (!tmp.is(rax)) __ movp(tmp, rax); | 3424 if (!tmp.is(rax)) __ movp(tmp, rax); |
| 3495 // Restore input_reg after call to runtime. | 3425 // Restore input_reg after call to runtime. |
| 3496 __ LoadFromSafepointRegisterSlot(input_reg, input_reg); | 3426 __ LoadFromSafepointRegisterSlot(input_reg, input_reg); |
| 3497 | 3427 |
| 3498 __ bind(&allocated); | 3428 __ bind(&allocated); |
| 3499 __ MoveDouble(tmp2, FieldOperand(input_reg, HeapNumber::kValueOffset)); | 3429 __ movq(tmp2, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
| 3500 __ shl(tmp2, Immediate(1)); | 3430 __ shl(tmp2, Immediate(1)); |
| 3501 __ shr(tmp2, Immediate(1)); | 3431 __ shr(tmp2, Immediate(1)); |
| 3502 __ MoveDouble(FieldOperand(tmp, HeapNumber::kValueOffset), tmp2); | 3432 __ movq(FieldOperand(tmp, HeapNumber::kValueOffset), tmp2); |
| 3503 __ StoreToSafepointRegisterSlot(input_reg, tmp); | 3433 __ StoreToSafepointRegisterSlot(input_reg, tmp); |
| 3504 | 3434 |
| 3505 __ bind(&done); | 3435 __ bind(&done); |
| 3506 } | 3436 } |
| 3507 | 3437 |
| 3508 | 3438 |
| 3509 void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) { | 3439 void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) { |
| 3510 Register input_reg = ToRegister(instr->value()); | 3440 Register input_reg = ToRegister(instr->value()); |
| 3511 __ testl(input_reg, input_reg); | 3441 __ testl(input_reg, input_reg); |
| 3512 Label is_positive; | 3442 Label is_positive; |
| (...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3799 __ movsd(Operand(rsp, 0), input_reg); | 3729 __ movsd(Operand(rsp, 0), input_reg); |
| 3800 __ fld_d(Operand(rsp, 0)); | 3730 __ fld_d(Operand(rsp, 0)); |
| 3801 __ fyl2x(); | 3731 __ fyl2x(); |
| 3802 __ fstp_d(Operand(rsp, 0)); | 3732 __ fstp_d(Operand(rsp, 0)); |
| 3803 __ movsd(input_reg, Operand(rsp, 0)); | 3733 __ movsd(input_reg, Operand(rsp, 0)); |
| 3804 __ addq(rsp, Immediate(kDoubleSize)); | 3734 __ addq(rsp, Immediate(kDoubleSize)); |
| 3805 __ bind(&done); | 3735 __ bind(&done); |
| 3806 } | 3736 } |
| 3807 | 3737 |
| 3808 | 3738 |
| 3739 void LCodeGen::DoMathClz32(LMathClz32* instr) { |
| 3740 Register input = ToRegister(instr->value()); |
| 3741 Register result = ToRegister(instr->result()); |
| 3742 Label not_zero_input; |
| 3743 __ bsrl(result, input); |
| 3744 |
| 3745 __ j(not_zero, ¬_zero_input); |
| 3746 __ Set(result, 63); // 63^31 == 32 |
| 3747 |
| 3748 __ bind(¬_zero_input); |
| 3749 __ xorl(result, Immediate(31)); // for x in [0..31], 31^x == 31-x. |
| 3750 } |
| 3751 |
| 3752 |
| 3809 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { | 3753 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { |
| 3810 ASSERT(ToRegister(instr->context()).is(rsi)); | 3754 ASSERT(ToRegister(instr->context()).is(rsi)); |
| 3811 ASSERT(ToRegister(instr->function()).is(rdi)); | 3755 ASSERT(ToRegister(instr->function()).is(rdi)); |
| 3812 ASSERT(instr->HasPointerMap()); | 3756 ASSERT(instr->HasPointerMap()); |
| 3813 | 3757 |
| 3814 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); | 3758 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); |
| 3815 if (known_function.is_null()) { | 3759 if (known_function.is_null()) { |
| 3816 LPointerMap* pointers = instr->pointer_map(); | 3760 LPointerMap* pointers = instr->pointer_map(); |
| 3817 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); | 3761 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); |
| 3818 ParameterCount count(instr->arity()); | 3762 ParameterCount count(instr->arity()); |
| 3819 __ InvokeFunction(rdi, count, CALL_FUNCTION, generator); | 3763 __ InvokeFunction(rdi, count, CALL_FUNCTION, generator); |
| 3820 } else { | 3764 } else { |
| 3821 CallKnownFunction(known_function, | 3765 CallKnownFunction(known_function, |
| 3822 instr->hydrogen()->formal_parameter_count(), | 3766 instr->hydrogen()->formal_parameter_count(), |
| 3823 instr->arity(), | 3767 instr->arity(), |
| 3824 instr, | 3768 instr, |
| 3825 RDI_CONTAINS_TARGET); | 3769 RDI_CONTAINS_TARGET); |
| 3826 } | 3770 } |
| 3827 } | 3771 } |
| 3828 | 3772 |
| 3829 | 3773 |
| 3830 void LCodeGen::DoCallFunction(LCallFunction* instr) { | 3774 void LCodeGen::DoCallFunction(LCallFunction* instr) { |
| 3831 ASSERT(ToRegister(instr->context()).is(rsi)); | 3775 ASSERT(ToRegister(instr->context()).is(rsi)); |
| 3832 ASSERT(ToRegister(instr->function()).is(rdi)); | 3776 ASSERT(ToRegister(instr->function()).is(rdi)); |
| 3833 ASSERT(ToRegister(instr->result()).is(rax)); | 3777 ASSERT(ToRegister(instr->result()).is(rax)); |
| 3834 | 3778 |
| 3835 int arity = instr->arity(); | 3779 int arity = instr->arity(); |
| 3836 CallFunctionStub stub(arity, NO_CALL_FUNCTION_FLAGS); | 3780 CallFunctionStub stub(arity, instr->hydrogen()->function_flags()); |
| 3837 if (instr->hydrogen()->IsTailCall()) { | 3781 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 3838 if (NeedsEagerFrame()) __ leave(); | |
| 3839 __ jmp(stub.GetCode(isolate()), RelocInfo::CODE_TARGET); | |
| 3840 } else { | |
| 3841 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | |
| 3842 } | |
| 3843 } | 3782 } |
| 3844 | 3783 |
| 3845 | 3784 |
| 3846 void LCodeGen::DoCallNew(LCallNew* instr) { | 3785 void LCodeGen::DoCallNew(LCallNew* instr) { |
| 3847 ASSERT(ToRegister(instr->context()).is(rsi)); | 3786 ASSERT(ToRegister(instr->context()).is(rsi)); |
| 3848 ASSERT(ToRegister(instr->constructor()).is(rdi)); | 3787 ASSERT(ToRegister(instr->constructor()).is(rdi)); |
| 3849 ASSERT(ToRegister(instr->result()).is(rax)); | 3788 ASSERT(ToRegister(instr->result()).is(rax)); |
| 3850 | 3789 |
| 3851 __ Set(rax, instr->arity()); | 3790 __ Set(rax, instr->arity()); |
| 3852 // No cell in ebx for construct type feedback in optimized code | 3791 // No cell in ebx for construct type feedback in optimized code |
| 3853 Handle<Object> undefined_value(isolate()->factory()->undefined_value()); | 3792 Handle<Object> undefined_value(isolate()->factory()->undefined_value()); |
| 3854 __ Move(rbx, undefined_value); | 3793 __ Move(rbx, undefined_value); |
| 3855 CallConstructStub stub(NO_CALL_FUNCTION_FLAGS); | 3794 CallConstructStub stub(NO_CALL_FUNCTION_FLAGS); |
| 3856 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); | 3795 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); |
| 3857 } | 3796 } |
| 3858 | 3797 |
| 3859 | 3798 |
| 3860 void LCodeGen::DoCallNewArray(LCallNewArray* instr) { | 3799 void LCodeGen::DoCallNewArray(LCallNewArray* instr) { |
| 3861 ASSERT(ToRegister(instr->context()).is(rsi)); | 3800 ASSERT(ToRegister(instr->context()).is(rsi)); |
| 3862 ASSERT(ToRegister(instr->constructor()).is(rdi)); | 3801 ASSERT(ToRegister(instr->constructor()).is(rdi)); |
| 3863 ASSERT(ToRegister(instr->result()).is(rax)); | 3802 ASSERT(ToRegister(instr->result()).is(rax)); |
| 3864 | 3803 |
| 3865 __ Set(rax, instr->arity()); | 3804 __ Set(rax, instr->arity()); |
| 3866 __ Move(rbx, instr->hydrogen()->property_cell()); | 3805 __ Move(rbx, factory()->undefined_value()); |
| 3867 ElementsKind kind = instr->hydrogen()->elements_kind(); | 3806 ElementsKind kind = instr->hydrogen()->elements_kind(); |
| 3868 AllocationSiteOverrideMode override_mode = | 3807 AllocationSiteOverrideMode override_mode = |
| 3869 (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE) | 3808 (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE) |
| 3870 ? DISABLE_ALLOCATION_SITES | 3809 ? DISABLE_ALLOCATION_SITES |
| 3871 : DONT_OVERRIDE; | 3810 : DONT_OVERRIDE; |
| 3872 | 3811 |
| 3873 if (instr->arity() == 0) { | 3812 if (instr->arity() == 0) { |
| 3874 ArrayNoArgumentConstructorStub stub(kind, override_mode); | 3813 ArrayNoArgumentConstructorStub stub(kind, override_mode); |
| 3875 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); | 3814 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); |
| 3876 } else if (instr->arity() == 1) { | 3815 } else if (instr->arity() == 1) { |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3932 Representation representation = instr->representation(); | 3871 Representation representation = instr->representation(); |
| 3933 | 3872 |
| 3934 HObjectAccess access = hinstr->access(); | 3873 HObjectAccess access = hinstr->access(); |
| 3935 int offset = access.offset(); | 3874 int offset = access.offset(); |
| 3936 | 3875 |
| 3937 if (access.IsExternalMemory()) { | 3876 if (access.IsExternalMemory()) { |
| 3938 ASSERT(!hinstr->NeedsWriteBarrier()); | 3877 ASSERT(!hinstr->NeedsWriteBarrier()); |
| 3939 Register value = ToRegister(instr->value()); | 3878 Register value = ToRegister(instr->value()); |
| 3940 if (instr->object()->IsConstantOperand()) { | 3879 if (instr->object()->IsConstantOperand()) { |
| 3941 ASSERT(value.is(rax)); | 3880 ASSERT(value.is(rax)); |
| 3942 ASSERT(!access.representation().IsSpecialization()); | |
| 3943 LConstantOperand* object = LConstantOperand::cast(instr->object()); | 3881 LConstantOperand* object = LConstantOperand::cast(instr->object()); |
| 3944 __ store_rax(ToExternalReference(object)); | 3882 __ store_rax(ToExternalReference(object)); |
| 3945 } else { | 3883 } else { |
| 3946 Register object = ToRegister(instr->object()); | 3884 Register object = ToRegister(instr->object()); |
| 3947 __ Store(MemOperand(object, offset), value, representation); | 3885 __ Store(MemOperand(object, offset), value, representation); |
| 3948 } | 3886 } |
| 3949 return; | 3887 return; |
| 3950 } | 3888 } |
| 3951 | 3889 |
| 3952 Register object = ToRegister(instr->object()); | 3890 Register object = ToRegister(instr->object()); |
| 3953 Handle<Map> transition = instr->transition(); | 3891 Handle<Map> transition = instr->transition(); |
| 3892 SmiCheck check_needed = hinstr->value()->IsHeapObject() |
| 3893 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
| 3954 | 3894 |
| 3955 if (FLAG_track_fields && representation.IsSmi()) { | 3895 if (FLAG_track_fields && representation.IsSmi()) { |
| 3956 if (instr->value()->IsConstantOperand()) { | 3896 if (instr->value()->IsConstantOperand()) { |
| 3957 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); | 3897 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); |
| 3958 if (!IsInteger32Constant(operand_value) && | 3898 if (!IsInteger32Constant(operand_value) && |
| 3959 !IsSmiConstant(operand_value)) { | 3899 !IsSmiConstant(operand_value)) { |
| 3960 DeoptimizeIf(no_condition, instr->environment()); | 3900 DeoptimizeIf(no_condition, instr->environment()); |
| 3961 } | 3901 } |
| 3962 } | 3902 } |
| 3963 } else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { | 3903 } else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { |
| 3964 if (instr->value()->IsConstantOperand()) { | 3904 if (instr->value()->IsConstantOperand()) { |
| 3965 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); | 3905 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); |
| 3966 if (IsInteger32Constant(operand_value)) { | 3906 if (IsInteger32Constant(operand_value)) { |
| 3967 DeoptimizeIf(no_condition, instr->environment()); | 3907 DeoptimizeIf(no_condition, instr->environment()); |
| 3968 } | 3908 } |
| 3969 } else { | 3909 } else { |
| 3970 if (!hinstr->value()->type().IsHeapObject()) { | 3910 if (!hinstr->value()->type().IsHeapObject()) { |
| 3971 Register value = ToRegister(instr->value()); | 3911 Register value = ToRegister(instr->value()); |
| 3972 Condition cc = masm()->CheckSmi(value); | 3912 Condition cc = masm()->CheckSmi(value); |
| 3973 DeoptimizeIf(cc, instr->environment()); | 3913 DeoptimizeIf(cc, instr->environment()); |
| 3914 |
| 3915 // We know that value is a smi now, so we can omit the check below. |
| 3916 check_needed = OMIT_SMI_CHECK; |
| 3974 } | 3917 } |
| 3975 } | 3918 } |
| 3976 } else if (FLAG_track_double_fields && representation.IsDouble()) { | 3919 } else if (representation.IsDouble()) { |
| 3977 ASSERT(transition.is_null()); | 3920 ASSERT(transition.is_null()); |
| 3978 ASSERT(access.IsInobject()); | 3921 ASSERT(access.IsInobject()); |
| 3979 ASSERT(!hinstr->NeedsWriteBarrier()); | 3922 ASSERT(!hinstr->NeedsWriteBarrier()); |
| 3980 XMMRegister value = ToDoubleRegister(instr->value()); | 3923 XMMRegister value = ToDoubleRegister(instr->value()); |
| 3981 __ movsd(FieldOperand(object, offset), value); | 3924 __ movsd(FieldOperand(object, offset), value); |
| 3982 return; | 3925 return; |
| 3983 } | 3926 } |
| 3984 | 3927 |
| 3985 if (!transition.is_null()) { | 3928 if (!transition.is_null()) { |
| 3986 if (!hinstr->NeedsWriteBarrierForMap()) { | 3929 if (!hinstr->NeedsWriteBarrierForMap()) { |
| 3987 __ Move(FieldOperand(object, HeapObject::kMapOffset), transition); | 3930 __ Move(FieldOperand(object, HeapObject::kMapOffset), transition); |
| 3988 } else { | 3931 } else { |
| 3989 Register temp = ToRegister(instr->temp()); | 3932 Register temp = ToRegister(instr->temp()); |
| 3990 __ Move(kScratchRegister, transition); | 3933 __ Move(kScratchRegister, transition); |
| 3991 __ movp(FieldOperand(object, HeapObject::kMapOffset), kScratchRegister); | 3934 __ movp(FieldOperand(object, HeapObject::kMapOffset), kScratchRegister); |
| 3992 // Update the write barrier for the map field. | 3935 // Update the write barrier for the map field. |
| 3993 __ RecordWriteField(object, | 3936 __ RecordWriteField(object, |
| 3994 HeapObject::kMapOffset, | 3937 HeapObject::kMapOffset, |
| 3995 kScratchRegister, | 3938 kScratchRegister, |
| 3996 temp, | 3939 temp, |
| 3997 kSaveFPRegs, | 3940 kSaveFPRegs, |
| 3998 OMIT_REMEMBERED_SET, | 3941 OMIT_REMEMBERED_SET, |
| 3999 OMIT_SMI_CHECK); | 3942 OMIT_SMI_CHECK); |
| 4000 } | 3943 } |
| 4001 } | 3944 } |
| 4002 | 3945 |
| 4003 // Do the store. | 3946 // Do the store. |
| 4004 SmiCheck check_needed = hinstr->value()->IsHeapObject() | |
| 4005 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; | |
| 4006 | |
| 4007 Register write_register = object; | 3947 Register write_register = object; |
| 4008 if (!access.IsInobject()) { | 3948 if (!access.IsInobject()) { |
| 4009 write_register = ToRegister(instr->temp()); | 3949 write_register = ToRegister(instr->temp()); |
| 4010 __ movp(write_register, FieldOperand(object, JSObject::kPropertiesOffset)); | 3950 __ movp(write_register, FieldOperand(object, JSObject::kPropertiesOffset)); |
| 4011 } | 3951 } |
| 4012 | 3952 |
| 4013 if (representation.IsSmi() && | 3953 if (representation.IsSmi() && |
| 4014 hinstr->value()->representation().IsInteger32()) { | 3954 hinstr->value()->representation().IsInteger32()) { |
| 4015 ASSERT(hinstr->store_mode() == STORE_TO_INITIALIZED_ENTRY); | 3955 ASSERT(hinstr->store_mode() == STORE_TO_INITIALIZED_ENTRY); |
| 3956 #ifdef DEBUG |
| 3957 Register scratch = kScratchRegister; |
| 3958 __ Load(scratch, FieldOperand(write_register, offset), representation); |
| 3959 __ AssertSmi(scratch); |
| 3960 #endif |
| 4016 // Store int value directly to upper half of the smi. | 3961 // Store int value directly to upper half of the smi. |
| 4017 STATIC_ASSERT(kSmiTag == 0); | 3962 STATIC_ASSERT(kSmiTag == 0); |
| 4018 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 32); | 3963 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 32); |
| 4019 offset += kPointerSize / 2; | 3964 offset += kPointerSize / 2; |
| 4020 representation = Representation::Integer32(); | 3965 representation = Representation::Integer32(); |
| 4021 } | 3966 } |
| 4022 | 3967 |
| 4023 Operand operand = FieldOperand(write_register, offset); | 3968 Operand operand = FieldOperand(write_register, offset); |
| 4024 | 3969 |
| 4025 if (instr->value()->IsRegister()) { | 3970 if (instr->value()->IsRegister()) { |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4145 int base_offset = instr->is_fixed_typed_array() | 4090 int base_offset = instr->is_fixed_typed_array() |
| 4146 ? FixedTypedArrayBase::kDataOffset - kHeapObjectTag | 4091 ? FixedTypedArrayBase::kDataOffset - kHeapObjectTag |
| 4147 : 0; | 4092 : 0; |
| 4148 Operand operand(BuildFastArrayOperand( | 4093 Operand operand(BuildFastArrayOperand( |
| 4149 instr->elements(), | 4094 instr->elements(), |
| 4150 key, | 4095 key, |
| 4151 elements_kind, | 4096 elements_kind, |
| 4152 base_offset, | 4097 base_offset, |
| 4153 instr->additional_index())); | 4098 instr->additional_index())); |
| 4154 | 4099 |
| 4155 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || | 4100 if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS || |
| 4156 elements_kind == FLOAT32_ELEMENTS) { | 4101 elements_kind == FLOAT32_ELEMENTS) { |
| 4157 XMMRegister value(ToDoubleRegister(instr->value())); | 4102 XMMRegister value(ToDoubleRegister(instr->value())); |
| 4158 __ cvtsd2ss(value, value); | 4103 __ cvtsd2ss(value, value); |
| 4159 __ movss(operand, value); | 4104 __ movss(operand, value); |
| 4160 } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS || | 4105 } else if (elements_kind == EXTERNAL_FLOAT64_ELEMENTS || |
| 4161 elements_kind == FLOAT64_ELEMENTS) { | 4106 elements_kind == FLOAT64_ELEMENTS) { |
| 4162 __ movsd(operand, ToDoubleRegister(instr->value())); | 4107 __ movsd(operand, ToDoubleRegister(instr->value())); |
| 4163 } else { | 4108 } else { |
| 4164 Register value(ToRegister(instr->value())); | 4109 Register value(ToRegister(instr->value())); |
| 4165 switch (elements_kind) { | 4110 switch (elements_kind) { |
| 4166 case EXTERNAL_PIXEL_ELEMENTS: | 4111 case EXTERNAL_UINT8_CLAMPED_ELEMENTS: |
| 4167 case EXTERNAL_BYTE_ELEMENTS: | 4112 case EXTERNAL_INT8_ELEMENTS: |
| 4168 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 4113 case EXTERNAL_UINT8_ELEMENTS: |
| 4169 case INT8_ELEMENTS: | 4114 case INT8_ELEMENTS: |
| 4170 case UINT8_ELEMENTS: | 4115 case UINT8_ELEMENTS: |
| 4171 case UINT8_CLAMPED_ELEMENTS: | 4116 case UINT8_CLAMPED_ELEMENTS: |
| 4172 __ movb(operand, value); | 4117 __ movb(operand, value); |
| 4173 break; | 4118 break; |
| 4174 case EXTERNAL_SHORT_ELEMENTS: | 4119 case EXTERNAL_INT16_ELEMENTS: |
| 4175 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 4120 case EXTERNAL_UINT16_ELEMENTS: |
| 4176 case INT16_ELEMENTS: | 4121 case INT16_ELEMENTS: |
| 4177 case UINT16_ELEMENTS: | 4122 case UINT16_ELEMENTS: |
| 4178 __ movw(operand, value); | 4123 __ movw(operand, value); |
| 4179 break; | 4124 break; |
| 4180 case EXTERNAL_INT_ELEMENTS: | 4125 case EXTERNAL_INT32_ELEMENTS: |
| 4181 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 4126 case EXTERNAL_UINT32_ELEMENTS: |
| 4182 case INT32_ELEMENTS: | 4127 case INT32_ELEMENTS: |
| 4183 case UINT32_ELEMENTS: | 4128 case UINT32_ELEMENTS: |
| 4184 __ movl(operand, value); | 4129 __ movl(operand, value); |
| 4185 break; | 4130 break; |
| 4186 case EXTERNAL_FLOAT_ELEMENTS: | 4131 case EXTERNAL_FLOAT32_ELEMENTS: |
| 4187 case EXTERNAL_DOUBLE_ELEMENTS: | 4132 case EXTERNAL_FLOAT64_ELEMENTS: |
| 4188 case FLOAT32_ELEMENTS: | 4133 case FLOAT32_ELEMENTS: |
| 4189 case FLOAT64_ELEMENTS: | 4134 case FLOAT64_ELEMENTS: |
| 4190 case FAST_ELEMENTS: | 4135 case FAST_ELEMENTS: |
| 4191 case FAST_SMI_ELEMENTS: | 4136 case FAST_SMI_ELEMENTS: |
| 4192 case FAST_DOUBLE_ELEMENTS: | 4137 case FAST_DOUBLE_ELEMENTS: |
| 4193 case FAST_HOLEY_ELEMENTS: | 4138 case FAST_HOLEY_ELEMENTS: |
| 4194 case FAST_HOLEY_SMI_ELEMENTS: | 4139 case FAST_HOLEY_SMI_ELEMENTS: |
| 4195 case FAST_HOLEY_DOUBLE_ELEMENTS: | 4140 case FAST_HOLEY_DOUBLE_ELEMENTS: |
| 4196 case DICTIONARY_ELEMENTS: | 4141 case DICTIONARY_ELEMENTS: |
| 4197 case NON_STRICT_ARGUMENTS_ELEMENTS: | 4142 case NON_STRICT_ARGUMENTS_ELEMENTS: |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4259 __ movsxlq(key_reg, key_reg); | 4204 __ movsxlq(key_reg, key_reg); |
| 4260 } | 4205 } |
| 4261 } | 4206 } |
| 4262 | 4207 |
| 4263 int offset = FixedArray::kHeaderSize - kHeapObjectTag; | 4208 int offset = FixedArray::kHeaderSize - kHeapObjectTag; |
| 4264 Representation representation = hinstr->value()->representation(); | 4209 Representation representation = hinstr->value()->representation(); |
| 4265 | 4210 |
| 4266 if (representation.IsInteger32()) { | 4211 if (representation.IsInteger32()) { |
| 4267 ASSERT(hinstr->store_mode() == STORE_TO_INITIALIZED_ENTRY); | 4212 ASSERT(hinstr->store_mode() == STORE_TO_INITIALIZED_ENTRY); |
| 4268 ASSERT(hinstr->elements_kind() == FAST_SMI_ELEMENTS); | 4213 ASSERT(hinstr->elements_kind() == FAST_SMI_ELEMENTS); |
| 4214 #ifdef DEBUG |
| 4215 Register scratch = kScratchRegister; |
| 4216 __ Load(scratch, |
| 4217 BuildFastArrayOperand(instr->elements(), |
| 4218 key, |
| 4219 FAST_ELEMENTS, |
| 4220 offset, |
| 4221 instr->additional_index()), |
| 4222 Representation::Smi()); |
| 4223 __ AssertSmi(scratch); |
| 4224 #endif |
| 4269 // Store int value directly to upper half of the smi. | 4225 // Store int value directly to upper half of the smi. |
| 4270 STATIC_ASSERT(kSmiTag == 0); | 4226 STATIC_ASSERT(kSmiTag == 0); |
| 4271 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 32); | 4227 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 32); |
| 4272 offset += kPointerSize / 2; | 4228 offset += kPointerSize / 2; |
| 4273 } | 4229 } |
| 4274 | 4230 |
| 4275 Operand operand = | 4231 Operand operand = |
| 4276 BuildFastArrayOperand(instr->elements(), | 4232 BuildFastArrayOperand(instr->elements(), |
| 4277 key, | 4233 key, |
| 4278 FAST_ELEMENTS, | 4234 FAST_ELEMENTS, |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4381 Register temp = ToRegister(instr->temp()); | 4337 Register temp = ToRegister(instr->temp()); |
| 4382 Label no_memento_found; | 4338 Label no_memento_found; |
| 4383 __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found); | 4339 __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found); |
| 4384 DeoptimizeIf(equal, instr->environment()); | 4340 DeoptimizeIf(equal, instr->environment()); |
| 4385 __ bind(&no_memento_found); | 4341 __ bind(&no_memento_found); |
| 4386 } | 4342 } |
| 4387 | 4343 |
| 4388 | 4344 |
| 4389 void LCodeGen::DoStringAdd(LStringAdd* instr) { | 4345 void LCodeGen::DoStringAdd(LStringAdd* instr) { |
| 4390 ASSERT(ToRegister(instr->context()).is(rsi)); | 4346 ASSERT(ToRegister(instr->context()).is(rsi)); |
| 4391 if (FLAG_new_string_add) { | 4347 ASSERT(ToRegister(instr->left()).is(rdx)); |
| 4392 ASSERT(ToRegister(instr->left()).is(rdx)); | 4348 ASSERT(ToRegister(instr->right()).is(rax)); |
| 4393 ASSERT(ToRegister(instr->right()).is(rax)); | 4349 StringAddStub stub(instr->hydrogen()->flags(), |
| 4394 NewStringAddStub stub(instr->hydrogen()->flags(), | 4350 instr->hydrogen()->pretenure_flag()); |
| 4395 isolate()->heap()->GetPretenureMode()); | 4351 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 4396 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | |
| 4397 } else { | |
| 4398 EmitPushTaggedOperand(instr->left()); | |
| 4399 EmitPushTaggedOperand(instr->right()); | |
| 4400 StringAddStub stub(instr->hydrogen()->flags()); | |
| 4401 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | |
| 4402 } | |
| 4403 } | 4352 } |
| 4404 | 4353 |
| 4405 | 4354 |
| 4406 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { | 4355 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { |
| 4407 class DeferredStringCharCodeAt V8_FINAL : public LDeferredCode { | 4356 class DeferredStringCharCodeAt V8_FINAL : public LDeferredCode { |
| 4408 public: | 4357 public: |
| 4409 DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr) | 4358 DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr) |
| 4410 : LDeferredCode(codegen), instr_(instr) { } | 4359 : LDeferredCode(codegen), instr_(instr) { } |
| 4411 virtual void Generate() V8_OVERRIDE { | 4360 virtual void Generate() V8_OVERRIDE { |
| 4412 codegen()->DoDeferredStringCharCodeAt(instr_); | 4361 codegen()->DoDeferredStringCharCodeAt(instr_); |
| (...skipping 722 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5135 ASSERT(!instr->hydrogen()->IsOldDataSpaceAllocation()); | 5084 ASSERT(!instr->hydrogen()->IsOldDataSpaceAllocation()); |
| 5136 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); | 5085 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); |
| 5137 flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_POINTER_SPACE); | 5086 flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_POINTER_SPACE); |
| 5138 } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) { | 5087 } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) { |
| 5139 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); | 5088 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); |
| 5140 flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_DATA_SPACE); | 5089 flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_DATA_SPACE); |
| 5141 } | 5090 } |
| 5142 | 5091 |
| 5143 if (instr->size()->IsConstantOperand()) { | 5092 if (instr->size()->IsConstantOperand()) { |
| 5144 int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); | 5093 int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); |
| 5145 __ Allocate(size, result, temp, no_reg, deferred->entry(), flags); | 5094 if (size <= Page::kMaxRegularHeapObjectSize) { |
| 5095 __ Allocate(size, result, temp, no_reg, deferred->entry(), flags); |
| 5096 } else { |
| 5097 __ jmp(deferred->entry()); |
| 5098 } |
| 5146 } else { | 5099 } else { |
| 5147 Register size = ToRegister(instr->size()); | 5100 Register size = ToRegister(instr->size()); |
| 5148 __ Allocate(size, result, temp, no_reg, deferred->entry(), flags); | 5101 __ Allocate(size, result, temp, no_reg, deferred->entry(), flags); |
| 5149 } | 5102 } |
| 5150 | 5103 |
| 5151 __ bind(deferred->exit()); | 5104 __ bind(deferred->exit()); |
| 5152 | 5105 |
| 5153 if (instr->hydrogen()->MustPrefillWithFiller()) { | 5106 if (instr->hydrogen()->MustPrefillWithFiller()) { |
| 5154 if (instr->size()->IsConstantOperand()) { | 5107 if (instr->size()->IsConstantOperand()) { |
| 5155 int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); | 5108 int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); |
| (...skipping 480 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5636 FixedArray::kHeaderSize - kPointerSize)); | 5589 FixedArray::kHeaderSize - kPointerSize)); |
| 5637 __ bind(&done); | 5590 __ bind(&done); |
| 5638 } | 5591 } |
| 5639 | 5592 |
| 5640 | 5593 |
| 5641 #undef __ | 5594 #undef __ |
| 5642 | 5595 |
| 5643 } } // namespace v8::internal | 5596 } } // namespace v8::internal |
| 5644 | 5597 |
| 5645 #endif // V8_TARGET_ARCH_X64 | 5598 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |