| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 181 __ j(not_zero, &align_loop, Label::kNear); | 181 __ j(not_zero, &align_loop, Label::kNear); |
| 182 __ mov(Operand(ebx, 0), Immediate(kAlignmentZapValue)); | 182 __ mov(Operand(ebx, 0), Immediate(kAlignmentZapValue)); |
| 183 __ bind(&do_not_pad); | 183 __ bind(&do_not_pad); |
| 184 } | 184 } |
| 185 } | 185 } |
| 186 | 186 |
| 187 info()->set_prologue_offset(masm_->pc_offset()); | 187 info()->set_prologue_offset(masm_->pc_offset()); |
| 188 if (NeedsEagerFrame()) { | 188 if (NeedsEagerFrame()) { |
| 189 ASSERT(!frame_is_built_); | 189 ASSERT(!frame_is_built_); |
| 190 frame_is_built_ = true; | 190 frame_is_built_ = true; |
| 191 __ push(ebp); // Caller's frame pointer. | 191 __ Prologue(info()->IsStub() ? BUILD_STUB_FRAME : BUILD_FUNCTION_FRAME); |
| 192 __ mov(ebp, esp); | |
| 193 info()->AddNoFrameRange(0, masm_->pc_offset()); | 192 info()->AddNoFrameRange(0, masm_->pc_offset()); |
| 194 __ push(esi); // Callee's context. | |
| 195 if (info()->IsStub()) { | |
| 196 __ push(Immediate(Smi::FromInt(StackFrame::STUB))); | |
| 197 } else { | |
| 198 __ push(edi); // Callee's JS function. | |
| 199 } | |
| 200 } | 193 } |
| 201 | 194 |
| 202 if (info()->IsOptimizing() && | 195 if (info()->IsOptimizing() && |
| 203 dynamic_frame_alignment_ && | 196 dynamic_frame_alignment_ && |
| 204 FLAG_debug_code) { | 197 FLAG_debug_code) { |
| 205 __ test(esp, Immediate(kPointerSize)); | 198 __ test(esp, Immediate(kPointerSize)); |
| 206 __ Assert(zero, kFrameIsExpectedToBeAligned); | 199 __ Assert(zero, kFrameIsExpectedToBeAligned); |
| 207 } | 200 } |
| 208 | 201 |
| 209 // Reserve space for the stack slots needed by the code. | 202 // Reserve space for the stack slots needed by the code. |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 250 } | 243 } |
| 251 } | 244 } |
| 252 | 245 |
| 253 if (info()->saves_caller_doubles() && CpuFeatures::IsSupported(SSE2)) { | 246 if (info()->saves_caller_doubles() && CpuFeatures::IsSupported(SSE2)) { |
| 254 Comment(";;; Save clobbered callee double registers"); | 247 Comment(";;; Save clobbered callee double registers"); |
| 255 CpuFeatureScope scope(masm(), SSE2); | 248 CpuFeatureScope scope(masm(), SSE2); |
| 256 int count = 0; | 249 int count = 0; |
| 257 BitVector* doubles = chunk()->allocated_double_registers(); | 250 BitVector* doubles = chunk()->allocated_double_registers(); |
| 258 BitVector::Iterator save_iterator(doubles); | 251 BitVector::Iterator save_iterator(doubles); |
| 259 while (!save_iterator.Done()) { | 252 while (!save_iterator.Done()) { |
| 260 __ movdbl(MemOperand(esp, count * kDoubleSize), | 253 __ movsd(MemOperand(esp, count * kDoubleSize), |
| 261 XMMRegister::FromAllocationIndex(save_iterator.Current())); | 254 XMMRegister::FromAllocationIndex(save_iterator.Current())); |
| 262 save_iterator.Advance(); | 255 save_iterator.Advance(); |
| 263 count++; | 256 count++; |
| 264 } | 257 } |
| 265 } | 258 } |
| 266 } | 259 } |
| 267 | 260 |
| 268 // Possibly allocate a local context. | 261 // Possibly allocate a local context. |
| 269 int heap_slots = info_->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; | 262 int heap_slots = info_->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; |
| 270 if (heap_slots > 0) { | 263 if (heap_slots > 0) { |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 440 | 433 |
| 441 | 434 |
| 442 bool LCodeGen::GenerateDeferredCode() { | 435 bool LCodeGen::GenerateDeferredCode() { |
| 443 ASSERT(is_generating()); | 436 ASSERT(is_generating()); |
| 444 if (deferred_.length() > 0) { | 437 if (deferred_.length() > 0) { |
| 445 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { | 438 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { |
| 446 LDeferredCode* code = deferred_[i]; | 439 LDeferredCode* code = deferred_[i]; |
| 447 X87Stack copy(code->x87_stack()); | 440 X87Stack copy(code->x87_stack()); |
| 448 x87_stack_ = copy; | 441 x87_stack_ = copy; |
| 449 | 442 |
| 450 int pos = instructions_->at(code->instruction_index())->position(); | 443 HValue* value = |
| 451 RecordAndUpdatePosition(pos); | 444 instructions_->at(code->instruction_index())->hydrogen_value(); |
| 445 RecordAndWritePosition(value->position()); |
| 452 | 446 |
| 453 Comment(";;; <@%d,#%d> " | 447 Comment(";;; <@%d,#%d> " |
| 454 "-------------------- Deferred %s --------------------", | 448 "-------------------- Deferred %s --------------------", |
| 455 code->instruction_index(), | 449 code->instruction_index(), |
| 456 code->instr()->hydrogen_value()->id(), | 450 code->instr()->hydrogen_value()->id(), |
| 457 code->instr()->Mnemonic()); | 451 code->instr()->Mnemonic()); |
| 458 __ bind(code->entry()); | 452 __ bind(code->entry()); |
| 459 if (NeedsDeferredFrame()) { | 453 if (NeedsDeferredFrame()) { |
| 460 Comment(";;; Build frame"); | 454 Comment(";;; Build frame"); |
| 461 ASSERT(!frame_is_built_); | 455 ASSERT(!frame_is_built_); |
| (...skipping 466 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 928 UNREACHABLE(); | 922 UNREACHABLE(); |
| 929 } | 923 } |
| 930 } | 924 } |
| 931 | 925 |
| 932 | 926 |
| 933 void LCodeGen::CallCodeGeneric(Handle<Code> code, | 927 void LCodeGen::CallCodeGeneric(Handle<Code> code, |
| 934 RelocInfo::Mode mode, | 928 RelocInfo::Mode mode, |
| 935 LInstruction* instr, | 929 LInstruction* instr, |
| 936 SafepointMode safepoint_mode) { | 930 SafepointMode safepoint_mode) { |
| 937 ASSERT(instr != NULL); | 931 ASSERT(instr != NULL); |
| 938 LPointerMap* pointers = instr->pointer_map(); | |
| 939 RecordPosition(pointers->position()); | |
| 940 __ call(code, mode); | 932 __ call(code, mode); |
| 941 RecordSafepointWithLazyDeopt(instr, safepoint_mode); | 933 RecordSafepointWithLazyDeopt(instr, safepoint_mode); |
| 942 | 934 |
| 943 // Signal that we don't inline smi code before these stubs in the | 935 // Signal that we don't inline smi code before these stubs in the |
| 944 // optimizing code generator. | 936 // optimizing code generator. |
| 945 if (code->kind() == Code::BINARY_OP_IC || | 937 if (code->kind() == Code::BINARY_OP_IC || |
| 946 code->kind() == Code::COMPARE_IC) { | 938 code->kind() == Code::COMPARE_IC) { |
| 947 __ nop(); | 939 __ nop(); |
| 948 } | 940 } |
| 949 } | 941 } |
| 950 | 942 |
| 951 | 943 |
| 952 void LCodeGen::CallCode(Handle<Code> code, | 944 void LCodeGen::CallCode(Handle<Code> code, |
| 953 RelocInfo::Mode mode, | 945 RelocInfo::Mode mode, |
| 954 LInstruction* instr) { | 946 LInstruction* instr) { |
| 955 CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT); | 947 CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT); |
| 956 } | 948 } |
| 957 | 949 |
| 958 | 950 |
| 959 void LCodeGen::CallRuntime(const Runtime::Function* fun, | 951 void LCodeGen::CallRuntime(const Runtime::Function* fun, |
| 960 int argc, | 952 int argc, |
| 961 LInstruction* instr, | 953 LInstruction* instr, |
| 962 SaveFPRegsMode save_doubles) { | 954 SaveFPRegsMode save_doubles) { |
| 963 ASSERT(instr != NULL); | 955 ASSERT(instr != NULL); |
| 964 ASSERT(instr->HasPointerMap()); | 956 ASSERT(instr->HasPointerMap()); |
| 965 LPointerMap* pointers = instr->pointer_map(); | |
| 966 RecordPosition(pointers->position()); | |
| 967 | 957 |
| 968 __ CallRuntime(fun, argc, save_doubles); | 958 __ CallRuntime(fun, argc, save_doubles); |
| 969 | 959 |
| 970 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); | 960 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); |
| 971 | 961 |
| 972 ASSERT(info()->is_calling()); | 962 ASSERT(info()->is_calling()); |
| 973 } | 963 } |
| 974 | 964 |
| 975 | 965 |
| 976 void LCodeGen::LoadContextFromDeferred(LOperand* context) { | 966 void LCodeGen::LoadContextFromDeferred(LOperand* context) { |
| (...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1249 } | 1239 } |
| 1250 | 1240 |
| 1251 | 1241 |
| 1252 void LCodeGen::RecordSafepoint(LPointerMap* pointers, | 1242 void LCodeGen::RecordSafepoint(LPointerMap* pointers, |
| 1253 Safepoint::DeoptMode mode) { | 1243 Safepoint::DeoptMode mode) { |
| 1254 RecordSafepoint(pointers, Safepoint::kSimple, 0, mode); | 1244 RecordSafepoint(pointers, Safepoint::kSimple, 0, mode); |
| 1255 } | 1245 } |
| 1256 | 1246 |
| 1257 | 1247 |
| 1258 void LCodeGen::RecordSafepoint(Safepoint::DeoptMode mode) { | 1248 void LCodeGen::RecordSafepoint(Safepoint::DeoptMode mode) { |
| 1259 LPointerMap empty_pointers(RelocInfo::kNoPosition, zone()); | 1249 LPointerMap empty_pointers(zone()); |
| 1260 RecordSafepoint(&empty_pointers, mode); | 1250 RecordSafepoint(&empty_pointers, mode); |
| 1261 } | 1251 } |
| 1262 | 1252 |
| 1263 | 1253 |
| 1264 void LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers, | 1254 void LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers, |
| 1265 int arguments, | 1255 int arguments, |
| 1266 Safepoint::DeoptMode mode) { | 1256 Safepoint::DeoptMode mode) { |
| 1267 RecordSafepoint(pointers, Safepoint::kWithRegisters, arguments, mode); | 1257 RecordSafepoint(pointers, Safepoint::kWithRegisters, arguments, mode); |
| 1268 } | 1258 } |
| 1269 | 1259 |
| 1270 | 1260 |
| 1271 void LCodeGen::RecordPosition(int position) { | 1261 void LCodeGen::RecordAndWritePosition(int position) { |
| 1272 if (position == RelocInfo::kNoPosition) return; | 1262 if (position == RelocInfo::kNoPosition) return; |
| 1273 masm()->positions_recorder()->RecordPosition(position); | 1263 masm()->positions_recorder()->RecordPosition(position); |
| 1264 masm()->positions_recorder()->WriteRecordedPositions(); |
| 1274 } | 1265 } |
| 1275 | 1266 |
| 1276 | 1267 |
| 1277 void LCodeGen::RecordAndUpdatePosition(int position) { | |
| 1278 if (position >= 0 && position != old_position_) { | |
| 1279 masm()->positions_recorder()->RecordPosition(position); | |
| 1280 old_position_ = position; | |
| 1281 } | |
| 1282 } | |
| 1283 | |
| 1284 | |
| 1285 static const char* LabelType(LLabel* label) { | 1268 static const char* LabelType(LLabel* label) { |
| 1286 if (label->is_loop_header()) return " (loop header)"; | 1269 if (label->is_loop_header()) return " (loop header)"; |
| 1287 if (label->is_osr_entry()) return " (OSR entry)"; | 1270 if (label->is_osr_entry()) return " (OSR entry)"; |
| 1288 return ""; | 1271 return ""; |
| 1289 } | 1272 } |
| 1290 | 1273 |
| 1291 | 1274 |
| 1292 void LCodeGen::DoLabel(LLabel* label) { | 1275 void LCodeGen::DoLabel(LLabel* label) { |
| 1293 Comment(";;; <@%d,#%d> -------------------- B%d%s --------------------", | 1276 Comment(";;; <@%d,#%d> -------------------- B%d%s --------------------", |
| 1294 current_instruction_, | 1277 current_instruction_, |
| (...skipping 931 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2226 break; | 2209 break; |
| 2227 case Token::DIV: | 2210 case Token::DIV: |
| 2228 __ divsd(left, right); | 2211 __ divsd(left, right); |
| 2229 // Don't delete this mov. It may improve performance on some CPUs, | 2212 // Don't delete this mov. It may improve performance on some CPUs, |
| 2230 // when there is a mulsd depending on the result | 2213 // when there is a mulsd depending on the result |
| 2231 __ movaps(left, left); | 2214 __ movaps(left, left); |
| 2232 break; | 2215 break; |
| 2233 case Token::MOD: { | 2216 case Token::MOD: { |
| 2234 // Pass two doubles as arguments on the stack. | 2217 // Pass two doubles as arguments on the stack. |
| 2235 __ PrepareCallCFunction(4, eax); | 2218 __ PrepareCallCFunction(4, eax); |
| 2236 __ movdbl(Operand(esp, 0 * kDoubleSize), left); | 2219 __ movsd(Operand(esp, 0 * kDoubleSize), left); |
| 2237 __ movdbl(Operand(esp, 1 * kDoubleSize), right); | 2220 __ movsd(Operand(esp, 1 * kDoubleSize), right); |
| 2238 __ CallCFunction( | 2221 __ CallCFunction( |
| 2239 ExternalReference::double_fp_operation(Token::MOD, isolate()), | 2222 ExternalReference::double_fp_operation(Token::MOD, isolate()), |
| 2240 4); | 2223 4); |
| 2241 | 2224 |
| 2242 // Return value is in st(0) on ia32. | 2225 // Return value is in st(0) on ia32. |
| 2243 // Store it into the result register. | 2226 // Store it into the result register. |
| 2244 __ sub(Operand(esp), Immediate(kDoubleSize)); | 2227 __ sub(Operand(esp), Immediate(kDoubleSize)); |
| 2245 __ fstp_d(Operand(esp, 0)); | 2228 __ fstp_d(Operand(esp, 0)); |
| 2246 __ movdbl(result, Operand(esp, 0)); | 2229 __ movsd(result, Operand(esp, 0)); |
| 2247 __ add(Operand(esp), Immediate(kDoubleSize)); | 2230 __ add(Operand(esp), Immediate(kDoubleSize)); |
| 2248 break; | 2231 break; |
| 2249 } | 2232 } |
| 2250 default: | 2233 default: |
| 2251 UNREACHABLE(); | 2234 UNREACHABLE(); |
| 2252 break; | 2235 break; |
| 2253 } | 2236 } |
| 2254 } else { | 2237 } else { |
| 2255 X87Register left = ToX87Register(instr->left()); | 2238 X87Register left = ToX87Register(instr->left()); |
| 2256 X87Register right = ToX87Register(instr->right()); | 2239 X87Register right = ToX87Register(instr->right()); |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2496 } | 2479 } |
| 2497 | 2480 |
| 2498 | 2481 |
| 2499 Condition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) { | 2482 Condition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) { |
| 2500 Condition cond = no_condition; | 2483 Condition cond = no_condition; |
| 2501 switch (op) { | 2484 switch (op) { |
| 2502 case Token::EQ: | 2485 case Token::EQ: |
| 2503 case Token::EQ_STRICT: | 2486 case Token::EQ_STRICT: |
| 2504 cond = equal; | 2487 cond = equal; |
| 2505 break; | 2488 break; |
| 2489 case Token::NE: |
| 2490 case Token::NE_STRICT: |
| 2491 cond = not_equal; |
| 2492 break; |
| 2506 case Token::LT: | 2493 case Token::LT: |
| 2507 cond = is_unsigned ? below : less; | 2494 cond = is_unsigned ? below : less; |
| 2508 break; | 2495 break; |
| 2509 case Token::GT: | 2496 case Token::GT: |
| 2510 cond = is_unsigned ? above : greater; | 2497 cond = is_unsigned ? above : greater; |
| 2511 break; | 2498 break; |
| 2512 case Token::LTE: | 2499 case Token::LTE: |
| 2513 cond = is_unsigned ? below_equal : less_equal; | 2500 cond = is_unsigned ? below_equal : less_equal; |
| 2514 break; | 2501 break; |
| 2515 case Token::GTE: | 2502 case Token::GTE: |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2606 __ fstp(0); | 2593 __ fstp(0); |
| 2607 EmitFalseBranch(instr, no_condition); | 2594 EmitFalseBranch(instr, no_condition); |
| 2608 __ bind(&ok); | 2595 __ bind(&ok); |
| 2609 } | 2596 } |
| 2610 | 2597 |
| 2611 | 2598 |
| 2612 __ sub(esp, Immediate(kDoubleSize)); | 2599 __ sub(esp, Immediate(kDoubleSize)); |
| 2613 if (use_sse2) { | 2600 if (use_sse2) { |
| 2614 CpuFeatureScope scope(masm(), SSE2); | 2601 CpuFeatureScope scope(masm(), SSE2); |
| 2615 XMMRegister input_reg = ToDoubleRegister(instr->object()); | 2602 XMMRegister input_reg = ToDoubleRegister(instr->object()); |
| 2616 __ movdbl(MemOperand(esp, 0), input_reg); | 2603 __ movsd(MemOperand(esp, 0), input_reg); |
| 2617 } else { | 2604 } else { |
| 2618 __ fstp_d(MemOperand(esp, 0)); | 2605 __ fstp_d(MemOperand(esp, 0)); |
| 2619 } | 2606 } |
| 2620 | 2607 |
| 2621 __ add(esp, Immediate(kDoubleSize)); | 2608 __ add(esp, Immediate(kDoubleSize)); |
| 2622 int offset = sizeof(kHoleNanUpper32); | 2609 int offset = sizeof(kHoleNanUpper32); |
| 2623 __ cmp(MemOperand(esp, -offset), Immediate(kHoleNanUpper32)); | 2610 __ cmp(MemOperand(esp, -offset), Immediate(kHoleNanUpper32)); |
| 2624 EmitBranch(instr, equal); | 2611 EmitBranch(instr, equal); |
| 2625 } | 2612 } |
| 2626 | 2613 |
| (...skipping 441 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3068 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 3055 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 3069 __ CallRuntime(Runtime::kTraceExit, 1); | 3056 __ CallRuntime(Runtime::kTraceExit, 1); |
| 3070 } | 3057 } |
| 3071 if (info()->saves_caller_doubles() && CpuFeatures::IsSupported(SSE2)) { | 3058 if (info()->saves_caller_doubles() && CpuFeatures::IsSupported(SSE2)) { |
| 3072 ASSERT(NeedsEagerFrame()); | 3059 ASSERT(NeedsEagerFrame()); |
| 3073 CpuFeatureScope scope(masm(), SSE2); | 3060 CpuFeatureScope scope(masm(), SSE2); |
| 3074 BitVector* doubles = chunk()->allocated_double_registers(); | 3061 BitVector* doubles = chunk()->allocated_double_registers(); |
| 3075 BitVector::Iterator save_iterator(doubles); | 3062 BitVector::Iterator save_iterator(doubles); |
| 3076 int count = 0; | 3063 int count = 0; |
| 3077 while (!save_iterator.Done()) { | 3064 while (!save_iterator.Done()) { |
| 3078 __ movdbl(XMMRegister::FromAllocationIndex(save_iterator.Current()), | 3065 __ movsd(XMMRegister::FromAllocationIndex(save_iterator.Current()), |
| 3079 MemOperand(esp, count * kDoubleSize)); | 3066 MemOperand(esp, count * kDoubleSize)); |
| 3080 save_iterator.Advance(); | 3067 save_iterator.Advance(); |
| 3081 count++; | 3068 count++; |
| 3082 } | 3069 } |
| 3083 } | 3070 } |
| 3084 if (dynamic_frame_alignment_) { | 3071 if (dynamic_frame_alignment_) { |
| 3085 // Fetch the state of the dynamic frame alignment. | 3072 // Fetch the state of the dynamic frame alignment. |
| 3086 __ mov(edx, Operand(ebp, | 3073 __ mov(edx, Operand(ebp, |
| 3087 JavaScriptFrameConstants::kDynamicAlignmentStateOffset)); | 3074 JavaScriptFrameConstants::kDynamicAlignmentStateOffset)); |
| 3088 } | 3075 } |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3236 } | 3223 } |
| 3237 return; | 3224 return; |
| 3238 } | 3225 } |
| 3239 | 3226 |
| 3240 Register object = ToRegister(instr->object()); | 3227 Register object = ToRegister(instr->object()); |
| 3241 if (FLAG_track_double_fields && | 3228 if (FLAG_track_double_fields && |
| 3242 instr->hydrogen()->representation().IsDouble()) { | 3229 instr->hydrogen()->representation().IsDouble()) { |
| 3243 if (CpuFeatures::IsSupported(SSE2)) { | 3230 if (CpuFeatures::IsSupported(SSE2)) { |
| 3244 CpuFeatureScope scope(masm(), SSE2); | 3231 CpuFeatureScope scope(masm(), SSE2); |
| 3245 XMMRegister result = ToDoubleRegister(instr->result()); | 3232 XMMRegister result = ToDoubleRegister(instr->result()); |
| 3246 __ movdbl(result, FieldOperand(object, offset)); | 3233 __ movsd(result, FieldOperand(object, offset)); |
| 3247 } else { | 3234 } else { |
| 3248 X87Mov(ToX87Register(instr->result()), FieldOperand(object, offset)); | 3235 X87Mov(ToX87Register(instr->result()), FieldOperand(object, offset)); |
| 3249 } | 3236 } |
| 3250 return; | 3237 return; |
| 3251 } | 3238 } |
| 3252 | 3239 |
| 3253 Register result = ToRegister(instr->result()); | 3240 Register result = ToRegister(instr->result()); |
| 3254 if (!access.IsInobject()) { | 3241 if (!access.IsInobject()) { |
| 3255 __ mov(result, FieldOperand(object, JSObject::kPropertiesOffset)); | 3242 __ mov(result, FieldOperand(object, JSObject::kPropertiesOffset)); |
| 3256 object = result; | 3243 object = result; |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3390 CpuFeatureScope scope(masm(), SSE2); | 3377 CpuFeatureScope scope(masm(), SSE2); |
| 3391 XMMRegister result(ToDoubleRegister(instr->result())); | 3378 XMMRegister result(ToDoubleRegister(instr->result())); |
| 3392 __ movss(result, operand); | 3379 __ movss(result, operand); |
| 3393 __ cvtss2sd(result, result); | 3380 __ cvtss2sd(result, result); |
| 3394 } else { | 3381 } else { |
| 3395 X87Mov(ToX87Register(instr->result()), operand, kX87FloatOperand); | 3382 X87Mov(ToX87Register(instr->result()), operand, kX87FloatOperand); |
| 3396 } | 3383 } |
| 3397 } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { | 3384 } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { |
| 3398 if (CpuFeatures::IsSupported(SSE2)) { | 3385 if (CpuFeatures::IsSupported(SSE2)) { |
| 3399 CpuFeatureScope scope(masm(), SSE2); | 3386 CpuFeatureScope scope(masm(), SSE2); |
| 3400 __ movdbl(ToDoubleRegister(instr->result()), operand); | 3387 __ movsd(ToDoubleRegister(instr->result()), operand); |
| 3401 } else { | 3388 } else { |
| 3402 X87Mov(ToX87Register(instr->result()), operand); | 3389 X87Mov(ToX87Register(instr->result()), operand); |
| 3403 } | 3390 } |
| 3404 } else { | 3391 } else { |
| 3405 Register result(ToRegister(instr->result())); | 3392 Register result(ToRegister(instr->result())); |
| 3406 switch (elements_kind) { | 3393 switch (elements_kind) { |
| 3407 case EXTERNAL_BYTE_ELEMENTS: | 3394 case EXTERNAL_BYTE_ELEMENTS: |
| 3408 __ movsx_b(result, operand); | 3395 __ movsx_b(result, operand); |
| 3409 break; | 3396 break; |
| 3410 case EXTERNAL_PIXEL_ELEMENTS: | 3397 case EXTERNAL_PIXEL_ELEMENTS: |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3461 Operand double_load_operand = BuildFastArrayOperand( | 3448 Operand double_load_operand = BuildFastArrayOperand( |
| 3462 instr->elements(), | 3449 instr->elements(), |
| 3463 instr->key(), | 3450 instr->key(), |
| 3464 instr->hydrogen()->key()->representation(), | 3451 instr->hydrogen()->key()->representation(), |
| 3465 FAST_DOUBLE_ELEMENTS, | 3452 FAST_DOUBLE_ELEMENTS, |
| 3466 FixedDoubleArray::kHeaderSize - kHeapObjectTag, | 3453 FixedDoubleArray::kHeaderSize - kHeapObjectTag, |
| 3467 instr->additional_index()); | 3454 instr->additional_index()); |
| 3468 if (CpuFeatures::IsSupported(SSE2)) { | 3455 if (CpuFeatures::IsSupported(SSE2)) { |
| 3469 CpuFeatureScope scope(masm(), SSE2); | 3456 CpuFeatureScope scope(masm(), SSE2); |
| 3470 XMMRegister result = ToDoubleRegister(instr->result()); | 3457 XMMRegister result = ToDoubleRegister(instr->result()); |
| 3471 __ movdbl(result, double_load_operand); | 3458 __ movsd(result, double_load_operand); |
| 3472 } else { | 3459 } else { |
| 3473 X87Mov(ToX87Register(instr->result()), double_load_operand); | 3460 X87Mov(ToX87Register(instr->result()), double_load_operand); |
| 3474 } | 3461 } |
| 3475 } | 3462 } |
| 3476 | 3463 |
| 3477 | 3464 |
| 3478 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { | 3465 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { |
| 3479 Register result = ToRegister(instr->result()); | 3466 Register result = ToRegister(instr->result()); |
| 3480 | 3467 |
| 3481 // Load the result. | 3468 // Load the result. |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3678 __ j(zero, &invoke, Label::kNear); | 3665 __ j(zero, &invoke, Label::kNear); |
| 3679 __ bind(&loop); | 3666 __ bind(&loop); |
| 3680 __ push(Operand(elements, length, times_pointer_size, 1 * kPointerSize)); | 3667 __ push(Operand(elements, length, times_pointer_size, 1 * kPointerSize)); |
| 3681 __ dec(length); | 3668 __ dec(length); |
| 3682 __ j(not_zero, &loop); | 3669 __ j(not_zero, &loop); |
| 3683 | 3670 |
| 3684 // Invoke the function. | 3671 // Invoke the function. |
| 3685 __ bind(&invoke); | 3672 __ bind(&invoke); |
| 3686 ASSERT(instr->HasPointerMap()); | 3673 ASSERT(instr->HasPointerMap()); |
| 3687 LPointerMap* pointers = instr->pointer_map(); | 3674 LPointerMap* pointers = instr->pointer_map(); |
| 3688 RecordPosition(pointers->position()); | |
| 3689 SafepointGenerator safepoint_generator( | 3675 SafepointGenerator safepoint_generator( |
| 3690 this, pointers, Safepoint::kLazyDeopt); | 3676 this, pointers, Safepoint::kLazyDeopt); |
| 3691 ParameterCount actual(eax); | 3677 ParameterCount actual(eax); |
| 3692 __ InvokeFunction(function, actual, CALL_FUNCTION, | 3678 __ InvokeFunction(function, actual, CALL_FUNCTION, |
| 3693 safepoint_generator, CALL_AS_METHOD); | 3679 safepoint_generator, CALL_AS_METHOD); |
| 3694 } | 3680 } |
| 3695 | 3681 |
| 3696 | 3682 |
| 3697 void LCodeGen::DoDebugBreak(LDebugBreak* instr) { | 3683 void LCodeGen::DoDebugBreak(LDebugBreak* instr) { |
| 3698 __ int3(); | 3684 __ int3(); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3763 int formal_parameter_count, | 3749 int formal_parameter_count, |
| 3764 int arity, | 3750 int arity, |
| 3765 LInstruction* instr, | 3751 LInstruction* instr, |
| 3766 CallKind call_kind, | 3752 CallKind call_kind, |
| 3767 EDIState edi_state) { | 3753 EDIState edi_state) { |
| 3768 bool dont_adapt_arguments = | 3754 bool dont_adapt_arguments = |
| 3769 formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel; | 3755 formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel; |
| 3770 bool can_invoke_directly = | 3756 bool can_invoke_directly = |
| 3771 dont_adapt_arguments || formal_parameter_count == arity; | 3757 dont_adapt_arguments || formal_parameter_count == arity; |
| 3772 | 3758 |
| 3773 LPointerMap* pointers = instr->pointer_map(); | |
| 3774 RecordPosition(pointers->position()); | |
| 3775 | |
| 3776 if (can_invoke_directly) { | 3759 if (can_invoke_directly) { |
| 3777 if (edi_state == EDI_UNINITIALIZED) { | 3760 if (edi_state == EDI_UNINITIALIZED) { |
| 3778 __ LoadHeapObject(edi, function); | 3761 __ LoadHeapObject(edi, function); |
| 3779 } | 3762 } |
| 3780 | 3763 |
| 3781 // Change context. | 3764 // Change context. |
| 3782 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); | 3765 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); |
| 3783 | 3766 |
| 3784 // Set eax to arguments count if adaption is not needed. Assumes that eax | 3767 // Set eax to arguments count if adaption is not needed. Assumes that eax |
| 3785 // is available to write to at this point. | 3768 // is available to write to at this point. |
| 3786 if (dont_adapt_arguments) { | 3769 if (dont_adapt_arguments) { |
| 3787 __ mov(eax, arity); | 3770 __ mov(eax, arity); |
| 3788 } | 3771 } |
| 3789 | 3772 |
| 3790 // Invoke function directly. | 3773 // Invoke function directly. |
| 3791 __ SetCallKind(ecx, call_kind); | 3774 __ SetCallKind(ecx, call_kind); |
| 3792 if (function.is_identical_to(info()->closure())) { | 3775 if (function.is_identical_to(info()->closure())) { |
| 3793 __ CallSelf(); | 3776 __ CallSelf(); |
| 3794 } else { | 3777 } else { |
| 3795 __ call(FieldOperand(edi, JSFunction::kCodeEntryOffset)); | 3778 __ call(FieldOperand(edi, JSFunction::kCodeEntryOffset)); |
| 3796 } | 3779 } |
| 3797 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); | 3780 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); |
| 3798 } else { | 3781 } else { |
| 3799 // We need to adapt arguments. | 3782 // We need to adapt arguments. |
| 3783 LPointerMap* pointers = instr->pointer_map(); |
| 3800 SafepointGenerator generator( | 3784 SafepointGenerator generator( |
| 3801 this, pointers, Safepoint::kLazyDeopt); | 3785 this, pointers, Safepoint::kLazyDeopt); |
| 3802 ParameterCount count(arity); | 3786 ParameterCount count(arity); |
| 3803 ParameterCount expected(formal_parameter_count); | 3787 ParameterCount expected(formal_parameter_count); |
| 3804 __ InvokeFunction( | 3788 __ InvokeFunction( |
| 3805 function, expected, count, CALL_FUNCTION, generator, call_kind); | 3789 function, expected, count, CALL_FUNCTION, generator, call_kind); |
| 3806 } | 3790 } |
| 3807 } | 3791 } |
| 3808 | 3792 |
| 3809 | 3793 |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3984 CpuFeatureScope scope(masm(), SSE2); | 3968 CpuFeatureScope scope(masm(), SSE2); |
| 3985 Register output_reg = ToRegister(instr->result()); | 3969 Register output_reg = ToRegister(instr->result()); |
| 3986 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 3970 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
| 3987 XMMRegister xmm_scratch = double_scratch0(); | 3971 XMMRegister xmm_scratch = double_scratch0(); |
| 3988 XMMRegister input_temp = ToDoubleRegister(instr->temp()); | 3972 XMMRegister input_temp = ToDoubleRegister(instr->temp()); |
| 3989 ExternalReference one_half = ExternalReference::address_of_one_half(); | 3973 ExternalReference one_half = ExternalReference::address_of_one_half(); |
| 3990 ExternalReference minus_one_half = | 3974 ExternalReference minus_one_half = |
| 3991 ExternalReference::address_of_minus_one_half(); | 3975 ExternalReference::address_of_minus_one_half(); |
| 3992 | 3976 |
| 3993 Label done, round_to_zero, below_one_half, do_not_compensate; | 3977 Label done, round_to_zero, below_one_half, do_not_compensate; |
| 3994 __ movdbl(xmm_scratch, Operand::StaticVariable(one_half)); | 3978 __ movsd(xmm_scratch, Operand::StaticVariable(one_half)); |
| 3995 __ ucomisd(xmm_scratch, input_reg); | 3979 __ ucomisd(xmm_scratch, input_reg); |
| 3996 __ j(above, &below_one_half); | 3980 __ j(above, &below_one_half); |
| 3997 | 3981 |
| 3998 // CVTTSD2SI rounds towards zero, since 0.5 <= x, we use floor(0.5 + x). | 3982 // CVTTSD2SI rounds towards zero, since 0.5 <= x, we use floor(0.5 + x). |
| 3999 __ addsd(xmm_scratch, input_reg); | 3983 __ addsd(xmm_scratch, input_reg); |
| 4000 __ cvttsd2si(output_reg, Operand(xmm_scratch)); | 3984 __ cvttsd2si(output_reg, Operand(xmm_scratch)); |
| 4001 // Overflow is signalled with minint. | 3985 // Overflow is signalled with minint. |
| 4002 __ cmp(output_reg, 0x80000000u); | 3986 __ cmp(output_reg, 0x80000000u); |
| 4003 __ RecordComment("D2I conversion overflow"); | 3987 __ RecordComment("D2I conversion overflow"); |
| 4004 DeoptimizeIf(equal, instr->environment()); | 3988 DeoptimizeIf(equal, instr->environment()); |
| 4005 __ jmp(&done); | 3989 __ jmp(&done); |
| 4006 | 3990 |
| 4007 __ bind(&below_one_half); | 3991 __ bind(&below_one_half); |
| 4008 __ movdbl(xmm_scratch, Operand::StaticVariable(minus_one_half)); | 3992 __ movsd(xmm_scratch, Operand::StaticVariable(minus_one_half)); |
| 4009 __ ucomisd(xmm_scratch, input_reg); | 3993 __ ucomisd(xmm_scratch, input_reg); |
| 4010 __ j(below_equal, &round_to_zero); | 3994 __ j(below_equal, &round_to_zero); |
| 4011 | 3995 |
| 4012 // CVTTSD2SI rounds towards zero, we use ceil(x - (-0.5)) and then | 3996 // CVTTSD2SI rounds towards zero, we use ceil(x - (-0.5)) and then |
| 4013 // compare and compensate. | 3997 // compare and compensate. |
| 4014 __ movsd(input_temp, input_reg); // Do not alter input_reg. | 3998 __ movsd(input_temp, input_reg); // Do not alter input_reg. |
| 4015 __ subsd(input_temp, xmm_scratch); | 3999 __ subsd(input_temp, xmm_scratch); |
| 4016 __ cvttsd2si(output_reg, Operand(input_temp)); | 4000 __ cvttsd2si(output_reg, Operand(input_temp)); |
| 4017 // Catch minint due to overflow, and to prevent overflow when compensating. | 4001 // Catch minint due to overflow, and to prevent overflow when compensating. |
| 4018 __ cmp(output_reg, 0x80000000u); | 4002 __ cmp(output_reg, 0x80000000u); |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4185 ASSERT(instr->value()->Equals(instr->result())); | 4169 ASSERT(instr->value()->Equals(instr->result())); |
| 4186 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 4170 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
| 4187 XMMRegister xmm_scratch = double_scratch0(); | 4171 XMMRegister xmm_scratch = double_scratch0(); |
| 4188 Label positive, done, zero; | 4172 Label positive, done, zero; |
| 4189 __ xorps(xmm_scratch, xmm_scratch); | 4173 __ xorps(xmm_scratch, xmm_scratch); |
| 4190 __ ucomisd(input_reg, xmm_scratch); | 4174 __ ucomisd(input_reg, xmm_scratch); |
| 4191 __ j(above, &positive, Label::kNear); | 4175 __ j(above, &positive, Label::kNear); |
| 4192 __ j(equal, &zero, Label::kNear); | 4176 __ j(equal, &zero, Label::kNear); |
| 4193 ExternalReference nan = | 4177 ExternalReference nan = |
| 4194 ExternalReference::address_of_canonical_non_hole_nan(); | 4178 ExternalReference::address_of_canonical_non_hole_nan(); |
| 4195 __ movdbl(input_reg, Operand::StaticVariable(nan)); | 4179 __ movsd(input_reg, Operand::StaticVariable(nan)); |
| 4196 __ jmp(&done, Label::kNear); | 4180 __ jmp(&done, Label::kNear); |
| 4197 __ bind(&zero); | 4181 __ bind(&zero); |
| 4198 __ push(Immediate(0xFFF00000)); | 4182 ExternalReference ninf = |
| 4199 __ push(Immediate(0)); | 4183 ExternalReference::address_of_negative_infinity(); |
| 4200 __ movdbl(input_reg, Operand(esp, 0)); | 4184 __ movsd(input_reg, Operand::StaticVariable(ninf)); |
| 4201 __ add(Operand(esp), Immediate(kDoubleSize)); | |
| 4202 __ jmp(&done, Label::kNear); | 4185 __ jmp(&done, Label::kNear); |
| 4203 __ bind(&positive); | 4186 __ bind(&positive); |
| 4204 __ fldln2(); | 4187 __ fldln2(); |
| 4205 __ sub(Operand(esp), Immediate(kDoubleSize)); | 4188 __ sub(Operand(esp), Immediate(kDoubleSize)); |
| 4206 __ movdbl(Operand(esp, 0), input_reg); | 4189 __ movsd(Operand(esp, 0), input_reg); |
| 4207 __ fld_d(Operand(esp, 0)); | 4190 __ fld_d(Operand(esp, 0)); |
| 4208 __ fyl2x(); | 4191 __ fyl2x(); |
| 4209 __ fstp_d(Operand(esp, 0)); | 4192 __ fstp_d(Operand(esp, 0)); |
| 4210 __ movdbl(input_reg, Operand(esp, 0)); | 4193 __ movsd(input_reg, Operand(esp, 0)); |
| 4211 __ add(Operand(esp), Immediate(kDoubleSize)); | 4194 __ add(Operand(esp), Immediate(kDoubleSize)); |
| 4212 __ bind(&done); | 4195 __ bind(&done); |
| 4213 } | 4196 } |
| 4214 | 4197 |
| 4215 | 4198 |
| 4216 void LCodeGen::DoMathExp(LMathExp* instr) { | 4199 void LCodeGen::DoMathExp(LMathExp* instr) { |
| 4217 CpuFeatureScope scope(masm(), SSE2); | 4200 CpuFeatureScope scope(masm(), SSE2); |
| 4218 XMMRegister input = ToDoubleRegister(instr->value()); | 4201 XMMRegister input = ToDoubleRegister(instr->value()); |
| 4219 XMMRegister result = ToDoubleRegister(instr->result()); | 4202 XMMRegister result = ToDoubleRegister(instr->result()); |
| 4220 XMMRegister temp0 = double_scratch0(); | 4203 XMMRegister temp0 = double_scratch0(); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4259 | 4242 |
| 4260 | 4243 |
| 4261 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { | 4244 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { |
| 4262 ASSERT(ToRegister(instr->context()).is(esi)); | 4245 ASSERT(ToRegister(instr->context()).is(esi)); |
| 4263 ASSERT(ToRegister(instr->function()).is(edi)); | 4246 ASSERT(ToRegister(instr->function()).is(edi)); |
| 4264 ASSERT(instr->HasPointerMap()); | 4247 ASSERT(instr->HasPointerMap()); |
| 4265 | 4248 |
| 4266 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); | 4249 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); |
| 4267 if (known_function.is_null()) { | 4250 if (known_function.is_null()) { |
| 4268 LPointerMap* pointers = instr->pointer_map(); | 4251 LPointerMap* pointers = instr->pointer_map(); |
| 4269 RecordPosition(pointers->position()); | |
| 4270 SafepointGenerator generator( | 4252 SafepointGenerator generator( |
| 4271 this, pointers, Safepoint::kLazyDeopt); | 4253 this, pointers, Safepoint::kLazyDeopt); |
| 4272 ParameterCount count(instr->arity()); | 4254 ParameterCount count(instr->arity()); |
| 4273 __ InvokeFunction(edi, count, CALL_FUNCTION, generator, CALL_AS_METHOD); | 4255 __ InvokeFunction(edi, count, CALL_FUNCTION, generator, CALL_AS_METHOD); |
| 4274 } else { | 4256 } else { |
| 4275 CallKnownFunction(known_function, | 4257 CallKnownFunction(known_function, |
| 4276 instr->hydrogen()->formal_parameter_count(), | 4258 instr->hydrogen()->formal_parameter_count(), |
| 4277 instr->arity(), | 4259 instr->arity(), |
| 4278 instr, | 4260 instr, |
| 4279 CALL_AS_METHOD, | 4261 CALL_AS_METHOD, |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4471 DeoptimizeIf(zero, instr->environment()); | 4453 DeoptimizeIf(zero, instr->environment()); |
| 4472 } | 4454 } |
| 4473 } | 4455 } |
| 4474 } else if (FLAG_track_double_fields && representation.IsDouble()) { | 4456 } else if (FLAG_track_double_fields && representation.IsDouble()) { |
| 4475 ASSERT(transition.is_null()); | 4457 ASSERT(transition.is_null()); |
| 4476 ASSERT(access.IsInobject()); | 4458 ASSERT(access.IsInobject()); |
| 4477 ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); | 4459 ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); |
| 4478 if (CpuFeatures::IsSupported(SSE2)) { | 4460 if (CpuFeatures::IsSupported(SSE2)) { |
| 4479 CpuFeatureScope scope(masm(), SSE2); | 4461 CpuFeatureScope scope(masm(), SSE2); |
| 4480 XMMRegister value = ToDoubleRegister(instr->value()); | 4462 XMMRegister value = ToDoubleRegister(instr->value()); |
| 4481 __ movdbl(FieldOperand(object, offset), value); | 4463 __ movsd(FieldOperand(object, offset), value); |
| 4482 } else { | 4464 } else { |
| 4483 X87Register value = ToX87Register(instr->value()); | 4465 X87Register value = ToX87Register(instr->value()); |
| 4484 X87Mov(FieldOperand(object, offset), value); | 4466 X87Mov(FieldOperand(object, offset), value); |
| 4485 } | 4467 } |
| 4486 return; | 4468 return; |
| 4487 } | 4469 } |
| 4488 | 4470 |
| 4489 if (!transition.is_null()) { | 4471 if (!transition.is_null()) { |
| 4490 if (!instr->hydrogen()->NeedsWriteBarrierForMap()) { | 4472 if (!instr->hydrogen()->NeedsWriteBarrierForMap()) { |
| 4491 __ mov(FieldOperand(object, HeapObject::kMapOffset), transition); | 4473 __ mov(FieldOperand(object, HeapObject::kMapOffset), transition); |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4621 XMMRegister xmm_scratch = double_scratch0(); | 4603 XMMRegister xmm_scratch = double_scratch0(); |
| 4622 __ cvtsd2ss(xmm_scratch, ToDoubleRegister(instr->value())); | 4604 __ cvtsd2ss(xmm_scratch, ToDoubleRegister(instr->value())); |
| 4623 __ movss(operand, xmm_scratch); | 4605 __ movss(operand, xmm_scratch); |
| 4624 } else { | 4606 } else { |
| 4625 __ fld(0); | 4607 __ fld(0); |
| 4626 __ fstp_s(operand); | 4608 __ fstp_s(operand); |
| 4627 } | 4609 } |
| 4628 } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { | 4610 } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { |
| 4629 if (CpuFeatures::IsSafeForSnapshot(SSE2)) { | 4611 if (CpuFeatures::IsSafeForSnapshot(SSE2)) { |
| 4630 CpuFeatureScope scope(masm(), SSE2); | 4612 CpuFeatureScope scope(masm(), SSE2); |
| 4631 __ movdbl(operand, ToDoubleRegister(instr->value())); | 4613 __ movsd(operand, ToDoubleRegister(instr->value())); |
| 4632 } else { | 4614 } else { |
| 4633 X87Mov(operand, ToX87Register(instr->value())); | 4615 X87Mov(operand, ToX87Register(instr->value())); |
| 4634 } | 4616 } |
| 4635 } else { | 4617 } else { |
| 4636 Register value = ToRegister(instr->value()); | 4618 Register value = ToRegister(instr->value()); |
| 4637 switch (elements_kind) { | 4619 switch (elements_kind) { |
| 4638 case EXTERNAL_PIXEL_ELEMENTS: | 4620 case EXTERNAL_PIXEL_ELEMENTS: |
| 4639 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 4621 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 4640 case EXTERNAL_BYTE_ELEMENTS: | 4622 case EXTERNAL_BYTE_ELEMENTS: |
| 4641 __ mov_b(operand, value); | 4623 __ mov_b(operand, value); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4679 if (CpuFeatures::IsSafeForSnapshot(SSE2)) { | 4661 if (CpuFeatures::IsSafeForSnapshot(SSE2)) { |
| 4680 CpuFeatureScope scope(masm(), SSE2); | 4662 CpuFeatureScope scope(masm(), SSE2); |
| 4681 XMMRegister value = ToDoubleRegister(instr->value()); | 4663 XMMRegister value = ToDoubleRegister(instr->value()); |
| 4682 | 4664 |
| 4683 if (instr->NeedsCanonicalization()) { | 4665 if (instr->NeedsCanonicalization()) { |
| 4684 Label have_value; | 4666 Label have_value; |
| 4685 | 4667 |
| 4686 __ ucomisd(value, value); | 4668 __ ucomisd(value, value); |
| 4687 __ j(parity_odd, &have_value); // NaN. | 4669 __ j(parity_odd, &have_value); // NaN. |
| 4688 | 4670 |
| 4689 __ movdbl(value, Operand::StaticVariable(canonical_nan_reference)); | 4671 __ movsd(value, Operand::StaticVariable(canonical_nan_reference)); |
| 4690 __ bind(&have_value); | 4672 __ bind(&have_value); |
| 4691 } | 4673 } |
| 4692 | 4674 |
| 4693 __ movdbl(double_store_operand, value); | 4675 __ movsd(double_store_operand, value); |
| 4694 } else { | 4676 } else { |
| 4695 // Can't use SSE2 in the serializer | 4677 // Can't use SSE2 in the serializer |
| 4696 if (instr->hydrogen()->IsConstantHoleStore()) { | 4678 if (instr->hydrogen()->IsConstantHoleStore()) { |
| 4697 // This means we should store the (double) hole. No floating point | 4679 // This means we should store the (double) hole. No floating point |
| 4698 // registers required. | 4680 // registers required. |
| 4699 double nan_double = FixedDoubleArray::hole_nan_as_double(); | 4681 double nan_double = FixedDoubleArray::hole_nan_as_double(); |
| 4700 uint64_t int_val = BitCast<uint64_t, double>(nan_double); | 4682 uint64_t int_val = BitCast<uint64_t, double>(nan_double); |
| 4701 int32_t lower = static_cast<int32_t>(int_val); | 4683 int32_t lower = static_cast<int32_t>(int_val); |
| 4702 int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt)); | 4684 int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt)); |
| 4703 | 4685 |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4806 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) | 4788 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) |
| 4807 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 4789 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() |
| 4808 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 4790 : isolate()->builtins()->KeyedStoreIC_Initialize(); |
| 4809 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 4791 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 4810 } | 4792 } |
| 4811 | 4793 |
| 4812 | 4794 |
| 4813 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { | 4795 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { |
| 4814 Register object = ToRegister(instr->object()); | 4796 Register object = ToRegister(instr->object()); |
| 4815 Register temp = ToRegister(instr->temp()); | 4797 Register temp = ToRegister(instr->temp()); |
| 4816 __ TestJSArrayForAllocationMemento(object, temp); | 4798 Label no_memento_found; |
| 4799 __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found); |
| 4817 DeoptimizeIf(equal, instr->environment()); | 4800 DeoptimizeIf(equal, instr->environment()); |
| 4801 __ bind(&no_memento_found); |
| 4818 } | 4802 } |
| 4819 | 4803 |
| 4820 | 4804 |
| 4821 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { | 4805 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { |
| 4822 Register object_reg = ToRegister(instr->object()); | 4806 Register object_reg = ToRegister(instr->object()); |
| 4823 | 4807 |
| 4824 Handle<Map> from_map = instr->original_map(); | 4808 Handle<Map> from_map = instr->original_map(); |
| 4825 Handle<Map> to_map = instr->transitioned_map(); | 4809 Handle<Map> to_map = instr->transitioned_map(); |
| 4826 ElementsKind from_kind = instr->from_kind(); | 4810 ElementsKind from_kind = instr->from_kind(); |
| 4827 ElementsKind to_kind = instr->to_kind(); | 4811 ElementsKind to_kind = instr->to_kind(); |
| (...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5147 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); | 5131 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); |
| 5148 RecordSafepointWithRegisters( | 5132 RecordSafepointWithRegisters( |
| 5149 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); | 5133 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); |
| 5150 if (!reg.is(eax)) __ mov(reg, eax); | 5134 if (!reg.is(eax)) __ mov(reg, eax); |
| 5151 | 5135 |
| 5152 // Done. Put the value in xmm_scratch into the value of the allocated heap | 5136 // Done. Put the value in xmm_scratch into the value of the allocated heap |
| 5153 // number. | 5137 // number. |
| 5154 __ bind(&done); | 5138 __ bind(&done); |
| 5155 if (CpuFeatures::IsSupported(SSE2)) { | 5139 if (CpuFeatures::IsSupported(SSE2)) { |
| 5156 CpuFeatureScope feature_scope(masm(), SSE2); | 5140 CpuFeatureScope feature_scope(masm(), SSE2); |
| 5157 __ movdbl(FieldOperand(reg, HeapNumber::kValueOffset), xmm_scratch); | 5141 __ movsd(FieldOperand(reg, HeapNumber::kValueOffset), xmm_scratch); |
| 5158 } else { | 5142 } else { |
| 5159 __ fstp_d(FieldOperand(reg, HeapNumber::kValueOffset)); | 5143 __ fstp_d(FieldOperand(reg, HeapNumber::kValueOffset)); |
| 5160 } | 5144 } |
| 5161 __ StoreToSafepointRegisterSlot(reg, reg); | 5145 __ StoreToSafepointRegisterSlot(reg, reg); |
| 5162 } | 5146 } |
| 5163 | 5147 |
| 5164 | 5148 |
| 5165 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { | 5149 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { |
| 5166 class DeferredNumberTagD V8_FINAL : public LDeferredCode { | 5150 class DeferredNumberTagD V8_FINAL : public LDeferredCode { |
| 5167 public: | 5151 public: |
| (...skipping 23 matching lines...) Expand all Loading... |
| 5191 if (FLAG_inline_new) { | 5175 if (FLAG_inline_new) { |
| 5192 Register tmp = ToRegister(instr->temp()); | 5176 Register tmp = ToRegister(instr->temp()); |
| 5193 __ AllocateHeapNumber(reg, tmp, no_reg, deferred->entry()); | 5177 __ AllocateHeapNumber(reg, tmp, no_reg, deferred->entry()); |
| 5194 } else { | 5178 } else { |
| 5195 __ jmp(deferred->entry()); | 5179 __ jmp(deferred->entry()); |
| 5196 } | 5180 } |
| 5197 __ bind(deferred->exit()); | 5181 __ bind(deferred->exit()); |
| 5198 if (use_sse2) { | 5182 if (use_sse2) { |
| 5199 CpuFeatureScope scope(masm(), SSE2); | 5183 CpuFeatureScope scope(masm(), SSE2); |
| 5200 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 5184 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
| 5201 __ movdbl(FieldOperand(reg, HeapNumber::kValueOffset), input_reg); | 5185 __ movsd(FieldOperand(reg, HeapNumber::kValueOffset), input_reg); |
| 5202 } else { | 5186 } else { |
| 5203 __ fstp_d(FieldOperand(reg, HeapNumber::kValueOffset)); | 5187 __ fstp_d(FieldOperand(reg, HeapNumber::kValueOffset)); |
| 5204 } | 5188 } |
| 5205 } | 5189 } |
| 5206 | 5190 |
| 5207 | 5191 |
| 5208 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { | 5192 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { |
| 5209 // TODO(3095996): Get rid of this. For now, we need to make the | 5193 // TODO(3095996): Get rid of this. For now, we need to make the |
| 5210 // result register contain a valid pointer because it is already | 5194 // result register contain a valid pointer because it is already |
| 5211 // contained in the register pointer map. | 5195 // contained in the register pointer map. |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5334 // Heap number map check. | 5318 // Heap number map check. |
| 5335 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), | 5319 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), |
| 5336 factory()->heap_number_map()); | 5320 factory()->heap_number_map()); |
| 5337 if (can_convert_undefined_to_nan) { | 5321 if (can_convert_undefined_to_nan) { |
| 5338 __ j(not_equal, &convert, Label::kNear); | 5322 __ j(not_equal, &convert, Label::kNear); |
| 5339 } else { | 5323 } else { |
| 5340 DeoptimizeIf(not_equal, env); | 5324 DeoptimizeIf(not_equal, env); |
| 5341 } | 5325 } |
| 5342 | 5326 |
| 5343 // Heap number to XMM conversion. | 5327 // Heap number to XMM conversion. |
| 5344 __ movdbl(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset)); | 5328 __ movsd(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
| 5345 | 5329 |
| 5346 if (deoptimize_on_minus_zero) { | 5330 if (deoptimize_on_minus_zero) { |
| 5347 XMMRegister xmm_scratch = double_scratch0(); | 5331 XMMRegister xmm_scratch = double_scratch0(); |
| 5348 __ xorps(xmm_scratch, xmm_scratch); | 5332 __ xorps(xmm_scratch, xmm_scratch); |
| 5349 __ ucomisd(result_reg, xmm_scratch); | 5333 __ ucomisd(result_reg, xmm_scratch); |
| 5350 __ j(not_zero, &done, Label::kNear); | 5334 __ j(not_zero, &done, Label::kNear); |
| 5351 __ movmskpd(temp_reg, result_reg); | 5335 __ movmskpd(temp_reg, result_reg); |
| 5352 __ test_b(temp_reg, 1); | 5336 __ test_b(temp_reg, 1); |
| 5353 DeoptimizeIf(not_zero, env); | 5337 DeoptimizeIf(not_zero, env); |
| 5354 } | 5338 } |
| 5355 __ jmp(&done, Label::kNear); | 5339 __ jmp(&done, Label::kNear); |
| 5356 | 5340 |
| 5357 if (can_convert_undefined_to_nan) { | 5341 if (can_convert_undefined_to_nan) { |
| 5358 __ bind(&convert); | 5342 __ bind(&convert); |
| 5359 | 5343 |
| 5360 // Convert undefined (and hole) to NaN. | 5344 // Convert undefined (and hole) to NaN. |
| 5361 __ cmp(input_reg, factory()->undefined_value()); | 5345 __ cmp(input_reg, factory()->undefined_value()); |
| 5362 DeoptimizeIf(not_equal, env); | 5346 DeoptimizeIf(not_equal, env); |
| 5363 | 5347 |
| 5364 ExternalReference nan = | 5348 ExternalReference nan = |
| 5365 ExternalReference::address_of_canonical_non_hole_nan(); | 5349 ExternalReference::address_of_canonical_non_hole_nan(); |
| 5366 __ movdbl(result_reg, Operand::StaticVariable(nan)); | 5350 __ movsd(result_reg, Operand::StaticVariable(nan)); |
| 5367 __ jmp(&done, Label::kNear); | 5351 __ jmp(&done, Label::kNear); |
| 5368 } | 5352 } |
| 5369 } else { | 5353 } else { |
| 5370 ASSERT(mode == NUMBER_CANDIDATE_IS_SMI); | 5354 ASSERT(mode == NUMBER_CANDIDATE_IS_SMI); |
| 5371 } | 5355 } |
| 5372 | 5356 |
| 5373 __ bind(&load_smi); | 5357 __ bind(&load_smi); |
| 5374 // Smi to XMM conversion. Clobbering a temp is faster than re-tagging the | 5358 // Smi to XMM conversion. Clobbering a temp is faster than re-tagging the |
| 5375 // input register since we avoid dependencies. | 5359 // input register since we avoid dependencies. |
| 5376 __ mov(temp_reg, input_reg); | 5360 __ mov(temp_reg, input_reg); |
| 5377 __ SmiUntag(temp_reg); // Untag smi before converting to float. | 5361 __ SmiUntag(temp_reg); // Untag smi before converting to float. |
| 5378 __ Cvtsi2sd(result_reg, Operand(temp_reg)); | 5362 __ Cvtsi2sd(result_reg, Operand(temp_reg)); |
| 5379 __ bind(&done); | 5363 __ bind(&done); |
| 5380 } | 5364 } |
| 5381 | 5365 |
| 5382 | 5366 |
| 5383 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr, Label* done) { | 5367 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr, Label* done) { |
| 5384 Register input_reg = ToRegister(instr->value()); | 5368 Register input_reg = ToRegister(instr->value()); |
| 5385 | 5369 |
| 5386 | |
| 5387 if (instr->truncating()) { | 5370 if (instr->truncating()) { |
| 5388 Label heap_number, slow_case; | 5371 Label no_heap_number, check_bools, check_false; |
| 5389 | 5372 |
| 5390 // Heap number map check. | 5373 // Heap number map check. |
| 5391 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), | 5374 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), |
| 5392 factory()->heap_number_map()); | 5375 factory()->heap_number_map()); |
| 5393 __ j(equal, &heap_number, Label::kNear); | 5376 __ j(not_equal, &no_heap_number, Label::kNear); |
| 5377 __ TruncateHeapNumberToI(input_reg, input_reg); |
| 5378 __ jmp(done); |
| 5394 | 5379 |
| 5395 // Check for undefined. Undefined is converted to zero for truncating | 5380 __ bind(&no_heap_number); |
| 5396 // conversions. | 5381 // Check for Oddballs. Undefined/False is converted to zero and True to one |
| 5382 // for truncating conversions. |
| 5397 __ cmp(input_reg, factory()->undefined_value()); | 5383 __ cmp(input_reg, factory()->undefined_value()); |
| 5384 __ j(not_equal, &check_bools, Label::kNear); |
| 5385 __ Set(input_reg, Immediate(0)); |
| 5386 __ jmp(done); |
| 5387 |
| 5388 __ bind(&check_bools); |
| 5389 __ cmp(input_reg, factory()->true_value()); |
| 5390 __ j(not_equal, &check_false, Label::kNear); |
| 5391 __ Set(input_reg, Immediate(1)); |
| 5392 __ jmp(done); |
| 5393 |
| 5394 __ bind(&check_false); |
| 5395 __ cmp(input_reg, factory()->false_value()); |
| 5398 __ RecordComment("Deferred TaggedToI: cannot truncate"); | 5396 __ RecordComment("Deferred TaggedToI: cannot truncate"); |
| 5399 DeoptimizeIf(not_equal, instr->environment()); | 5397 DeoptimizeIf(not_equal, instr->environment()); |
| 5400 __ mov(input_reg, 0); | 5398 __ Set(input_reg, Immediate(0)); |
| 5401 __ jmp(done); | 5399 __ jmp(done); |
| 5402 | |
| 5403 __ bind(&heap_number); | |
| 5404 __ TruncateHeapNumberToI(input_reg, input_reg); | |
| 5405 } else { | 5400 } else { |
| 5406 Label bailout; | 5401 Label bailout; |
| 5407 XMMRegister scratch = (instr->temp() != NULL) | 5402 XMMRegister scratch = (instr->temp() != NULL) |
| 5408 ? ToDoubleRegister(instr->temp()) | 5403 ? ToDoubleRegister(instr->temp()) |
| 5409 : no_xmm_reg; | 5404 : no_xmm_reg; |
| 5410 __ TaggedToI(input_reg, input_reg, scratch, | 5405 __ TaggedToI(input_reg, input_reg, scratch, |
| 5411 instr->hydrogen()->GetMinusZeroMode(), &bailout); | 5406 instr->hydrogen()->GetMinusZeroMode(), &bailout); |
| 5412 __ jmp(done); | 5407 __ jmp(done); |
| 5413 __ bind(&bailout); | 5408 __ bind(&bailout); |
| 5414 DeoptimizeIf(no_condition, instr->environment()); | 5409 DeoptimizeIf(no_condition, instr->environment()); |
| (...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5734 | 5729 |
| 5735 // Check for undefined. Undefined is converted to zero for clamping | 5730 // Check for undefined. Undefined is converted to zero for clamping |
| 5736 // conversions. | 5731 // conversions. |
| 5737 __ cmp(input_reg, factory()->undefined_value()); | 5732 __ cmp(input_reg, factory()->undefined_value()); |
| 5738 DeoptimizeIf(not_equal, instr->environment()); | 5733 DeoptimizeIf(not_equal, instr->environment()); |
| 5739 __ mov(input_reg, 0); | 5734 __ mov(input_reg, 0); |
| 5740 __ jmp(&done, Label::kNear); | 5735 __ jmp(&done, Label::kNear); |
| 5741 | 5736 |
| 5742 // Heap number | 5737 // Heap number |
| 5743 __ bind(&heap_number); | 5738 __ bind(&heap_number); |
| 5744 __ movdbl(xmm_scratch, FieldOperand(input_reg, HeapNumber::kValueOffset)); | 5739 __ movsd(xmm_scratch, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
| 5745 __ ClampDoubleToUint8(xmm_scratch, temp_xmm_reg, input_reg); | 5740 __ ClampDoubleToUint8(xmm_scratch, temp_xmm_reg, input_reg); |
| 5746 __ jmp(&done, Label::kNear); | 5741 __ jmp(&done, Label::kNear); |
| 5747 | 5742 |
| 5748 // smi | 5743 // smi |
| 5749 __ bind(&is_smi); | 5744 __ bind(&is_smi); |
| 5750 __ SmiUntag(input_reg); | 5745 __ SmiUntag(input_reg); |
| 5751 __ ClampUint8(input_reg); | 5746 __ ClampUint8(input_reg); |
| 5752 __ bind(&done); | 5747 __ bind(&done); |
| 5753 } | 5748 } |
| 5754 | 5749 |
| (...skipping 628 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6383 FixedArray::kHeaderSize - kPointerSize)); | 6378 FixedArray::kHeaderSize - kPointerSize)); |
| 6384 __ bind(&done); | 6379 __ bind(&done); |
| 6385 } | 6380 } |
| 6386 | 6381 |
| 6387 | 6382 |
| 6388 #undef __ | 6383 #undef __ |
| 6389 | 6384 |
| 6390 } } // namespace v8::internal | 6385 } } // namespace v8::internal |
| 6391 | 6386 |
| 6392 #endif // V8_TARGET_ARCH_IA32 | 6387 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |