OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_X64 | 7 #if V8_TARGET_ARCH_X64 |
8 | 8 |
9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
10 #include "src/hydrogen-osr.h" | 10 #include "src/hydrogen-osr.h" |
(...skipping 26 matching lines...) Expand all Loading... |
37 LCodeGen* codegen_; | 37 LCodeGen* codegen_; |
38 LPointerMap* pointers_; | 38 LPointerMap* pointers_; |
39 Safepoint::DeoptMode deopt_mode_; | 39 Safepoint::DeoptMode deopt_mode_; |
40 }; | 40 }; |
41 | 41 |
42 | 42 |
43 #define __ masm()-> | 43 #define __ masm()-> |
44 | 44 |
45 bool LCodeGen::GenerateCode() { | 45 bool LCodeGen::GenerateCode() { |
46 LPhase phase("Z_Code generation", chunk()); | 46 LPhase phase("Z_Code generation", chunk()); |
47 ASSERT(is_unused()); | 47 DCHECK(is_unused()); |
48 status_ = GENERATING; | 48 status_ = GENERATING; |
49 | 49 |
50 // Open a frame scope to indicate that there is a frame on the stack. The | 50 // Open a frame scope to indicate that there is a frame on the stack. The |
51 // MANUAL indicates that the scope shouldn't actually generate code to set up | 51 // MANUAL indicates that the scope shouldn't actually generate code to set up |
52 // the frame (that is done in GeneratePrologue). | 52 // the frame (that is done in GeneratePrologue). |
53 FrameScope frame_scope(masm_, StackFrame::MANUAL); | 53 FrameScope frame_scope(masm_, StackFrame::MANUAL); |
54 | 54 |
55 return GeneratePrologue() && | 55 return GeneratePrologue() && |
56 GenerateBody() && | 56 GenerateBody() && |
57 GenerateDeferredCode() && | 57 GenerateDeferredCode() && |
58 GenerateJumpTable() && | 58 GenerateJumpTable() && |
59 GenerateSafepointTable(); | 59 GenerateSafepointTable(); |
60 } | 60 } |
61 | 61 |
62 | 62 |
63 void LCodeGen::FinishCode(Handle<Code> code) { | 63 void LCodeGen::FinishCode(Handle<Code> code) { |
64 ASSERT(is_done()); | 64 DCHECK(is_done()); |
65 code->set_stack_slots(GetStackSlotCount()); | 65 code->set_stack_slots(GetStackSlotCount()); |
66 code->set_safepoint_table_offset(safepoints_.GetCodeOffset()); | 66 code->set_safepoint_table_offset(safepoints_.GetCodeOffset()); |
67 if (code->is_optimized_code()) RegisterWeakObjectsInOptimizedCode(code); | 67 if (code->is_optimized_code()) RegisterWeakObjectsInOptimizedCode(code); |
68 PopulateDeoptimizationData(code); | 68 PopulateDeoptimizationData(code); |
69 } | 69 } |
70 | 70 |
71 | 71 |
72 #ifdef _MSC_VER | 72 #ifdef _MSC_VER |
73 void LCodeGen::MakeSureStackPagesMapped(int offset) { | 73 void LCodeGen::MakeSureStackPagesMapped(int offset) { |
74 const int kPageSize = 4 * KB; | 74 const int kPageSize = 4 * KB; |
75 for (offset -= kPageSize; offset > 0; offset -= kPageSize) { | 75 for (offset -= kPageSize; offset > 0; offset -= kPageSize) { |
76 __ movp(Operand(rsp, offset), rax); | 76 __ movp(Operand(rsp, offset), rax); |
77 } | 77 } |
78 } | 78 } |
79 #endif | 79 #endif |
80 | 80 |
81 | 81 |
82 void LCodeGen::SaveCallerDoubles() { | 82 void LCodeGen::SaveCallerDoubles() { |
83 ASSERT(info()->saves_caller_doubles()); | 83 DCHECK(info()->saves_caller_doubles()); |
84 ASSERT(NeedsEagerFrame()); | 84 DCHECK(NeedsEagerFrame()); |
85 Comment(";;; Save clobbered callee double registers"); | 85 Comment(";;; Save clobbered callee double registers"); |
86 int count = 0; | 86 int count = 0; |
87 BitVector* doubles = chunk()->allocated_double_registers(); | 87 BitVector* doubles = chunk()->allocated_double_registers(); |
88 BitVector::Iterator save_iterator(doubles); | 88 BitVector::Iterator save_iterator(doubles); |
89 while (!save_iterator.Done()) { | 89 while (!save_iterator.Done()) { |
90 __ movsd(MemOperand(rsp, count * kDoubleSize), | 90 __ movsd(MemOperand(rsp, count * kDoubleSize), |
91 XMMRegister::FromAllocationIndex(save_iterator.Current())); | 91 XMMRegister::FromAllocationIndex(save_iterator.Current())); |
92 save_iterator.Advance(); | 92 save_iterator.Advance(); |
93 count++; | 93 count++; |
94 } | 94 } |
95 } | 95 } |
96 | 96 |
97 | 97 |
98 void LCodeGen::RestoreCallerDoubles() { | 98 void LCodeGen::RestoreCallerDoubles() { |
99 ASSERT(info()->saves_caller_doubles()); | 99 DCHECK(info()->saves_caller_doubles()); |
100 ASSERT(NeedsEagerFrame()); | 100 DCHECK(NeedsEagerFrame()); |
101 Comment(";;; Restore clobbered callee double registers"); | 101 Comment(";;; Restore clobbered callee double registers"); |
102 BitVector* doubles = chunk()->allocated_double_registers(); | 102 BitVector* doubles = chunk()->allocated_double_registers(); |
103 BitVector::Iterator save_iterator(doubles); | 103 BitVector::Iterator save_iterator(doubles); |
104 int count = 0; | 104 int count = 0; |
105 while (!save_iterator.Done()) { | 105 while (!save_iterator.Done()) { |
106 __ movsd(XMMRegister::FromAllocationIndex(save_iterator.Current()), | 106 __ movsd(XMMRegister::FromAllocationIndex(save_iterator.Current()), |
107 MemOperand(rsp, count * kDoubleSize)); | 107 MemOperand(rsp, count * kDoubleSize)); |
108 save_iterator.Advance(); | 108 save_iterator.Advance(); |
109 count++; | 109 count++; |
110 } | 110 } |
111 } | 111 } |
112 | 112 |
113 | 113 |
114 bool LCodeGen::GeneratePrologue() { | 114 bool LCodeGen::GeneratePrologue() { |
115 ASSERT(is_generating()); | 115 DCHECK(is_generating()); |
116 | 116 |
117 if (info()->IsOptimizing()) { | 117 if (info()->IsOptimizing()) { |
118 ProfileEntryHookStub::MaybeCallEntryHook(masm_); | 118 ProfileEntryHookStub::MaybeCallEntryHook(masm_); |
119 | 119 |
120 #ifdef DEBUG | 120 #ifdef DEBUG |
121 if (strlen(FLAG_stop_at) > 0 && | 121 if (strlen(FLAG_stop_at) > 0 && |
122 info_->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { | 122 info_->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { |
123 __ int3(); | 123 __ int3(); |
124 } | 124 } |
125 #endif | 125 #endif |
(...skipping 14 matching lines...) Expand all Loading... |
140 __ movp(rcx, FieldOperand(rcx, GlobalObject::kGlobalProxyOffset)); | 140 __ movp(rcx, FieldOperand(rcx, GlobalObject::kGlobalProxyOffset)); |
141 | 141 |
142 __ movp(args.GetReceiverOperand(), rcx); | 142 __ movp(args.GetReceiverOperand(), rcx); |
143 | 143 |
144 __ bind(&ok); | 144 __ bind(&ok); |
145 } | 145 } |
146 } | 146 } |
147 | 147 |
148 info()->set_prologue_offset(masm_->pc_offset()); | 148 info()->set_prologue_offset(masm_->pc_offset()); |
149 if (NeedsEagerFrame()) { | 149 if (NeedsEagerFrame()) { |
150 ASSERT(!frame_is_built_); | 150 DCHECK(!frame_is_built_); |
151 frame_is_built_ = true; | 151 frame_is_built_ = true; |
152 if (info()->IsStub()) { | 152 if (info()->IsStub()) { |
153 __ StubPrologue(); | 153 __ StubPrologue(); |
154 } else { | 154 } else { |
155 __ Prologue(info()->IsCodePreAgingActive()); | 155 __ Prologue(info()->IsCodePreAgingActive()); |
156 } | 156 } |
157 info()->AddNoFrameRange(0, masm_->pc_offset()); | 157 info()->AddNoFrameRange(0, masm_->pc_offset()); |
158 } | 158 } |
159 | 159 |
160 // Reserve space for the stack slots needed by the code. | 160 // Reserve space for the stack slots needed by the code. |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
245 void LCodeGen::GenerateOsrPrologue() { | 245 void LCodeGen::GenerateOsrPrologue() { |
246 // Generate the OSR entry prologue at the first unknown OSR value, or if there | 246 // Generate the OSR entry prologue at the first unknown OSR value, or if there |
247 // are none, at the OSR entrypoint instruction. | 247 // are none, at the OSR entrypoint instruction. |
248 if (osr_pc_offset_ >= 0) return; | 248 if (osr_pc_offset_ >= 0) return; |
249 | 249 |
250 osr_pc_offset_ = masm()->pc_offset(); | 250 osr_pc_offset_ = masm()->pc_offset(); |
251 | 251 |
252 // Adjust the frame size, subsuming the unoptimized frame into the | 252 // Adjust the frame size, subsuming the unoptimized frame into the |
253 // optimized frame. | 253 // optimized frame. |
254 int slots = GetStackSlotCount() - graph()->osr()->UnoptimizedFrameSlots(); | 254 int slots = GetStackSlotCount() - graph()->osr()->UnoptimizedFrameSlots(); |
255 ASSERT(slots >= 0); | 255 DCHECK(slots >= 0); |
256 __ subp(rsp, Immediate(slots * kPointerSize)); | 256 __ subp(rsp, Immediate(slots * kPointerSize)); |
257 } | 257 } |
258 | 258 |
259 | 259 |
260 void LCodeGen::GenerateBodyInstructionPre(LInstruction* instr) { | 260 void LCodeGen::GenerateBodyInstructionPre(LInstruction* instr) { |
261 if (instr->IsCall()) { | 261 if (instr->IsCall()) { |
262 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); | 262 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); |
263 } | 263 } |
264 if (!instr->IsLazyBailout() && !instr->IsGap()) { | 264 if (!instr->IsLazyBailout() && !instr->IsGap()) { |
265 safepoints_.BumpLastLazySafepointIndex(); | 265 safepoints_.BumpLastLazySafepointIndex(); |
266 } | 266 } |
267 } | 267 } |
268 | 268 |
269 | 269 |
270 void LCodeGen::GenerateBodyInstructionPost(LInstruction* instr) { | 270 void LCodeGen::GenerateBodyInstructionPost(LInstruction* instr) { |
271 if (FLAG_debug_code && FLAG_enable_slow_asserts && instr->HasResult() && | 271 if (FLAG_debug_code && FLAG_enable_slow_asserts && instr->HasResult() && |
272 instr->hydrogen_value()->representation().IsInteger32() && | 272 instr->hydrogen_value()->representation().IsInteger32() && |
273 instr->result()->IsRegister()) { | 273 instr->result()->IsRegister()) { |
274 __ AssertZeroExtended(ToRegister(instr->result())); | 274 __ AssertZeroExtended(ToRegister(instr->result())); |
275 } | 275 } |
276 | 276 |
277 if (instr->HasResult() && instr->MustSignExtendResult(chunk())) { | 277 if (instr->HasResult() && instr->MustSignExtendResult(chunk())) { |
278 // We sign extend the dehoisted key at the definition point when the pointer | 278 // We sign extend the dehoisted key at the definition point when the pointer |
279 // size is 64-bit. For x32 port, we sign extend the dehoisted key at the use | 279 // size is 64-bit. For x32 port, we sign extend the dehoisted key at the use |
280 // points and MustSignExtendResult is always false. We can't use | 280 // points and MustSignExtendResult is always false. We can't use |
281 // STATIC_ASSERT here as the pointer size is 32-bit for x32. | 281 // STATIC_ASSERT here as the pointer size is 32-bit for x32. |
282 ASSERT(kPointerSize == kInt64Size); | 282 DCHECK(kPointerSize == kInt64Size); |
283 if (instr->result()->IsRegister()) { | 283 if (instr->result()->IsRegister()) { |
284 Register result_reg = ToRegister(instr->result()); | 284 Register result_reg = ToRegister(instr->result()); |
285 __ movsxlq(result_reg, result_reg); | 285 __ movsxlq(result_reg, result_reg); |
286 } else { | 286 } else { |
287 // Sign extend the 32bit result in the stack slots. | 287 // Sign extend the 32bit result in the stack slots. |
288 ASSERT(instr->result()->IsStackSlot()); | 288 DCHECK(instr->result()->IsStackSlot()); |
289 Operand src = ToOperand(instr->result()); | 289 Operand src = ToOperand(instr->result()); |
290 __ movsxlq(kScratchRegister, src); | 290 __ movsxlq(kScratchRegister, src); |
291 __ movq(src, kScratchRegister); | 291 __ movq(src, kScratchRegister); |
292 } | 292 } |
293 } | 293 } |
294 } | 294 } |
295 | 295 |
296 | 296 |
297 bool LCodeGen::GenerateJumpTable() { | 297 bool LCodeGen::GenerateJumpTable() { |
298 Label needs_frame; | 298 Label needs_frame; |
299 if (jump_table_.length() > 0) { | 299 if (jump_table_.length() > 0) { |
300 Comment(";;; -------------------- Jump table --------------------"); | 300 Comment(";;; -------------------- Jump table --------------------"); |
301 } | 301 } |
302 for (int i = 0; i < jump_table_.length(); i++) { | 302 for (int i = 0; i < jump_table_.length(); i++) { |
303 __ bind(&jump_table_[i].label); | 303 __ bind(&jump_table_[i].label); |
304 Address entry = jump_table_[i].address; | 304 Address entry = jump_table_[i].address; |
305 Deoptimizer::BailoutType type = jump_table_[i].bailout_type; | 305 Deoptimizer::BailoutType type = jump_table_[i].bailout_type; |
306 int id = Deoptimizer::GetDeoptimizationId(isolate(), entry, type); | 306 int id = Deoptimizer::GetDeoptimizationId(isolate(), entry, type); |
307 if (id == Deoptimizer::kNotDeoptimizationEntry) { | 307 if (id == Deoptimizer::kNotDeoptimizationEntry) { |
308 Comment(";;; jump table entry %d.", i); | 308 Comment(";;; jump table entry %d.", i); |
309 } else { | 309 } else { |
310 Comment(";;; jump table entry %d: deoptimization bailout %d.", i, id); | 310 Comment(";;; jump table entry %d: deoptimization bailout %d.", i, id); |
311 } | 311 } |
312 if (jump_table_[i].needs_frame) { | 312 if (jump_table_[i].needs_frame) { |
313 ASSERT(!info()->saves_caller_doubles()); | 313 DCHECK(!info()->saves_caller_doubles()); |
314 __ Move(kScratchRegister, ExternalReference::ForDeoptEntry(entry)); | 314 __ Move(kScratchRegister, ExternalReference::ForDeoptEntry(entry)); |
315 if (needs_frame.is_bound()) { | 315 if (needs_frame.is_bound()) { |
316 __ jmp(&needs_frame); | 316 __ jmp(&needs_frame); |
317 } else { | 317 } else { |
318 __ bind(&needs_frame); | 318 __ bind(&needs_frame); |
319 __ movp(rsi, MemOperand(rbp, StandardFrameConstants::kContextOffset)); | 319 __ movp(rsi, MemOperand(rbp, StandardFrameConstants::kContextOffset)); |
320 __ pushq(rbp); | 320 __ pushq(rbp); |
321 __ movp(rbp, rsp); | 321 __ movp(rbp, rsp); |
322 __ Push(rsi); | 322 __ Push(rsi); |
323 // This variant of deopt can only be used with stubs. Since we don't | 323 // This variant of deopt can only be used with stubs. Since we don't |
324 // have a function pointer to install in the stack frame that we're | 324 // have a function pointer to install in the stack frame that we're |
325 // building, install a special marker there instead. | 325 // building, install a special marker there instead. |
326 ASSERT(info()->IsStub()); | 326 DCHECK(info()->IsStub()); |
327 __ Move(rsi, Smi::FromInt(StackFrame::STUB)); | 327 __ Move(rsi, Smi::FromInt(StackFrame::STUB)); |
328 __ Push(rsi); | 328 __ Push(rsi); |
329 __ movp(rsi, MemOperand(rsp, kPointerSize)); | 329 __ movp(rsi, MemOperand(rsp, kPointerSize)); |
330 __ call(kScratchRegister); | 330 __ call(kScratchRegister); |
331 } | 331 } |
332 } else { | 332 } else { |
333 if (info()->saves_caller_doubles()) { | 333 if (info()->saves_caller_doubles()) { |
334 ASSERT(info()->IsStub()); | 334 DCHECK(info()->IsStub()); |
335 RestoreCallerDoubles(); | 335 RestoreCallerDoubles(); |
336 } | 336 } |
337 __ call(entry, RelocInfo::RUNTIME_ENTRY); | 337 __ call(entry, RelocInfo::RUNTIME_ENTRY); |
338 } | 338 } |
339 } | 339 } |
340 return !is_aborted(); | 340 return !is_aborted(); |
341 } | 341 } |
342 | 342 |
343 | 343 |
344 bool LCodeGen::GenerateDeferredCode() { | 344 bool LCodeGen::GenerateDeferredCode() { |
345 ASSERT(is_generating()); | 345 DCHECK(is_generating()); |
346 if (deferred_.length() > 0) { | 346 if (deferred_.length() > 0) { |
347 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { | 347 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { |
348 LDeferredCode* code = deferred_[i]; | 348 LDeferredCode* code = deferred_[i]; |
349 | 349 |
350 HValue* value = | 350 HValue* value = |
351 instructions_->at(code->instruction_index())->hydrogen_value(); | 351 instructions_->at(code->instruction_index())->hydrogen_value(); |
352 RecordAndWritePosition( | 352 RecordAndWritePosition( |
353 chunk()->graph()->SourcePositionToScriptPosition(value->position())); | 353 chunk()->graph()->SourcePositionToScriptPosition(value->position())); |
354 | 354 |
355 Comment(";;; <@%d,#%d> " | 355 Comment(";;; <@%d,#%d> " |
356 "-------------------- Deferred %s --------------------", | 356 "-------------------- Deferred %s --------------------", |
357 code->instruction_index(), | 357 code->instruction_index(), |
358 code->instr()->hydrogen_value()->id(), | 358 code->instr()->hydrogen_value()->id(), |
359 code->instr()->Mnemonic()); | 359 code->instr()->Mnemonic()); |
360 __ bind(code->entry()); | 360 __ bind(code->entry()); |
361 if (NeedsDeferredFrame()) { | 361 if (NeedsDeferredFrame()) { |
362 Comment(";;; Build frame"); | 362 Comment(";;; Build frame"); |
363 ASSERT(!frame_is_built_); | 363 DCHECK(!frame_is_built_); |
364 ASSERT(info()->IsStub()); | 364 DCHECK(info()->IsStub()); |
365 frame_is_built_ = true; | 365 frame_is_built_ = true; |
366 // Build the frame in such a way that esi isn't trashed. | 366 // Build the frame in such a way that esi isn't trashed. |
367 __ pushq(rbp); // Caller's frame pointer. | 367 __ pushq(rbp); // Caller's frame pointer. |
368 __ Push(Operand(rbp, StandardFrameConstants::kContextOffset)); | 368 __ Push(Operand(rbp, StandardFrameConstants::kContextOffset)); |
369 __ Push(Smi::FromInt(StackFrame::STUB)); | 369 __ Push(Smi::FromInt(StackFrame::STUB)); |
370 __ leap(rbp, Operand(rsp, 2 * kPointerSize)); | 370 __ leap(rbp, Operand(rsp, 2 * kPointerSize)); |
371 Comment(";;; Deferred code"); | 371 Comment(";;; Deferred code"); |
372 } | 372 } |
373 code->Generate(); | 373 code->Generate(); |
374 if (NeedsDeferredFrame()) { | 374 if (NeedsDeferredFrame()) { |
375 __ bind(code->done()); | 375 __ bind(code->done()); |
376 Comment(";;; Destroy frame"); | 376 Comment(";;; Destroy frame"); |
377 ASSERT(frame_is_built_); | 377 DCHECK(frame_is_built_); |
378 frame_is_built_ = false; | 378 frame_is_built_ = false; |
379 __ movp(rsp, rbp); | 379 __ movp(rsp, rbp); |
380 __ popq(rbp); | 380 __ popq(rbp); |
381 } | 381 } |
382 __ jmp(code->exit()); | 382 __ jmp(code->exit()); |
383 } | 383 } |
384 } | 384 } |
385 | 385 |
386 // Deferred code is the last part of the instruction sequence. Mark | 386 // Deferred code is the last part of the instruction sequence. Mark |
387 // the generated code as done unless we bailed out. | 387 // the generated code as done unless we bailed out. |
388 if (!is_aborted()) status_ = DONE; | 388 if (!is_aborted()) status_ = DONE; |
389 return !is_aborted(); | 389 return !is_aborted(); |
390 } | 390 } |
391 | 391 |
392 | 392 |
393 bool LCodeGen::GenerateSafepointTable() { | 393 bool LCodeGen::GenerateSafepointTable() { |
394 ASSERT(is_done()); | 394 DCHECK(is_done()); |
395 safepoints_.Emit(masm(), GetStackSlotCount()); | 395 safepoints_.Emit(masm(), GetStackSlotCount()); |
396 return !is_aborted(); | 396 return !is_aborted(); |
397 } | 397 } |
398 | 398 |
399 | 399 |
400 Register LCodeGen::ToRegister(int index) const { | 400 Register LCodeGen::ToRegister(int index) const { |
401 return Register::FromAllocationIndex(index); | 401 return Register::FromAllocationIndex(index); |
402 } | 402 } |
403 | 403 |
404 | 404 |
405 XMMRegister LCodeGen::ToDoubleRegister(int index) const { | 405 XMMRegister LCodeGen::ToDoubleRegister(int index) const { |
406 return XMMRegister::FromAllocationIndex(index); | 406 return XMMRegister::FromAllocationIndex(index); |
407 } | 407 } |
408 | 408 |
409 | 409 |
410 Register LCodeGen::ToRegister(LOperand* op) const { | 410 Register LCodeGen::ToRegister(LOperand* op) const { |
411 ASSERT(op->IsRegister()); | 411 DCHECK(op->IsRegister()); |
412 return ToRegister(op->index()); | 412 return ToRegister(op->index()); |
413 } | 413 } |
414 | 414 |
415 | 415 |
416 XMMRegister LCodeGen::ToDoubleRegister(LOperand* op) const { | 416 XMMRegister LCodeGen::ToDoubleRegister(LOperand* op) const { |
417 ASSERT(op->IsDoubleRegister()); | 417 DCHECK(op->IsDoubleRegister()); |
418 return ToDoubleRegister(op->index()); | 418 return ToDoubleRegister(op->index()); |
419 } | 419 } |
420 | 420 |
421 | 421 |
422 bool LCodeGen::IsInteger32Constant(LConstantOperand* op) const { | 422 bool LCodeGen::IsInteger32Constant(LConstantOperand* op) const { |
423 return chunk_->LookupLiteralRepresentation(op).IsSmiOrInteger32(); | 423 return chunk_->LookupLiteralRepresentation(op).IsSmiOrInteger32(); |
424 } | 424 } |
425 | 425 |
426 | 426 |
427 bool LCodeGen::IsDehoistedKeyConstant(LConstantOperand* op) const { | 427 bool LCodeGen::IsDehoistedKeyConstant(LConstantOperand* op) const { |
(...skipping 10 matching lines...) Expand all Loading... |
438 int32_t LCodeGen::ToInteger32(LConstantOperand* op) const { | 438 int32_t LCodeGen::ToInteger32(LConstantOperand* op) const { |
439 return ToRepresentation(op, Representation::Integer32()); | 439 return ToRepresentation(op, Representation::Integer32()); |
440 } | 440 } |
441 | 441 |
442 | 442 |
443 int32_t LCodeGen::ToRepresentation(LConstantOperand* op, | 443 int32_t LCodeGen::ToRepresentation(LConstantOperand* op, |
444 const Representation& r) const { | 444 const Representation& r) const { |
445 HConstant* constant = chunk_->LookupConstant(op); | 445 HConstant* constant = chunk_->LookupConstant(op); |
446 int32_t value = constant->Integer32Value(); | 446 int32_t value = constant->Integer32Value(); |
447 if (r.IsInteger32()) return value; | 447 if (r.IsInteger32()) return value; |
448 ASSERT(SmiValuesAre31Bits() && r.IsSmiOrTagged()); | 448 DCHECK(SmiValuesAre31Bits() && r.IsSmiOrTagged()); |
449 return static_cast<int32_t>(reinterpret_cast<intptr_t>(Smi::FromInt(value))); | 449 return static_cast<int32_t>(reinterpret_cast<intptr_t>(Smi::FromInt(value))); |
450 } | 450 } |
451 | 451 |
452 | 452 |
453 Smi* LCodeGen::ToSmi(LConstantOperand* op) const { | 453 Smi* LCodeGen::ToSmi(LConstantOperand* op) const { |
454 HConstant* constant = chunk_->LookupConstant(op); | 454 HConstant* constant = chunk_->LookupConstant(op); |
455 return Smi::FromInt(constant->Integer32Value()); | 455 return Smi::FromInt(constant->Integer32Value()); |
456 } | 456 } |
457 | 457 |
458 | 458 |
459 double LCodeGen::ToDouble(LConstantOperand* op) const { | 459 double LCodeGen::ToDouble(LConstantOperand* op) const { |
460 HConstant* constant = chunk_->LookupConstant(op); | 460 HConstant* constant = chunk_->LookupConstant(op); |
461 ASSERT(constant->HasDoubleValue()); | 461 DCHECK(constant->HasDoubleValue()); |
462 return constant->DoubleValue(); | 462 return constant->DoubleValue(); |
463 } | 463 } |
464 | 464 |
465 | 465 |
466 ExternalReference LCodeGen::ToExternalReference(LConstantOperand* op) const { | 466 ExternalReference LCodeGen::ToExternalReference(LConstantOperand* op) const { |
467 HConstant* constant = chunk_->LookupConstant(op); | 467 HConstant* constant = chunk_->LookupConstant(op); |
468 ASSERT(constant->HasExternalReferenceValue()); | 468 DCHECK(constant->HasExternalReferenceValue()); |
469 return constant->ExternalReferenceValue(); | 469 return constant->ExternalReferenceValue(); |
470 } | 470 } |
471 | 471 |
472 | 472 |
473 Handle<Object> LCodeGen::ToHandle(LConstantOperand* op) const { | 473 Handle<Object> LCodeGen::ToHandle(LConstantOperand* op) const { |
474 HConstant* constant = chunk_->LookupConstant(op); | 474 HConstant* constant = chunk_->LookupConstant(op); |
475 ASSERT(chunk_->LookupLiteralRepresentation(op).IsSmiOrTagged()); | 475 DCHECK(chunk_->LookupLiteralRepresentation(op).IsSmiOrTagged()); |
476 return constant->handle(isolate()); | 476 return constant->handle(isolate()); |
477 } | 477 } |
478 | 478 |
479 | 479 |
480 static int ArgumentsOffsetWithoutFrame(int index) { | 480 static int ArgumentsOffsetWithoutFrame(int index) { |
481 ASSERT(index < 0); | 481 DCHECK(index < 0); |
482 return -(index + 1) * kPointerSize + kPCOnStackSize; | 482 return -(index + 1) * kPointerSize + kPCOnStackSize; |
483 } | 483 } |
484 | 484 |
485 | 485 |
486 Operand LCodeGen::ToOperand(LOperand* op) const { | 486 Operand LCodeGen::ToOperand(LOperand* op) const { |
487 // Does not handle registers. In X64 assembler, plain registers are not | 487 // Does not handle registers. In X64 assembler, plain registers are not |
488 // representable as an Operand. | 488 // representable as an Operand. |
489 ASSERT(op->IsStackSlot() || op->IsDoubleStackSlot()); | 489 DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot()); |
490 if (NeedsEagerFrame()) { | 490 if (NeedsEagerFrame()) { |
491 return Operand(rbp, StackSlotOffset(op->index())); | 491 return Operand(rbp, StackSlotOffset(op->index())); |
492 } else { | 492 } else { |
493 // Retrieve parameter without eager stack-frame relative to the | 493 // Retrieve parameter without eager stack-frame relative to the |
494 // stack-pointer. | 494 // stack-pointer. |
495 return Operand(rsp, ArgumentsOffsetWithoutFrame(op->index())); | 495 return Operand(rsp, ArgumentsOffsetWithoutFrame(op->index())); |
496 } | 496 } |
497 } | 497 } |
498 | 498 |
499 | 499 |
(...skipping 14 matching lines...) Expand all Loading... |
514 : Translation::kSelfLiteralId; | 514 : Translation::kSelfLiteralId; |
515 | 515 |
516 switch (environment->frame_type()) { | 516 switch (environment->frame_type()) { |
517 case JS_FUNCTION: | 517 case JS_FUNCTION: |
518 translation->BeginJSFrame(environment->ast_id(), closure_id, height); | 518 translation->BeginJSFrame(environment->ast_id(), closure_id, height); |
519 break; | 519 break; |
520 case JS_CONSTRUCT: | 520 case JS_CONSTRUCT: |
521 translation->BeginConstructStubFrame(closure_id, translation_size); | 521 translation->BeginConstructStubFrame(closure_id, translation_size); |
522 break; | 522 break; |
523 case JS_GETTER: | 523 case JS_GETTER: |
524 ASSERT(translation_size == 1); | 524 DCHECK(translation_size == 1); |
525 ASSERT(height == 0); | 525 DCHECK(height == 0); |
526 translation->BeginGetterStubFrame(closure_id); | 526 translation->BeginGetterStubFrame(closure_id); |
527 break; | 527 break; |
528 case JS_SETTER: | 528 case JS_SETTER: |
529 ASSERT(translation_size == 2); | 529 DCHECK(translation_size == 2); |
530 ASSERT(height == 0); | 530 DCHECK(height == 0); |
531 translation->BeginSetterStubFrame(closure_id); | 531 translation->BeginSetterStubFrame(closure_id); |
532 break; | 532 break; |
533 case ARGUMENTS_ADAPTOR: | 533 case ARGUMENTS_ADAPTOR: |
534 translation->BeginArgumentsAdaptorFrame(closure_id, translation_size); | 534 translation->BeginArgumentsAdaptorFrame(closure_id, translation_size); |
535 break; | 535 break; |
536 case STUB: | 536 case STUB: |
537 translation->BeginCompiledStubFrame(); | 537 translation->BeginCompiledStubFrame(); |
538 break; | 538 break; |
539 } | 539 } |
540 | 540 |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
619 UNREACHABLE(); | 619 UNREACHABLE(); |
620 } | 620 } |
621 } | 621 } |
622 | 622 |
623 | 623 |
624 void LCodeGen::CallCodeGeneric(Handle<Code> code, | 624 void LCodeGen::CallCodeGeneric(Handle<Code> code, |
625 RelocInfo::Mode mode, | 625 RelocInfo::Mode mode, |
626 LInstruction* instr, | 626 LInstruction* instr, |
627 SafepointMode safepoint_mode, | 627 SafepointMode safepoint_mode, |
628 int argc) { | 628 int argc) { |
629 ASSERT(instr != NULL); | 629 DCHECK(instr != NULL); |
630 __ call(code, mode); | 630 __ call(code, mode); |
631 RecordSafepointWithLazyDeopt(instr, safepoint_mode, argc); | 631 RecordSafepointWithLazyDeopt(instr, safepoint_mode, argc); |
632 | 632 |
633 // Signal that we don't inline smi code before these stubs in the | 633 // Signal that we don't inline smi code before these stubs in the |
634 // optimizing code generator. | 634 // optimizing code generator. |
635 if (code->kind() == Code::BINARY_OP_IC || | 635 if (code->kind() == Code::BINARY_OP_IC || |
636 code->kind() == Code::COMPARE_IC) { | 636 code->kind() == Code::COMPARE_IC) { |
637 __ nop(); | 637 __ nop(); |
638 } | 638 } |
639 } | 639 } |
640 | 640 |
641 | 641 |
642 void LCodeGen::CallCode(Handle<Code> code, | 642 void LCodeGen::CallCode(Handle<Code> code, |
643 RelocInfo::Mode mode, | 643 RelocInfo::Mode mode, |
644 LInstruction* instr) { | 644 LInstruction* instr) { |
645 CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT, 0); | 645 CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT, 0); |
646 } | 646 } |
647 | 647 |
648 | 648 |
649 void LCodeGen::CallRuntime(const Runtime::Function* function, | 649 void LCodeGen::CallRuntime(const Runtime::Function* function, |
650 int num_arguments, | 650 int num_arguments, |
651 LInstruction* instr, | 651 LInstruction* instr, |
652 SaveFPRegsMode save_doubles) { | 652 SaveFPRegsMode save_doubles) { |
653 ASSERT(instr != NULL); | 653 DCHECK(instr != NULL); |
654 ASSERT(instr->HasPointerMap()); | 654 DCHECK(instr->HasPointerMap()); |
655 | 655 |
656 __ CallRuntime(function, num_arguments, save_doubles); | 656 __ CallRuntime(function, num_arguments, save_doubles); |
657 | 657 |
658 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT, 0); | 658 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT, 0); |
659 } | 659 } |
660 | 660 |
661 | 661 |
662 void LCodeGen::LoadContextFromDeferred(LOperand* context) { | 662 void LCodeGen::LoadContextFromDeferred(LOperand* context) { |
663 if (context->IsRegister()) { | 663 if (context->IsRegister()) { |
664 if (!ToRegister(context).is(rsi)) { | 664 if (!ToRegister(context).is(rsi)) { |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
723 (mode == Safepoint::kLazyDeopt) ? pc_offset : -1); | 723 (mode == Safepoint::kLazyDeopt) ? pc_offset : -1); |
724 deoptimizations_.Add(environment, environment->zone()); | 724 deoptimizations_.Add(environment, environment->zone()); |
725 } | 725 } |
726 } | 726 } |
727 | 727 |
728 | 728 |
729 void LCodeGen::DeoptimizeIf(Condition cc, | 729 void LCodeGen::DeoptimizeIf(Condition cc, |
730 LEnvironment* environment, | 730 LEnvironment* environment, |
731 Deoptimizer::BailoutType bailout_type) { | 731 Deoptimizer::BailoutType bailout_type) { |
732 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); | 732 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); |
733 ASSERT(environment->HasBeenRegistered()); | 733 DCHECK(environment->HasBeenRegistered()); |
734 int id = environment->deoptimization_index(); | 734 int id = environment->deoptimization_index(); |
735 ASSERT(info()->IsOptimizing() || info()->IsStub()); | 735 DCHECK(info()->IsOptimizing() || info()->IsStub()); |
736 Address entry = | 736 Address entry = |
737 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type); | 737 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type); |
738 if (entry == NULL) { | 738 if (entry == NULL) { |
739 Abort(kBailoutWasNotPrepared); | 739 Abort(kBailoutWasNotPrepared); |
740 return; | 740 return; |
741 } | 741 } |
742 | 742 |
743 if (DeoptEveryNTimes()) { | 743 if (DeoptEveryNTimes()) { |
744 ExternalReference count = ExternalReference::stress_deopt_count(isolate()); | 744 ExternalReference count = ExternalReference::stress_deopt_count(isolate()); |
745 Label no_deopt; | 745 Label no_deopt; |
746 __ pushfq(); | 746 __ pushfq(); |
747 __ pushq(rax); | 747 __ pushq(rax); |
748 Operand count_operand = masm()->ExternalOperand(count, kScratchRegister); | 748 Operand count_operand = masm()->ExternalOperand(count, kScratchRegister); |
749 __ movl(rax, count_operand); | 749 __ movl(rax, count_operand); |
750 __ subl(rax, Immediate(1)); | 750 __ subl(rax, Immediate(1)); |
751 __ j(not_zero, &no_deopt, Label::kNear); | 751 __ j(not_zero, &no_deopt, Label::kNear); |
752 if (FLAG_trap_on_deopt) __ int3(); | 752 if (FLAG_trap_on_deopt) __ int3(); |
753 __ movl(rax, Immediate(FLAG_deopt_every_n_times)); | 753 __ movl(rax, Immediate(FLAG_deopt_every_n_times)); |
754 __ movl(count_operand, rax); | 754 __ movl(count_operand, rax); |
755 __ popq(rax); | 755 __ popq(rax); |
756 __ popfq(); | 756 __ popfq(); |
757 ASSERT(frame_is_built_); | 757 DCHECK(frame_is_built_); |
758 __ call(entry, RelocInfo::RUNTIME_ENTRY); | 758 __ call(entry, RelocInfo::RUNTIME_ENTRY); |
759 __ bind(&no_deopt); | 759 __ bind(&no_deopt); |
760 __ movl(count_operand, rax); | 760 __ movl(count_operand, rax); |
761 __ popq(rax); | 761 __ popq(rax); |
762 __ popfq(); | 762 __ popfq(); |
763 } | 763 } |
764 | 764 |
765 if (info()->ShouldTrapOnDeopt()) { | 765 if (info()->ShouldTrapOnDeopt()) { |
766 Label done; | 766 Label done; |
767 if (cc != no_condition) { | 767 if (cc != no_condition) { |
768 __ j(NegateCondition(cc), &done, Label::kNear); | 768 __ j(NegateCondition(cc), &done, Label::kNear); |
769 } | 769 } |
770 __ int3(); | 770 __ int3(); |
771 __ bind(&done); | 771 __ bind(&done); |
772 } | 772 } |
773 | 773 |
774 ASSERT(info()->IsStub() || frame_is_built_); | 774 DCHECK(info()->IsStub() || frame_is_built_); |
775 // Go through jump table if we need to handle condition, build frame, or | 775 // Go through jump table if we need to handle condition, build frame, or |
776 // restore caller doubles. | 776 // restore caller doubles. |
777 if (cc == no_condition && frame_is_built_ && | 777 if (cc == no_condition && frame_is_built_ && |
778 !info()->saves_caller_doubles()) { | 778 !info()->saves_caller_doubles()) { |
779 __ call(entry, RelocInfo::RUNTIME_ENTRY); | 779 __ call(entry, RelocInfo::RUNTIME_ENTRY); |
780 } else { | 780 } else { |
781 // We often have several deopts to the same entry, reuse the last | 781 // We often have several deopts to the same entry, reuse the last |
782 // jump entry if this is the case. | 782 // jump entry if this is the case. |
783 if (jump_table_.is_empty() || | 783 if (jump_table_.is_empty() || |
784 jump_table_.last().address != entry || | 784 jump_table_.last().address != entry || |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
855 int result = deoptimization_literals_.length(); | 855 int result = deoptimization_literals_.length(); |
856 for (int i = 0; i < deoptimization_literals_.length(); ++i) { | 856 for (int i = 0; i < deoptimization_literals_.length(); ++i) { |
857 if (deoptimization_literals_[i].is_identical_to(literal)) return i; | 857 if (deoptimization_literals_[i].is_identical_to(literal)) return i; |
858 } | 858 } |
859 deoptimization_literals_.Add(literal, zone()); | 859 deoptimization_literals_.Add(literal, zone()); |
860 return result; | 860 return result; |
861 } | 861 } |
862 | 862 |
863 | 863 |
864 void LCodeGen::PopulateDeoptimizationLiteralsWithInlinedFunctions() { | 864 void LCodeGen::PopulateDeoptimizationLiteralsWithInlinedFunctions() { |
865 ASSERT(deoptimization_literals_.length() == 0); | 865 DCHECK(deoptimization_literals_.length() == 0); |
866 | 866 |
867 const ZoneList<Handle<JSFunction> >* inlined_closures = | 867 const ZoneList<Handle<JSFunction> >* inlined_closures = |
868 chunk()->inlined_closures(); | 868 chunk()->inlined_closures(); |
869 | 869 |
870 for (int i = 0, length = inlined_closures->length(); | 870 for (int i = 0, length = inlined_closures->length(); |
871 i < length; | 871 i < length; |
872 i++) { | 872 i++) { |
873 DefineDeoptimizationLiteral(inlined_closures->at(i)); | 873 DefineDeoptimizationLiteral(inlined_closures->at(i)); |
874 } | 874 } |
875 | 875 |
876 inlined_function_count_ = deoptimization_literals_.length(); | 876 inlined_function_count_ = deoptimization_literals_.length(); |
877 } | 877 } |
878 | 878 |
879 | 879 |
880 void LCodeGen::RecordSafepointWithLazyDeopt( | 880 void LCodeGen::RecordSafepointWithLazyDeopt( |
881 LInstruction* instr, SafepointMode safepoint_mode, int argc) { | 881 LInstruction* instr, SafepointMode safepoint_mode, int argc) { |
882 if (safepoint_mode == RECORD_SIMPLE_SAFEPOINT) { | 882 if (safepoint_mode == RECORD_SIMPLE_SAFEPOINT) { |
883 RecordSafepoint(instr->pointer_map(), Safepoint::kLazyDeopt); | 883 RecordSafepoint(instr->pointer_map(), Safepoint::kLazyDeopt); |
884 } else { | 884 } else { |
885 ASSERT(safepoint_mode == RECORD_SAFEPOINT_WITH_REGISTERS); | 885 DCHECK(safepoint_mode == RECORD_SAFEPOINT_WITH_REGISTERS); |
886 RecordSafepointWithRegisters( | 886 RecordSafepointWithRegisters( |
887 instr->pointer_map(), argc, Safepoint::kLazyDeopt); | 887 instr->pointer_map(), argc, Safepoint::kLazyDeopt); |
888 } | 888 } |
889 } | 889 } |
890 | 890 |
891 | 891 |
892 void LCodeGen::RecordSafepoint( | 892 void LCodeGen::RecordSafepoint( |
893 LPointerMap* pointers, | 893 LPointerMap* pointers, |
894 Safepoint::Kind kind, | 894 Safepoint::Kind kind, |
895 int arguments, | 895 int arguments, |
896 Safepoint::DeoptMode deopt_mode) { | 896 Safepoint::DeoptMode deopt_mode) { |
897 ASSERT(kind == expected_safepoint_kind_); | 897 DCHECK(kind == expected_safepoint_kind_); |
898 | 898 |
899 const ZoneList<LOperand*>* operands = pointers->GetNormalizedOperands(); | 899 const ZoneList<LOperand*>* operands = pointers->GetNormalizedOperands(); |
900 | 900 |
901 Safepoint safepoint = safepoints_.DefineSafepoint(masm(), | 901 Safepoint safepoint = safepoints_.DefineSafepoint(masm(), |
902 kind, arguments, deopt_mode); | 902 kind, arguments, deopt_mode); |
903 for (int i = 0; i < operands->length(); i++) { | 903 for (int i = 0; i < operands->length(); i++) { |
904 LOperand* pointer = operands->at(i); | 904 LOperand* pointer = operands->at(i); |
905 if (pointer->IsStackSlot()) { | 905 if (pointer->IsStackSlot()) { |
906 safepoint.DefinePointerSlot(pointer->index(), zone()); | 906 safepoint.DefinePointerSlot(pointer->index(), zone()); |
907 } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) { | 907 } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) { |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
976 DoGap(instr); | 976 DoGap(instr); |
977 } | 977 } |
978 | 978 |
979 | 979 |
980 void LCodeGen::DoParameter(LParameter* instr) { | 980 void LCodeGen::DoParameter(LParameter* instr) { |
981 // Nothing to do. | 981 // Nothing to do. |
982 } | 982 } |
983 | 983 |
984 | 984 |
985 void LCodeGen::DoCallStub(LCallStub* instr) { | 985 void LCodeGen::DoCallStub(LCallStub* instr) { |
986 ASSERT(ToRegister(instr->context()).is(rsi)); | 986 DCHECK(ToRegister(instr->context()).is(rsi)); |
987 ASSERT(ToRegister(instr->result()).is(rax)); | 987 DCHECK(ToRegister(instr->result()).is(rax)); |
988 switch (instr->hydrogen()->major_key()) { | 988 switch (instr->hydrogen()->major_key()) { |
989 case CodeStub::RegExpExec: { | 989 case CodeStub::RegExpExec: { |
990 RegExpExecStub stub(isolate()); | 990 RegExpExecStub stub(isolate()); |
991 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 991 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
992 break; | 992 break; |
993 } | 993 } |
994 case CodeStub::SubString: { | 994 case CodeStub::SubString: { |
995 SubStringStub stub(isolate()); | 995 SubStringStub stub(isolate()); |
996 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 996 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
997 break; | 997 break; |
(...skipping 10 matching lines...) Expand all Loading... |
1008 | 1008 |
1009 | 1009 |
1010 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { | 1010 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { |
1011 GenerateOsrPrologue(); | 1011 GenerateOsrPrologue(); |
1012 } | 1012 } |
1013 | 1013 |
1014 | 1014 |
1015 void LCodeGen::DoModByPowerOf2I(LModByPowerOf2I* instr) { | 1015 void LCodeGen::DoModByPowerOf2I(LModByPowerOf2I* instr) { |
1016 Register dividend = ToRegister(instr->dividend()); | 1016 Register dividend = ToRegister(instr->dividend()); |
1017 int32_t divisor = instr->divisor(); | 1017 int32_t divisor = instr->divisor(); |
1018 ASSERT(dividend.is(ToRegister(instr->result()))); | 1018 DCHECK(dividend.is(ToRegister(instr->result()))); |
1019 | 1019 |
1020 // Theoretically, a variation of the branch-free code for integer division by | 1020 // Theoretically, a variation of the branch-free code for integer division by |
1021 // a power of 2 (calculating the remainder via an additional multiplication | 1021 // a power of 2 (calculating the remainder via an additional multiplication |
1022 // (which gets simplified to an 'and') and subtraction) should be faster, and | 1022 // (which gets simplified to an 'and') and subtraction) should be faster, and |
1023 // this is exactly what GCC and clang emit. Nevertheless, benchmarks seem to | 1023 // this is exactly what GCC and clang emit. Nevertheless, benchmarks seem to |
1024 // indicate that positive dividends are heavily favored, so the branching | 1024 // indicate that positive dividends are heavily favored, so the branching |
1025 // version performs better. | 1025 // version performs better. |
1026 HMod* hmod = instr->hydrogen(); | 1026 HMod* hmod = instr->hydrogen(); |
1027 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); | 1027 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); |
1028 Label dividend_is_not_negative, done; | 1028 Label dividend_is_not_negative, done; |
(...skipping 12 matching lines...) Expand all Loading... |
1041 | 1041 |
1042 __ bind(÷nd_is_not_negative); | 1042 __ bind(÷nd_is_not_negative); |
1043 __ andl(dividend, Immediate(mask)); | 1043 __ andl(dividend, Immediate(mask)); |
1044 __ bind(&done); | 1044 __ bind(&done); |
1045 } | 1045 } |
1046 | 1046 |
1047 | 1047 |
1048 void LCodeGen::DoModByConstI(LModByConstI* instr) { | 1048 void LCodeGen::DoModByConstI(LModByConstI* instr) { |
1049 Register dividend = ToRegister(instr->dividend()); | 1049 Register dividend = ToRegister(instr->dividend()); |
1050 int32_t divisor = instr->divisor(); | 1050 int32_t divisor = instr->divisor(); |
1051 ASSERT(ToRegister(instr->result()).is(rax)); | 1051 DCHECK(ToRegister(instr->result()).is(rax)); |
1052 | 1052 |
1053 if (divisor == 0) { | 1053 if (divisor == 0) { |
1054 DeoptimizeIf(no_condition, instr->environment()); | 1054 DeoptimizeIf(no_condition, instr->environment()); |
1055 return; | 1055 return; |
1056 } | 1056 } |
1057 | 1057 |
1058 __ TruncatingDiv(dividend, Abs(divisor)); | 1058 __ TruncatingDiv(dividend, Abs(divisor)); |
1059 __ imull(rdx, rdx, Immediate(Abs(divisor))); | 1059 __ imull(rdx, rdx, Immediate(Abs(divisor))); |
1060 __ movl(rax, dividend); | 1060 __ movl(rax, dividend); |
1061 __ subl(rax, rdx); | 1061 __ subl(rax, rdx); |
1062 | 1062 |
1063 // Check for negative zero. | 1063 // Check for negative zero. |
1064 HMod* hmod = instr->hydrogen(); | 1064 HMod* hmod = instr->hydrogen(); |
1065 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1065 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1066 Label remainder_not_zero; | 1066 Label remainder_not_zero; |
1067 __ j(not_zero, &remainder_not_zero, Label::kNear); | 1067 __ j(not_zero, &remainder_not_zero, Label::kNear); |
1068 __ cmpl(dividend, Immediate(0)); | 1068 __ cmpl(dividend, Immediate(0)); |
1069 DeoptimizeIf(less, instr->environment()); | 1069 DeoptimizeIf(less, instr->environment()); |
1070 __ bind(&remainder_not_zero); | 1070 __ bind(&remainder_not_zero); |
1071 } | 1071 } |
1072 } | 1072 } |
1073 | 1073 |
1074 | 1074 |
1075 void LCodeGen::DoModI(LModI* instr) { | 1075 void LCodeGen::DoModI(LModI* instr) { |
1076 HMod* hmod = instr->hydrogen(); | 1076 HMod* hmod = instr->hydrogen(); |
1077 | 1077 |
1078 Register left_reg = ToRegister(instr->left()); | 1078 Register left_reg = ToRegister(instr->left()); |
1079 ASSERT(left_reg.is(rax)); | 1079 DCHECK(left_reg.is(rax)); |
1080 Register right_reg = ToRegister(instr->right()); | 1080 Register right_reg = ToRegister(instr->right()); |
1081 ASSERT(!right_reg.is(rax)); | 1081 DCHECK(!right_reg.is(rax)); |
1082 ASSERT(!right_reg.is(rdx)); | 1082 DCHECK(!right_reg.is(rdx)); |
1083 Register result_reg = ToRegister(instr->result()); | 1083 Register result_reg = ToRegister(instr->result()); |
1084 ASSERT(result_reg.is(rdx)); | 1084 DCHECK(result_reg.is(rdx)); |
1085 | 1085 |
1086 Label done; | 1086 Label done; |
1087 // Check for x % 0, idiv would signal a divide error. We have to | 1087 // Check for x % 0, idiv would signal a divide error. We have to |
1088 // deopt in this case because we can't return a NaN. | 1088 // deopt in this case because we can't return a NaN. |
1089 if (hmod->CheckFlag(HValue::kCanBeDivByZero)) { | 1089 if (hmod->CheckFlag(HValue::kCanBeDivByZero)) { |
1090 __ testl(right_reg, right_reg); | 1090 __ testl(right_reg, right_reg); |
1091 DeoptimizeIf(zero, instr->environment()); | 1091 DeoptimizeIf(zero, instr->environment()); |
1092 } | 1092 } |
1093 | 1093 |
1094 // Check for kMinInt % -1, idiv would signal a divide error. We | 1094 // Check for kMinInt % -1, idiv would signal a divide error. We |
(...skipping 29 matching lines...) Expand all Loading... |
1124 __ bind(&positive_left); | 1124 __ bind(&positive_left); |
1125 } | 1125 } |
1126 __ idivl(right_reg); | 1126 __ idivl(right_reg); |
1127 __ bind(&done); | 1127 __ bind(&done); |
1128 } | 1128 } |
1129 | 1129 |
1130 | 1130 |
1131 void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) { | 1131 void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) { |
1132 Register dividend = ToRegister(instr->dividend()); | 1132 Register dividend = ToRegister(instr->dividend()); |
1133 int32_t divisor = instr->divisor(); | 1133 int32_t divisor = instr->divisor(); |
1134 ASSERT(dividend.is(ToRegister(instr->result()))); | 1134 DCHECK(dividend.is(ToRegister(instr->result()))); |
1135 | 1135 |
1136 // If the divisor is positive, things are easy: There can be no deopts and we | 1136 // If the divisor is positive, things are easy: There can be no deopts and we |
1137 // can simply do an arithmetic right shift. | 1137 // can simply do an arithmetic right shift. |
1138 if (divisor == 1) return; | 1138 if (divisor == 1) return; |
1139 int32_t shift = WhichPowerOf2Abs(divisor); | 1139 int32_t shift = WhichPowerOf2Abs(divisor); |
1140 if (divisor > 1) { | 1140 if (divisor > 1) { |
1141 __ sarl(dividend, Immediate(shift)); | 1141 __ sarl(dividend, Immediate(shift)); |
1142 return; | 1142 return; |
1143 } | 1143 } |
1144 | 1144 |
(...skipping 23 matching lines...) Expand all Loading... |
1168 __ jmp(&done, Label::kNear); | 1168 __ jmp(&done, Label::kNear); |
1169 __ bind(¬_kmin_int); | 1169 __ bind(¬_kmin_int); |
1170 __ sarl(dividend, Immediate(shift)); | 1170 __ sarl(dividend, Immediate(shift)); |
1171 __ bind(&done); | 1171 __ bind(&done); |
1172 } | 1172 } |
1173 | 1173 |
1174 | 1174 |
1175 void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) { | 1175 void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) { |
1176 Register dividend = ToRegister(instr->dividend()); | 1176 Register dividend = ToRegister(instr->dividend()); |
1177 int32_t divisor = instr->divisor(); | 1177 int32_t divisor = instr->divisor(); |
1178 ASSERT(ToRegister(instr->result()).is(rdx)); | 1178 DCHECK(ToRegister(instr->result()).is(rdx)); |
1179 | 1179 |
1180 if (divisor == 0) { | 1180 if (divisor == 0) { |
1181 DeoptimizeIf(no_condition, instr->environment()); | 1181 DeoptimizeIf(no_condition, instr->environment()); |
1182 return; | 1182 return; |
1183 } | 1183 } |
1184 | 1184 |
1185 // Check for (0 / -x) that will produce negative zero. | 1185 // Check for (0 / -x) that will produce negative zero. |
1186 HMathFloorOfDiv* hdiv = instr->hydrogen(); | 1186 HMathFloorOfDiv* hdiv = instr->hydrogen(); |
1187 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { | 1187 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { |
1188 __ testl(dividend, dividend); | 1188 __ testl(dividend, dividend); |
1189 DeoptimizeIf(zero, instr->environment()); | 1189 DeoptimizeIf(zero, instr->environment()); |
1190 } | 1190 } |
1191 | 1191 |
1192 // Easy case: We need no dynamic check for the dividend and the flooring | 1192 // Easy case: We need no dynamic check for the dividend and the flooring |
1193 // division is the same as the truncating division. | 1193 // division is the same as the truncating division. |
1194 if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) || | 1194 if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) || |
1195 (divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) { | 1195 (divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) { |
1196 __ TruncatingDiv(dividend, Abs(divisor)); | 1196 __ TruncatingDiv(dividend, Abs(divisor)); |
1197 if (divisor < 0) __ negl(rdx); | 1197 if (divisor < 0) __ negl(rdx); |
1198 return; | 1198 return; |
1199 } | 1199 } |
1200 | 1200 |
1201 // In the general case we may need to adjust before and after the truncating | 1201 // In the general case we may need to adjust before and after the truncating |
1202 // division to get a flooring division. | 1202 // division to get a flooring division. |
1203 Register temp = ToRegister(instr->temp3()); | 1203 Register temp = ToRegister(instr->temp3()); |
1204 ASSERT(!temp.is(dividend) && !temp.is(rax) && !temp.is(rdx)); | 1204 DCHECK(!temp.is(dividend) && !temp.is(rax) && !temp.is(rdx)); |
1205 Label needs_adjustment, done; | 1205 Label needs_adjustment, done; |
1206 __ cmpl(dividend, Immediate(0)); | 1206 __ cmpl(dividend, Immediate(0)); |
1207 __ j(divisor > 0 ? less : greater, &needs_adjustment, Label::kNear); | 1207 __ j(divisor > 0 ? less : greater, &needs_adjustment, Label::kNear); |
1208 __ TruncatingDiv(dividend, Abs(divisor)); | 1208 __ TruncatingDiv(dividend, Abs(divisor)); |
1209 if (divisor < 0) __ negl(rdx); | 1209 if (divisor < 0) __ negl(rdx); |
1210 __ jmp(&done, Label::kNear); | 1210 __ jmp(&done, Label::kNear); |
1211 __ bind(&needs_adjustment); | 1211 __ bind(&needs_adjustment); |
1212 __ leal(temp, Operand(dividend, divisor > 0 ? 1 : -1)); | 1212 __ leal(temp, Operand(dividend, divisor > 0 ? 1 : -1)); |
1213 __ TruncatingDiv(temp, Abs(divisor)); | 1213 __ TruncatingDiv(temp, Abs(divisor)); |
1214 if (divisor < 0) __ negl(rdx); | 1214 if (divisor < 0) __ negl(rdx); |
1215 __ decl(rdx); | 1215 __ decl(rdx); |
1216 __ bind(&done); | 1216 __ bind(&done); |
1217 } | 1217 } |
1218 | 1218 |
1219 | 1219 |
1220 // TODO(svenpanne) Refactor this to avoid code duplication with DoDivI. | 1220 // TODO(svenpanne) Refactor this to avoid code duplication with DoDivI. |
1221 void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) { | 1221 void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) { |
1222 HBinaryOperation* hdiv = instr->hydrogen(); | 1222 HBinaryOperation* hdiv = instr->hydrogen(); |
1223 Register dividend = ToRegister(instr->dividend()); | 1223 Register dividend = ToRegister(instr->dividend()); |
1224 Register divisor = ToRegister(instr->divisor()); | 1224 Register divisor = ToRegister(instr->divisor()); |
1225 Register remainder = ToRegister(instr->temp()); | 1225 Register remainder = ToRegister(instr->temp()); |
1226 Register result = ToRegister(instr->result()); | 1226 Register result = ToRegister(instr->result()); |
1227 ASSERT(dividend.is(rax)); | 1227 DCHECK(dividend.is(rax)); |
1228 ASSERT(remainder.is(rdx)); | 1228 DCHECK(remainder.is(rdx)); |
1229 ASSERT(result.is(rax)); | 1229 DCHECK(result.is(rax)); |
1230 ASSERT(!divisor.is(rax)); | 1230 DCHECK(!divisor.is(rax)); |
1231 ASSERT(!divisor.is(rdx)); | 1231 DCHECK(!divisor.is(rdx)); |
1232 | 1232 |
1233 // Check for x / 0. | 1233 // Check for x / 0. |
1234 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { | 1234 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { |
1235 __ testl(divisor, divisor); | 1235 __ testl(divisor, divisor); |
1236 DeoptimizeIf(zero, instr->environment()); | 1236 DeoptimizeIf(zero, instr->environment()); |
1237 } | 1237 } |
1238 | 1238 |
1239 // Check for (0 / -x) that will produce negative zero. | 1239 // Check for (0 / -x) that will produce negative zero. |
1240 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1240 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1241 Label dividend_not_zero; | 1241 Label dividend_not_zero; |
(...skipping 25 matching lines...) Expand all Loading... |
1267 __ sarl(remainder, Immediate(31)); | 1267 __ sarl(remainder, Immediate(31)); |
1268 __ addl(result, remainder); | 1268 __ addl(result, remainder); |
1269 __ bind(&done); | 1269 __ bind(&done); |
1270 } | 1270 } |
1271 | 1271 |
1272 | 1272 |
1273 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) { | 1273 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) { |
1274 Register dividend = ToRegister(instr->dividend()); | 1274 Register dividend = ToRegister(instr->dividend()); |
1275 int32_t divisor = instr->divisor(); | 1275 int32_t divisor = instr->divisor(); |
1276 Register result = ToRegister(instr->result()); | 1276 Register result = ToRegister(instr->result()); |
1277 ASSERT(divisor == kMinInt || IsPowerOf2(Abs(divisor))); | 1277 DCHECK(divisor == kMinInt || IsPowerOf2(Abs(divisor))); |
1278 ASSERT(!result.is(dividend)); | 1278 DCHECK(!result.is(dividend)); |
1279 | 1279 |
1280 // Check for (0 / -x) that will produce negative zero. | 1280 // Check for (0 / -x) that will produce negative zero. |
1281 HDiv* hdiv = instr->hydrogen(); | 1281 HDiv* hdiv = instr->hydrogen(); |
1282 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { | 1282 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { |
1283 __ testl(dividend, dividend); | 1283 __ testl(dividend, dividend); |
1284 DeoptimizeIf(zero, instr->environment()); | 1284 DeoptimizeIf(zero, instr->environment()); |
1285 } | 1285 } |
1286 // Check for (kMinInt / -1). | 1286 // Check for (kMinInt / -1). |
1287 if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) { | 1287 if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) { |
1288 __ cmpl(dividend, Immediate(kMinInt)); | 1288 __ cmpl(dividend, Immediate(kMinInt)); |
(...skipping 15 matching lines...) Expand all Loading... |
1304 __ addl(result, dividend); | 1304 __ addl(result, dividend); |
1305 __ sarl(result, Immediate(shift)); | 1305 __ sarl(result, Immediate(shift)); |
1306 } | 1306 } |
1307 if (divisor < 0) __ negl(result); | 1307 if (divisor < 0) __ negl(result); |
1308 } | 1308 } |
1309 | 1309 |
1310 | 1310 |
1311 void LCodeGen::DoDivByConstI(LDivByConstI* instr) { | 1311 void LCodeGen::DoDivByConstI(LDivByConstI* instr) { |
1312 Register dividend = ToRegister(instr->dividend()); | 1312 Register dividend = ToRegister(instr->dividend()); |
1313 int32_t divisor = instr->divisor(); | 1313 int32_t divisor = instr->divisor(); |
1314 ASSERT(ToRegister(instr->result()).is(rdx)); | 1314 DCHECK(ToRegister(instr->result()).is(rdx)); |
1315 | 1315 |
1316 if (divisor == 0) { | 1316 if (divisor == 0) { |
1317 DeoptimizeIf(no_condition, instr->environment()); | 1317 DeoptimizeIf(no_condition, instr->environment()); |
1318 return; | 1318 return; |
1319 } | 1319 } |
1320 | 1320 |
1321 // Check for (0 / -x) that will produce negative zero. | 1321 // Check for (0 / -x) that will produce negative zero. |
1322 HDiv* hdiv = instr->hydrogen(); | 1322 HDiv* hdiv = instr->hydrogen(); |
1323 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { | 1323 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { |
1324 __ testl(dividend, dividend); | 1324 __ testl(dividend, dividend); |
(...skipping 11 matching lines...) Expand all Loading... |
1336 } | 1336 } |
1337 } | 1337 } |
1338 | 1338 |
1339 | 1339 |
1340 // TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI. | 1340 // TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI. |
1341 void LCodeGen::DoDivI(LDivI* instr) { | 1341 void LCodeGen::DoDivI(LDivI* instr) { |
1342 HBinaryOperation* hdiv = instr->hydrogen(); | 1342 HBinaryOperation* hdiv = instr->hydrogen(); |
1343 Register dividend = ToRegister(instr->dividend()); | 1343 Register dividend = ToRegister(instr->dividend()); |
1344 Register divisor = ToRegister(instr->divisor()); | 1344 Register divisor = ToRegister(instr->divisor()); |
1345 Register remainder = ToRegister(instr->temp()); | 1345 Register remainder = ToRegister(instr->temp()); |
1346 ASSERT(dividend.is(rax)); | 1346 DCHECK(dividend.is(rax)); |
1347 ASSERT(remainder.is(rdx)); | 1347 DCHECK(remainder.is(rdx)); |
1348 ASSERT(ToRegister(instr->result()).is(rax)); | 1348 DCHECK(ToRegister(instr->result()).is(rax)); |
1349 ASSERT(!divisor.is(rax)); | 1349 DCHECK(!divisor.is(rax)); |
1350 ASSERT(!divisor.is(rdx)); | 1350 DCHECK(!divisor.is(rdx)); |
1351 | 1351 |
1352 // Check for x / 0. | 1352 // Check for x / 0. |
1353 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { | 1353 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { |
1354 __ testl(divisor, divisor); | 1354 __ testl(divisor, divisor); |
1355 DeoptimizeIf(zero, instr->environment()); | 1355 DeoptimizeIf(zero, instr->environment()); |
1356 } | 1356 } |
1357 | 1357 |
1358 // Check for (0 / -x) that will produce negative zero. | 1358 // Check for (0 / -x) that will produce negative zero. |
1359 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1359 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1360 Label dividend_not_zero; | 1360 Label dividend_not_zero; |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1467 Label done; | 1467 Label done; |
1468 if (instr->hydrogen_value()->representation().IsSmi()) { | 1468 if (instr->hydrogen_value()->representation().IsSmi()) { |
1469 __ testp(left, left); | 1469 __ testp(left, left); |
1470 } else { | 1470 } else { |
1471 __ testl(left, left); | 1471 __ testl(left, left); |
1472 } | 1472 } |
1473 __ j(not_zero, &done, Label::kNear); | 1473 __ j(not_zero, &done, Label::kNear); |
1474 if (right->IsConstantOperand()) { | 1474 if (right->IsConstantOperand()) { |
1475 // Constant can't be represented as 32-bit Smi due to immediate size | 1475 // Constant can't be represented as 32-bit Smi due to immediate size |
1476 // limit. | 1476 // limit. |
1477 ASSERT(SmiValuesAre32Bits() | 1477 DCHECK(SmiValuesAre32Bits() |
1478 ? !instr->hydrogen_value()->representation().IsSmi() | 1478 ? !instr->hydrogen_value()->representation().IsSmi() |
1479 : SmiValuesAre31Bits()); | 1479 : SmiValuesAre31Bits()); |
1480 if (ToInteger32(LConstantOperand::cast(right)) < 0) { | 1480 if (ToInteger32(LConstantOperand::cast(right)) < 0) { |
1481 DeoptimizeIf(no_condition, instr->environment()); | 1481 DeoptimizeIf(no_condition, instr->environment()); |
1482 } else if (ToInteger32(LConstantOperand::cast(right)) == 0) { | 1482 } else if (ToInteger32(LConstantOperand::cast(right)) == 0) { |
1483 __ cmpl(kScratchRegister, Immediate(0)); | 1483 __ cmpl(kScratchRegister, Immediate(0)); |
1484 DeoptimizeIf(less, instr->environment()); | 1484 DeoptimizeIf(less, instr->environment()); |
1485 } | 1485 } |
1486 } else if (right->IsStackSlot()) { | 1486 } else if (right->IsStackSlot()) { |
1487 if (instr->hydrogen_value()->representation().IsSmi()) { | 1487 if (instr->hydrogen_value()->representation().IsSmi()) { |
(...skipping 12 matching lines...) Expand all Loading... |
1500 DeoptimizeIf(sign, instr->environment()); | 1500 DeoptimizeIf(sign, instr->environment()); |
1501 } | 1501 } |
1502 __ bind(&done); | 1502 __ bind(&done); |
1503 } | 1503 } |
1504 } | 1504 } |
1505 | 1505 |
1506 | 1506 |
1507 void LCodeGen::DoBitI(LBitI* instr) { | 1507 void LCodeGen::DoBitI(LBitI* instr) { |
1508 LOperand* left = instr->left(); | 1508 LOperand* left = instr->left(); |
1509 LOperand* right = instr->right(); | 1509 LOperand* right = instr->right(); |
1510 ASSERT(left->Equals(instr->result())); | 1510 DCHECK(left->Equals(instr->result())); |
1511 ASSERT(left->IsRegister()); | 1511 DCHECK(left->IsRegister()); |
1512 | 1512 |
1513 if (right->IsConstantOperand()) { | 1513 if (right->IsConstantOperand()) { |
1514 int32_t right_operand = | 1514 int32_t right_operand = |
1515 ToRepresentation(LConstantOperand::cast(right), | 1515 ToRepresentation(LConstantOperand::cast(right), |
1516 instr->hydrogen()->right()->representation()); | 1516 instr->hydrogen()->right()->representation()); |
1517 switch (instr->op()) { | 1517 switch (instr->op()) { |
1518 case Token::BIT_AND: | 1518 case Token::BIT_AND: |
1519 __ andl(ToRegister(left), Immediate(right_operand)); | 1519 __ andl(ToRegister(left), Immediate(right_operand)); |
1520 break; | 1520 break; |
1521 case Token::BIT_OR: | 1521 case Token::BIT_OR: |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1553 __ xorl(ToRegister(left), ToOperand(right)); | 1553 __ xorl(ToRegister(left), ToOperand(right)); |
1554 } else { | 1554 } else { |
1555 __ xorp(ToRegister(left), ToOperand(right)); | 1555 __ xorp(ToRegister(left), ToOperand(right)); |
1556 } | 1556 } |
1557 break; | 1557 break; |
1558 default: | 1558 default: |
1559 UNREACHABLE(); | 1559 UNREACHABLE(); |
1560 break; | 1560 break; |
1561 } | 1561 } |
1562 } else { | 1562 } else { |
1563 ASSERT(right->IsRegister()); | 1563 DCHECK(right->IsRegister()); |
1564 switch (instr->op()) { | 1564 switch (instr->op()) { |
1565 case Token::BIT_AND: | 1565 case Token::BIT_AND: |
1566 if (instr->IsInteger32()) { | 1566 if (instr->IsInteger32()) { |
1567 __ andl(ToRegister(left), ToRegister(right)); | 1567 __ andl(ToRegister(left), ToRegister(right)); |
1568 } else { | 1568 } else { |
1569 __ andp(ToRegister(left), ToRegister(right)); | 1569 __ andp(ToRegister(left), ToRegister(right)); |
1570 } | 1570 } |
1571 break; | 1571 break; |
1572 case Token::BIT_OR: | 1572 case Token::BIT_OR: |
1573 if (instr->IsInteger32()) { | 1573 if (instr->IsInteger32()) { |
(...skipping 13 matching lines...) Expand all Loading... |
1587 UNREACHABLE(); | 1587 UNREACHABLE(); |
1588 break; | 1588 break; |
1589 } | 1589 } |
1590 } | 1590 } |
1591 } | 1591 } |
1592 | 1592 |
1593 | 1593 |
1594 void LCodeGen::DoShiftI(LShiftI* instr) { | 1594 void LCodeGen::DoShiftI(LShiftI* instr) { |
1595 LOperand* left = instr->left(); | 1595 LOperand* left = instr->left(); |
1596 LOperand* right = instr->right(); | 1596 LOperand* right = instr->right(); |
1597 ASSERT(left->Equals(instr->result())); | 1597 DCHECK(left->Equals(instr->result())); |
1598 ASSERT(left->IsRegister()); | 1598 DCHECK(left->IsRegister()); |
1599 if (right->IsRegister()) { | 1599 if (right->IsRegister()) { |
1600 ASSERT(ToRegister(right).is(rcx)); | 1600 DCHECK(ToRegister(right).is(rcx)); |
1601 | 1601 |
1602 switch (instr->op()) { | 1602 switch (instr->op()) { |
1603 case Token::ROR: | 1603 case Token::ROR: |
1604 __ rorl_cl(ToRegister(left)); | 1604 __ rorl_cl(ToRegister(left)); |
1605 break; | 1605 break; |
1606 case Token::SAR: | 1606 case Token::SAR: |
1607 __ sarl_cl(ToRegister(left)); | 1607 __ sarl_cl(ToRegister(left)); |
1608 break; | 1608 break; |
1609 case Token::SHR: | 1609 case Token::SHR: |
1610 __ shrl_cl(ToRegister(left)); | 1610 __ shrl_cl(ToRegister(left)); |
(...skipping 30 matching lines...) Expand all Loading... |
1641 __ testl(ToRegister(left), ToRegister(left)); | 1641 __ testl(ToRegister(left), ToRegister(left)); |
1642 DeoptimizeIf(negative, instr->environment()); | 1642 DeoptimizeIf(negative, instr->environment()); |
1643 } | 1643 } |
1644 break; | 1644 break; |
1645 case Token::SHL: | 1645 case Token::SHL: |
1646 if (shift_count != 0) { | 1646 if (shift_count != 0) { |
1647 if (instr->hydrogen_value()->representation().IsSmi()) { | 1647 if (instr->hydrogen_value()->representation().IsSmi()) { |
1648 if (SmiValuesAre32Bits()) { | 1648 if (SmiValuesAre32Bits()) { |
1649 __ shlp(ToRegister(left), Immediate(shift_count)); | 1649 __ shlp(ToRegister(left), Immediate(shift_count)); |
1650 } else { | 1650 } else { |
1651 ASSERT(SmiValuesAre31Bits()); | 1651 DCHECK(SmiValuesAre31Bits()); |
1652 if (instr->can_deopt()) { | 1652 if (instr->can_deopt()) { |
1653 if (shift_count != 1) { | 1653 if (shift_count != 1) { |
1654 __ shll(ToRegister(left), Immediate(shift_count - 1)); | 1654 __ shll(ToRegister(left), Immediate(shift_count - 1)); |
1655 } | 1655 } |
1656 __ Integer32ToSmi(ToRegister(left), ToRegister(left)); | 1656 __ Integer32ToSmi(ToRegister(left), ToRegister(left)); |
1657 DeoptimizeIf(overflow, instr->environment()); | 1657 DeoptimizeIf(overflow, instr->environment()); |
1658 } else { | 1658 } else { |
1659 __ shll(ToRegister(left), Immediate(shift_count)); | 1659 __ shll(ToRegister(left), Immediate(shift_count)); |
1660 } | 1660 } |
1661 } | 1661 } |
1662 } else { | 1662 } else { |
1663 __ shll(ToRegister(left), Immediate(shift_count)); | 1663 __ shll(ToRegister(left), Immediate(shift_count)); |
1664 } | 1664 } |
1665 } | 1665 } |
1666 break; | 1666 break; |
1667 default: | 1667 default: |
1668 UNREACHABLE(); | 1668 UNREACHABLE(); |
1669 break; | 1669 break; |
1670 } | 1670 } |
1671 } | 1671 } |
1672 } | 1672 } |
1673 | 1673 |
1674 | 1674 |
1675 void LCodeGen::DoSubI(LSubI* instr) { | 1675 void LCodeGen::DoSubI(LSubI* instr) { |
1676 LOperand* left = instr->left(); | 1676 LOperand* left = instr->left(); |
1677 LOperand* right = instr->right(); | 1677 LOperand* right = instr->right(); |
1678 ASSERT(left->Equals(instr->result())); | 1678 DCHECK(left->Equals(instr->result())); |
1679 | 1679 |
1680 if (right->IsConstantOperand()) { | 1680 if (right->IsConstantOperand()) { |
1681 int32_t right_operand = | 1681 int32_t right_operand = |
1682 ToRepresentation(LConstantOperand::cast(right), | 1682 ToRepresentation(LConstantOperand::cast(right), |
1683 instr->hydrogen()->right()->representation()); | 1683 instr->hydrogen()->right()->representation()); |
1684 __ subl(ToRegister(left), Immediate(right_operand)); | 1684 __ subl(ToRegister(left), Immediate(right_operand)); |
1685 } else if (right->IsRegister()) { | 1685 } else if (right->IsRegister()) { |
1686 if (instr->hydrogen_value()->representation().IsSmi()) { | 1686 if (instr->hydrogen_value()->representation().IsSmi()) { |
1687 __ subp(ToRegister(left), ToRegister(right)); | 1687 __ subp(ToRegister(left), ToRegister(right)); |
1688 } else { | 1688 } else { |
(...skipping 22 matching lines...) Expand all Loading... |
1711 } | 1711 } |
1712 } | 1712 } |
1713 | 1713 |
1714 | 1714 |
1715 void LCodeGen::DoConstantS(LConstantS* instr) { | 1715 void LCodeGen::DoConstantS(LConstantS* instr) { |
1716 __ Move(ToRegister(instr->result()), instr->value()); | 1716 __ Move(ToRegister(instr->result()), instr->value()); |
1717 } | 1717 } |
1718 | 1718 |
1719 | 1719 |
1720 void LCodeGen::DoConstantD(LConstantD* instr) { | 1720 void LCodeGen::DoConstantD(LConstantD* instr) { |
1721 ASSERT(instr->result()->IsDoubleRegister()); | 1721 DCHECK(instr->result()->IsDoubleRegister()); |
1722 XMMRegister res = ToDoubleRegister(instr->result()); | 1722 XMMRegister res = ToDoubleRegister(instr->result()); |
1723 double v = instr->value(); | 1723 double v = instr->value(); |
1724 uint64_t int_val = BitCast<uint64_t, double>(v); | 1724 uint64_t int_val = BitCast<uint64_t, double>(v); |
1725 // Use xor to produce +0.0 in a fast and compact way, but avoid to | 1725 // Use xor to produce +0.0 in a fast and compact way, but avoid to |
1726 // do so if the constant is -0.0. | 1726 // do so if the constant is -0.0. |
1727 if (int_val == 0) { | 1727 if (int_val == 0) { |
1728 __ xorps(res, res); | 1728 __ xorps(res, res); |
1729 } else { | 1729 } else { |
1730 Register tmp = ToRegister(instr->temp()); | 1730 Register tmp = ToRegister(instr->temp()); |
1731 __ Set(tmp, int_val); | 1731 __ Set(tmp, int_val); |
(...skipping 19 matching lines...) Expand all Loading... |
1751 Register map = ToRegister(instr->value()); | 1751 Register map = ToRegister(instr->value()); |
1752 __ EnumLength(result, map); | 1752 __ EnumLength(result, map); |
1753 } | 1753 } |
1754 | 1754 |
1755 | 1755 |
1756 void LCodeGen::DoDateField(LDateField* instr) { | 1756 void LCodeGen::DoDateField(LDateField* instr) { |
1757 Register object = ToRegister(instr->date()); | 1757 Register object = ToRegister(instr->date()); |
1758 Register result = ToRegister(instr->result()); | 1758 Register result = ToRegister(instr->result()); |
1759 Smi* index = instr->index(); | 1759 Smi* index = instr->index(); |
1760 Label runtime, done, not_date_object; | 1760 Label runtime, done, not_date_object; |
1761 ASSERT(object.is(result)); | 1761 DCHECK(object.is(result)); |
1762 ASSERT(object.is(rax)); | 1762 DCHECK(object.is(rax)); |
1763 | 1763 |
1764 Condition cc = masm()->CheckSmi(object); | 1764 Condition cc = masm()->CheckSmi(object); |
1765 DeoptimizeIf(cc, instr->environment()); | 1765 DeoptimizeIf(cc, instr->environment()); |
1766 __ CmpObjectType(object, JS_DATE_TYPE, kScratchRegister); | 1766 __ CmpObjectType(object, JS_DATE_TYPE, kScratchRegister); |
1767 DeoptimizeIf(not_equal, instr->environment()); | 1767 DeoptimizeIf(not_equal, instr->environment()); |
1768 | 1768 |
1769 if (index->value() == 0) { | 1769 if (index->value() == 0) { |
1770 __ movp(result, FieldOperand(object, JSDate::kValueOffset)); | 1770 __ movp(result, FieldOperand(object, JSDate::kValueOffset)); |
1771 } else { | 1771 } else { |
1772 if (index->value() < JSDate::kFirstUncachedField) { | 1772 if (index->value() < JSDate::kFirstUncachedField) { |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1847 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag; | 1847 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag; |
1848 int encoding_mask = | 1848 int encoding_mask = |
1849 instr->hydrogen()->encoding() == String::ONE_BYTE_ENCODING | 1849 instr->hydrogen()->encoding() == String::ONE_BYTE_ENCODING |
1850 ? one_byte_seq_type : two_byte_seq_type; | 1850 ? one_byte_seq_type : two_byte_seq_type; |
1851 __ EmitSeqStringSetCharCheck(string, index, value, encoding_mask); | 1851 __ EmitSeqStringSetCharCheck(string, index, value, encoding_mask); |
1852 } | 1852 } |
1853 | 1853 |
1854 Operand operand = BuildSeqStringOperand(string, instr->index(), encoding); | 1854 Operand operand = BuildSeqStringOperand(string, instr->index(), encoding); |
1855 if (instr->value()->IsConstantOperand()) { | 1855 if (instr->value()->IsConstantOperand()) { |
1856 int value = ToInteger32(LConstantOperand::cast(instr->value())); | 1856 int value = ToInteger32(LConstantOperand::cast(instr->value())); |
1857 ASSERT_LE(0, value); | 1857 DCHECK_LE(0, value); |
1858 if (encoding == String::ONE_BYTE_ENCODING) { | 1858 if (encoding == String::ONE_BYTE_ENCODING) { |
1859 ASSERT_LE(value, String::kMaxOneByteCharCode); | 1859 DCHECK_LE(value, String::kMaxOneByteCharCode); |
1860 __ movb(operand, Immediate(value)); | 1860 __ movb(operand, Immediate(value)); |
1861 } else { | 1861 } else { |
1862 ASSERT_LE(value, String::kMaxUtf16CodeUnit); | 1862 DCHECK_LE(value, String::kMaxUtf16CodeUnit); |
1863 __ movw(operand, Immediate(value)); | 1863 __ movw(operand, Immediate(value)); |
1864 } | 1864 } |
1865 } else { | 1865 } else { |
1866 Register value = ToRegister(instr->value()); | 1866 Register value = ToRegister(instr->value()); |
1867 if (encoding == String::ONE_BYTE_ENCODING) { | 1867 if (encoding == String::ONE_BYTE_ENCODING) { |
1868 __ movb(operand, value); | 1868 __ movb(operand, value); |
1869 } else { | 1869 } else { |
1870 __ movw(operand, value); | 1870 __ movw(operand, value); |
1871 } | 1871 } |
1872 } | 1872 } |
1873 } | 1873 } |
1874 | 1874 |
1875 | 1875 |
1876 void LCodeGen::DoAddI(LAddI* instr) { | 1876 void LCodeGen::DoAddI(LAddI* instr) { |
1877 LOperand* left = instr->left(); | 1877 LOperand* left = instr->left(); |
1878 LOperand* right = instr->right(); | 1878 LOperand* right = instr->right(); |
1879 | 1879 |
1880 Representation target_rep = instr->hydrogen()->representation(); | 1880 Representation target_rep = instr->hydrogen()->representation(); |
1881 bool is_p = target_rep.IsSmi() || target_rep.IsExternal(); | 1881 bool is_p = target_rep.IsSmi() || target_rep.IsExternal(); |
1882 | 1882 |
1883 if (LAddI::UseLea(instr->hydrogen()) && !left->Equals(instr->result())) { | 1883 if (LAddI::UseLea(instr->hydrogen()) && !left->Equals(instr->result())) { |
1884 if (right->IsConstantOperand()) { | 1884 if (right->IsConstantOperand()) { |
1885 // No support for smi-immediates for 32-bit SMI. | 1885 // No support for smi-immediates for 32-bit SMI. |
1886 ASSERT(SmiValuesAre32Bits() ? !target_rep.IsSmi() : SmiValuesAre31Bits()); | 1886 DCHECK(SmiValuesAre32Bits() ? !target_rep.IsSmi() : SmiValuesAre31Bits()); |
1887 int32_t offset = | 1887 int32_t offset = |
1888 ToRepresentation(LConstantOperand::cast(right), | 1888 ToRepresentation(LConstantOperand::cast(right), |
1889 instr->hydrogen()->right()->representation()); | 1889 instr->hydrogen()->right()->representation()); |
1890 if (is_p) { | 1890 if (is_p) { |
1891 __ leap(ToRegister(instr->result()), | 1891 __ leap(ToRegister(instr->result()), |
1892 MemOperand(ToRegister(left), offset)); | 1892 MemOperand(ToRegister(left), offset)); |
1893 } else { | 1893 } else { |
1894 __ leal(ToRegister(instr->result()), | 1894 __ leal(ToRegister(instr->result()), |
1895 MemOperand(ToRegister(left), offset)); | 1895 MemOperand(ToRegister(left), offset)); |
1896 } | 1896 } |
1897 } else { | 1897 } else { |
1898 Operand address(ToRegister(left), ToRegister(right), times_1, 0); | 1898 Operand address(ToRegister(left), ToRegister(right), times_1, 0); |
1899 if (is_p) { | 1899 if (is_p) { |
1900 __ leap(ToRegister(instr->result()), address); | 1900 __ leap(ToRegister(instr->result()), address); |
1901 } else { | 1901 } else { |
1902 __ leal(ToRegister(instr->result()), address); | 1902 __ leal(ToRegister(instr->result()), address); |
1903 } | 1903 } |
1904 } | 1904 } |
1905 } else { | 1905 } else { |
1906 if (right->IsConstantOperand()) { | 1906 if (right->IsConstantOperand()) { |
1907 // No support for smi-immediates for 32-bit SMI. | 1907 // No support for smi-immediates for 32-bit SMI. |
1908 ASSERT(SmiValuesAre32Bits() ? !target_rep.IsSmi() : SmiValuesAre31Bits()); | 1908 DCHECK(SmiValuesAre32Bits() ? !target_rep.IsSmi() : SmiValuesAre31Bits()); |
1909 int32_t right_operand = | 1909 int32_t right_operand = |
1910 ToRepresentation(LConstantOperand::cast(right), | 1910 ToRepresentation(LConstantOperand::cast(right), |
1911 instr->hydrogen()->right()->representation()); | 1911 instr->hydrogen()->right()->representation()); |
1912 if (is_p) { | 1912 if (is_p) { |
1913 __ addp(ToRegister(left), Immediate(right_operand)); | 1913 __ addp(ToRegister(left), Immediate(right_operand)); |
1914 } else { | 1914 } else { |
1915 __ addl(ToRegister(left), Immediate(right_operand)); | 1915 __ addl(ToRegister(left), Immediate(right_operand)); |
1916 } | 1916 } |
1917 } else if (right->IsRegister()) { | 1917 } else if (right->IsRegister()) { |
1918 if (is_p) { | 1918 if (is_p) { |
(...skipping 11 matching lines...) Expand all Loading... |
1930 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 1930 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
1931 DeoptimizeIf(overflow, instr->environment()); | 1931 DeoptimizeIf(overflow, instr->environment()); |
1932 } | 1932 } |
1933 } | 1933 } |
1934 } | 1934 } |
1935 | 1935 |
1936 | 1936 |
1937 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { | 1937 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { |
1938 LOperand* left = instr->left(); | 1938 LOperand* left = instr->left(); |
1939 LOperand* right = instr->right(); | 1939 LOperand* right = instr->right(); |
1940 ASSERT(left->Equals(instr->result())); | 1940 DCHECK(left->Equals(instr->result())); |
1941 HMathMinMax::Operation operation = instr->hydrogen()->operation(); | 1941 HMathMinMax::Operation operation = instr->hydrogen()->operation(); |
1942 if (instr->hydrogen()->representation().IsSmiOrInteger32()) { | 1942 if (instr->hydrogen()->representation().IsSmiOrInteger32()) { |
1943 Label return_left; | 1943 Label return_left; |
1944 Condition condition = (operation == HMathMinMax::kMathMin) | 1944 Condition condition = (operation == HMathMinMax::kMathMin) |
1945 ? less_equal | 1945 ? less_equal |
1946 : greater_equal; | 1946 : greater_equal; |
1947 Register left_reg = ToRegister(left); | 1947 Register left_reg = ToRegister(left); |
1948 if (right->IsConstantOperand()) { | 1948 if (right->IsConstantOperand()) { |
1949 Immediate right_imm = Immediate( | 1949 Immediate right_imm = Immediate( |
1950 ToRepresentation(LConstantOperand::cast(right), | 1950 ToRepresentation(LConstantOperand::cast(right), |
1951 instr->hydrogen()->right()->representation())); | 1951 instr->hydrogen()->right()->representation())); |
1952 ASSERT(SmiValuesAre32Bits() | 1952 DCHECK(SmiValuesAre32Bits() |
1953 ? !instr->hydrogen()->representation().IsSmi() | 1953 ? !instr->hydrogen()->representation().IsSmi() |
1954 : SmiValuesAre31Bits()); | 1954 : SmiValuesAre31Bits()); |
1955 __ cmpl(left_reg, right_imm); | 1955 __ cmpl(left_reg, right_imm); |
1956 __ j(condition, &return_left, Label::kNear); | 1956 __ j(condition, &return_left, Label::kNear); |
1957 __ movp(left_reg, right_imm); | 1957 __ movp(left_reg, right_imm); |
1958 } else if (right->IsRegister()) { | 1958 } else if (right->IsRegister()) { |
1959 Register right_reg = ToRegister(right); | 1959 Register right_reg = ToRegister(right); |
1960 if (instr->hydrogen_value()->representation().IsSmi()) { | 1960 if (instr->hydrogen_value()->representation().IsSmi()) { |
1961 __ cmpp(left_reg, right_reg); | 1961 __ cmpp(left_reg, right_reg); |
1962 } else { | 1962 } else { |
1963 __ cmpl(left_reg, right_reg); | 1963 __ cmpl(left_reg, right_reg); |
1964 } | 1964 } |
1965 __ j(condition, &return_left, Label::kNear); | 1965 __ j(condition, &return_left, Label::kNear); |
1966 __ movp(left_reg, right_reg); | 1966 __ movp(left_reg, right_reg); |
1967 } else { | 1967 } else { |
1968 Operand right_op = ToOperand(right); | 1968 Operand right_op = ToOperand(right); |
1969 if (instr->hydrogen_value()->representation().IsSmi()) { | 1969 if (instr->hydrogen_value()->representation().IsSmi()) { |
1970 __ cmpp(left_reg, right_op); | 1970 __ cmpp(left_reg, right_op); |
1971 } else { | 1971 } else { |
1972 __ cmpl(left_reg, right_op); | 1972 __ cmpl(left_reg, right_op); |
1973 } | 1973 } |
1974 __ j(condition, &return_left, Label::kNear); | 1974 __ j(condition, &return_left, Label::kNear); |
1975 __ movp(left_reg, right_op); | 1975 __ movp(left_reg, right_op); |
1976 } | 1976 } |
1977 __ bind(&return_left); | 1977 __ bind(&return_left); |
1978 } else { | 1978 } else { |
1979 ASSERT(instr->hydrogen()->representation().IsDouble()); | 1979 DCHECK(instr->hydrogen()->representation().IsDouble()); |
1980 Label check_nan_left, check_zero, return_left, return_right; | 1980 Label check_nan_left, check_zero, return_left, return_right; |
1981 Condition condition = (operation == HMathMinMax::kMathMin) ? below : above; | 1981 Condition condition = (operation == HMathMinMax::kMathMin) ? below : above; |
1982 XMMRegister left_reg = ToDoubleRegister(left); | 1982 XMMRegister left_reg = ToDoubleRegister(left); |
1983 XMMRegister right_reg = ToDoubleRegister(right); | 1983 XMMRegister right_reg = ToDoubleRegister(right); |
1984 __ ucomisd(left_reg, right_reg); | 1984 __ ucomisd(left_reg, right_reg); |
1985 __ j(parity_even, &check_nan_left, Label::kNear); // At least one NaN. | 1985 __ j(parity_even, &check_nan_left, Label::kNear); // At least one NaN. |
1986 __ j(equal, &check_zero, Label::kNear); // left == right. | 1986 __ j(equal, &check_zero, Label::kNear); // left == right. |
1987 __ j(condition, &return_left, Label::kNear); | 1987 __ j(condition, &return_left, Label::kNear); |
1988 __ jmp(&return_right, Label::kNear); | 1988 __ jmp(&return_right, Label::kNear); |
1989 | 1989 |
(...skipping 20 matching lines...) Expand all Loading... |
2010 __ bind(&return_left); | 2010 __ bind(&return_left); |
2011 } | 2011 } |
2012 } | 2012 } |
2013 | 2013 |
2014 | 2014 |
2015 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { | 2015 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { |
2016 XMMRegister left = ToDoubleRegister(instr->left()); | 2016 XMMRegister left = ToDoubleRegister(instr->left()); |
2017 XMMRegister right = ToDoubleRegister(instr->right()); | 2017 XMMRegister right = ToDoubleRegister(instr->right()); |
2018 XMMRegister result = ToDoubleRegister(instr->result()); | 2018 XMMRegister result = ToDoubleRegister(instr->result()); |
2019 // All operations except MOD are computed in-place. | 2019 // All operations except MOD are computed in-place. |
2020 ASSERT(instr->op() == Token::MOD || left.is(result)); | 2020 DCHECK(instr->op() == Token::MOD || left.is(result)); |
2021 switch (instr->op()) { | 2021 switch (instr->op()) { |
2022 case Token::ADD: | 2022 case Token::ADD: |
2023 __ addsd(left, right); | 2023 __ addsd(left, right); |
2024 break; | 2024 break; |
2025 case Token::SUB: | 2025 case Token::SUB: |
2026 __ subsd(left, right); | 2026 __ subsd(left, right); |
2027 break; | 2027 break; |
2028 case Token::MUL: | 2028 case Token::MUL: |
2029 __ mulsd(left, right); | 2029 __ mulsd(left, right); |
2030 break; | 2030 break; |
2031 case Token::DIV: | 2031 case Token::DIV: |
2032 __ divsd(left, right); | 2032 __ divsd(left, right); |
2033 // Don't delete this mov. It may improve performance on some CPUs, | 2033 // Don't delete this mov. It may improve performance on some CPUs, |
2034 // when there is a mulsd depending on the result | 2034 // when there is a mulsd depending on the result |
2035 __ movaps(left, left); | 2035 __ movaps(left, left); |
2036 break; | 2036 break; |
2037 case Token::MOD: { | 2037 case Token::MOD: { |
2038 XMMRegister xmm_scratch = double_scratch0(); | 2038 XMMRegister xmm_scratch = double_scratch0(); |
2039 __ PrepareCallCFunction(2); | 2039 __ PrepareCallCFunction(2); |
2040 __ movaps(xmm_scratch, left); | 2040 __ movaps(xmm_scratch, left); |
2041 ASSERT(right.is(xmm1)); | 2041 DCHECK(right.is(xmm1)); |
2042 __ CallCFunction( | 2042 __ CallCFunction( |
2043 ExternalReference::mod_two_doubles_operation(isolate()), 2); | 2043 ExternalReference::mod_two_doubles_operation(isolate()), 2); |
2044 __ movaps(result, xmm_scratch); | 2044 __ movaps(result, xmm_scratch); |
2045 break; | 2045 break; |
2046 } | 2046 } |
2047 default: | 2047 default: |
2048 UNREACHABLE(); | 2048 UNREACHABLE(); |
2049 break; | 2049 break; |
2050 } | 2050 } |
2051 } | 2051 } |
2052 | 2052 |
2053 | 2053 |
2054 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { | 2054 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { |
2055 ASSERT(ToRegister(instr->context()).is(rsi)); | 2055 DCHECK(ToRegister(instr->context()).is(rsi)); |
2056 ASSERT(ToRegister(instr->left()).is(rdx)); | 2056 DCHECK(ToRegister(instr->left()).is(rdx)); |
2057 ASSERT(ToRegister(instr->right()).is(rax)); | 2057 DCHECK(ToRegister(instr->right()).is(rax)); |
2058 ASSERT(ToRegister(instr->result()).is(rax)); | 2058 DCHECK(ToRegister(instr->result()).is(rax)); |
2059 | 2059 |
2060 BinaryOpICStub stub(isolate(), instr->op(), NO_OVERWRITE); | 2060 BinaryOpICStub stub(isolate(), instr->op(), NO_OVERWRITE); |
2061 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 2061 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
2062 } | 2062 } |
2063 | 2063 |
2064 | 2064 |
2065 template<class InstrType> | 2065 template<class InstrType> |
2066 void LCodeGen::EmitBranch(InstrType instr, Condition cc) { | 2066 void LCodeGen::EmitBranch(InstrType instr, Condition cc) { |
2067 int left_block = instr->TrueDestination(chunk_); | 2067 int left_block = instr->TrueDestination(chunk_); |
2068 int right_block = instr->FalseDestination(chunk_); | 2068 int right_block = instr->FalseDestination(chunk_); |
(...skipping 23 matching lines...) Expand all Loading... |
2092 | 2092 |
2093 | 2093 |
2094 void LCodeGen::DoDebugBreak(LDebugBreak* instr) { | 2094 void LCodeGen::DoDebugBreak(LDebugBreak* instr) { |
2095 __ int3(); | 2095 __ int3(); |
2096 } | 2096 } |
2097 | 2097 |
2098 | 2098 |
2099 void LCodeGen::DoBranch(LBranch* instr) { | 2099 void LCodeGen::DoBranch(LBranch* instr) { |
2100 Representation r = instr->hydrogen()->value()->representation(); | 2100 Representation r = instr->hydrogen()->value()->representation(); |
2101 if (r.IsInteger32()) { | 2101 if (r.IsInteger32()) { |
2102 ASSERT(!info()->IsStub()); | 2102 DCHECK(!info()->IsStub()); |
2103 Register reg = ToRegister(instr->value()); | 2103 Register reg = ToRegister(instr->value()); |
2104 __ testl(reg, reg); | 2104 __ testl(reg, reg); |
2105 EmitBranch(instr, not_zero); | 2105 EmitBranch(instr, not_zero); |
2106 } else if (r.IsSmi()) { | 2106 } else if (r.IsSmi()) { |
2107 ASSERT(!info()->IsStub()); | 2107 DCHECK(!info()->IsStub()); |
2108 Register reg = ToRegister(instr->value()); | 2108 Register reg = ToRegister(instr->value()); |
2109 __ testp(reg, reg); | 2109 __ testp(reg, reg); |
2110 EmitBranch(instr, not_zero); | 2110 EmitBranch(instr, not_zero); |
2111 } else if (r.IsDouble()) { | 2111 } else if (r.IsDouble()) { |
2112 ASSERT(!info()->IsStub()); | 2112 DCHECK(!info()->IsStub()); |
2113 XMMRegister reg = ToDoubleRegister(instr->value()); | 2113 XMMRegister reg = ToDoubleRegister(instr->value()); |
2114 XMMRegister xmm_scratch = double_scratch0(); | 2114 XMMRegister xmm_scratch = double_scratch0(); |
2115 __ xorps(xmm_scratch, xmm_scratch); | 2115 __ xorps(xmm_scratch, xmm_scratch); |
2116 __ ucomisd(reg, xmm_scratch); | 2116 __ ucomisd(reg, xmm_scratch); |
2117 EmitBranch(instr, not_equal); | 2117 EmitBranch(instr, not_equal); |
2118 } else { | 2118 } else { |
2119 ASSERT(r.IsTagged()); | 2119 DCHECK(r.IsTagged()); |
2120 Register reg = ToRegister(instr->value()); | 2120 Register reg = ToRegister(instr->value()); |
2121 HType type = instr->hydrogen()->value()->type(); | 2121 HType type = instr->hydrogen()->value()->type(); |
2122 if (type.IsBoolean()) { | 2122 if (type.IsBoolean()) { |
2123 ASSERT(!info()->IsStub()); | 2123 DCHECK(!info()->IsStub()); |
2124 __ CompareRoot(reg, Heap::kTrueValueRootIndex); | 2124 __ CompareRoot(reg, Heap::kTrueValueRootIndex); |
2125 EmitBranch(instr, equal); | 2125 EmitBranch(instr, equal); |
2126 } else if (type.IsSmi()) { | 2126 } else if (type.IsSmi()) { |
2127 ASSERT(!info()->IsStub()); | 2127 DCHECK(!info()->IsStub()); |
2128 __ SmiCompare(reg, Smi::FromInt(0)); | 2128 __ SmiCompare(reg, Smi::FromInt(0)); |
2129 EmitBranch(instr, not_equal); | 2129 EmitBranch(instr, not_equal); |
2130 } else if (type.IsJSArray()) { | 2130 } else if (type.IsJSArray()) { |
2131 ASSERT(!info()->IsStub()); | 2131 DCHECK(!info()->IsStub()); |
2132 EmitBranch(instr, no_condition); | 2132 EmitBranch(instr, no_condition); |
2133 } else if (type.IsHeapNumber()) { | 2133 } else if (type.IsHeapNumber()) { |
2134 ASSERT(!info()->IsStub()); | 2134 DCHECK(!info()->IsStub()); |
2135 XMMRegister xmm_scratch = double_scratch0(); | 2135 XMMRegister xmm_scratch = double_scratch0(); |
2136 __ xorps(xmm_scratch, xmm_scratch); | 2136 __ xorps(xmm_scratch, xmm_scratch); |
2137 __ ucomisd(xmm_scratch, FieldOperand(reg, HeapNumber::kValueOffset)); | 2137 __ ucomisd(xmm_scratch, FieldOperand(reg, HeapNumber::kValueOffset)); |
2138 EmitBranch(instr, not_equal); | 2138 EmitBranch(instr, not_equal); |
2139 } else if (type.IsString()) { | 2139 } else if (type.IsString()) { |
2140 ASSERT(!info()->IsStub()); | 2140 DCHECK(!info()->IsStub()); |
2141 __ cmpp(FieldOperand(reg, String::kLengthOffset), Immediate(0)); | 2141 __ cmpp(FieldOperand(reg, String::kLengthOffset), Immediate(0)); |
2142 EmitBranch(instr, not_equal); | 2142 EmitBranch(instr, not_equal); |
2143 } else { | 2143 } else { |
2144 ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types(); | 2144 ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types(); |
2145 // Avoid deopts in the case where we've never executed this path before. | 2145 // Avoid deopts in the case where we've never executed this path before. |
2146 if (expected.IsEmpty()) expected = ToBooleanStub::Types::Generic(); | 2146 if (expected.IsEmpty()) expected = ToBooleanStub::Types::Generic(); |
2147 | 2147 |
2148 if (expected.Contains(ToBooleanStub::UNDEFINED)) { | 2148 if (expected.Contains(ToBooleanStub::UNDEFINED)) { |
2149 // undefined -> false. | 2149 // undefined -> false. |
2150 __ CompareRoot(reg, Heap::kUndefinedValueRootIndex); | 2150 __ CompareRoot(reg, Heap::kUndefinedValueRootIndex); |
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2373 __ addp(rsp, Immediate(kDoubleSize)); | 2373 __ addp(rsp, Immediate(kDoubleSize)); |
2374 | 2374 |
2375 int offset = sizeof(kHoleNanUpper32); | 2375 int offset = sizeof(kHoleNanUpper32); |
2376 __ cmpl(MemOperand(rsp, -offset), Immediate(kHoleNanUpper32)); | 2376 __ cmpl(MemOperand(rsp, -offset), Immediate(kHoleNanUpper32)); |
2377 EmitBranch(instr, equal); | 2377 EmitBranch(instr, equal); |
2378 } | 2378 } |
2379 | 2379 |
2380 | 2380 |
2381 void LCodeGen::DoCompareMinusZeroAndBranch(LCompareMinusZeroAndBranch* instr) { | 2381 void LCodeGen::DoCompareMinusZeroAndBranch(LCompareMinusZeroAndBranch* instr) { |
2382 Representation rep = instr->hydrogen()->value()->representation(); | 2382 Representation rep = instr->hydrogen()->value()->representation(); |
2383 ASSERT(!rep.IsInteger32()); | 2383 DCHECK(!rep.IsInteger32()); |
2384 | 2384 |
2385 if (rep.IsDouble()) { | 2385 if (rep.IsDouble()) { |
2386 XMMRegister value = ToDoubleRegister(instr->value()); | 2386 XMMRegister value = ToDoubleRegister(instr->value()); |
2387 XMMRegister xmm_scratch = double_scratch0(); | 2387 XMMRegister xmm_scratch = double_scratch0(); |
2388 __ xorps(xmm_scratch, xmm_scratch); | 2388 __ xorps(xmm_scratch, xmm_scratch); |
2389 __ ucomisd(xmm_scratch, value); | 2389 __ ucomisd(xmm_scratch, value); |
2390 EmitFalseBranch(instr, not_equal); | 2390 EmitFalseBranch(instr, not_equal); |
2391 __ movmskpd(kScratchRegister, value); | 2391 __ movmskpd(kScratchRegister, value); |
2392 __ testl(kScratchRegister, Immediate(1)); | 2392 __ testl(kScratchRegister, Immediate(1)); |
2393 EmitBranch(instr, not_zero); | 2393 EmitBranch(instr, not_zero); |
2394 } else { | 2394 } else { |
2395 Register value = ToRegister(instr->value()); | 2395 Register value = ToRegister(instr->value()); |
2396 Handle<Map> map = masm()->isolate()->factory()->heap_number_map(); | 2396 Handle<Map> map = masm()->isolate()->factory()->heap_number_map(); |
2397 __ CheckMap(value, map, instr->FalseLabel(chunk()), DO_SMI_CHECK); | 2397 __ CheckMap(value, map, instr->FalseLabel(chunk()), DO_SMI_CHECK); |
2398 __ cmpl(FieldOperand(value, HeapNumber::kExponentOffset), | 2398 __ cmpl(FieldOperand(value, HeapNumber::kExponentOffset), |
2399 Immediate(0x1)); | 2399 Immediate(0x1)); |
2400 EmitFalseBranch(instr, no_overflow); | 2400 EmitFalseBranch(instr, no_overflow); |
2401 __ cmpl(FieldOperand(value, HeapNumber::kMantissaOffset), | 2401 __ cmpl(FieldOperand(value, HeapNumber::kMantissaOffset), |
2402 Immediate(0x00000000)); | 2402 Immediate(0x00000000)); |
2403 EmitBranch(instr, equal); | 2403 EmitBranch(instr, equal); |
2404 } | 2404 } |
2405 } | 2405 } |
2406 | 2406 |
2407 | 2407 |
2408 Condition LCodeGen::EmitIsObject(Register input, | 2408 Condition LCodeGen::EmitIsObject(Register input, |
2409 Label* is_not_object, | 2409 Label* is_not_object, |
2410 Label* is_object) { | 2410 Label* is_object) { |
2411 ASSERT(!input.is(kScratchRegister)); | 2411 DCHECK(!input.is(kScratchRegister)); |
2412 | 2412 |
2413 __ JumpIfSmi(input, is_not_object); | 2413 __ JumpIfSmi(input, is_not_object); |
2414 | 2414 |
2415 __ CompareRoot(input, Heap::kNullValueRootIndex); | 2415 __ CompareRoot(input, Heap::kNullValueRootIndex); |
2416 __ j(equal, is_object); | 2416 __ j(equal, is_object); |
2417 | 2417 |
2418 __ movp(kScratchRegister, FieldOperand(input, HeapObject::kMapOffset)); | 2418 __ movp(kScratchRegister, FieldOperand(input, HeapObject::kMapOffset)); |
2419 // Undetectable objects behave like undefined. | 2419 // Undetectable objects behave like undefined. |
2420 __ testb(FieldOperand(kScratchRegister, Map::kBitFieldOffset), | 2420 __ testb(FieldOperand(kScratchRegister, Map::kBitFieldOffset), |
2421 Immediate(1 << Map::kIsUndetectable)); | 2421 Immediate(1 << Map::kIsUndetectable)); |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2490 __ JumpIfSmi(input, instr->FalseLabel(chunk_)); | 2490 __ JumpIfSmi(input, instr->FalseLabel(chunk_)); |
2491 } | 2491 } |
2492 __ movp(temp, FieldOperand(input, HeapObject::kMapOffset)); | 2492 __ movp(temp, FieldOperand(input, HeapObject::kMapOffset)); |
2493 __ testb(FieldOperand(temp, Map::kBitFieldOffset), | 2493 __ testb(FieldOperand(temp, Map::kBitFieldOffset), |
2494 Immediate(1 << Map::kIsUndetectable)); | 2494 Immediate(1 << Map::kIsUndetectable)); |
2495 EmitBranch(instr, not_zero); | 2495 EmitBranch(instr, not_zero); |
2496 } | 2496 } |
2497 | 2497 |
2498 | 2498 |
2499 void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) { | 2499 void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) { |
2500 ASSERT(ToRegister(instr->context()).is(rsi)); | 2500 DCHECK(ToRegister(instr->context()).is(rsi)); |
2501 Token::Value op = instr->op(); | 2501 Token::Value op = instr->op(); |
2502 | 2502 |
2503 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); | 2503 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); |
2504 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2504 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
2505 | 2505 |
2506 Condition condition = TokenToCondition(op, false); | 2506 Condition condition = TokenToCondition(op, false); |
2507 __ testp(rax, rax); | 2507 __ testp(rax, rax); |
2508 | 2508 |
2509 EmitBranch(instr, condition); | 2509 EmitBranch(instr, condition); |
2510 } | 2510 } |
2511 | 2511 |
2512 | 2512 |
2513 static InstanceType TestType(HHasInstanceTypeAndBranch* instr) { | 2513 static InstanceType TestType(HHasInstanceTypeAndBranch* instr) { |
2514 InstanceType from = instr->from(); | 2514 InstanceType from = instr->from(); |
2515 InstanceType to = instr->to(); | 2515 InstanceType to = instr->to(); |
2516 if (from == FIRST_TYPE) return to; | 2516 if (from == FIRST_TYPE) return to; |
2517 ASSERT(from == to || to == LAST_TYPE); | 2517 DCHECK(from == to || to == LAST_TYPE); |
2518 return from; | 2518 return from; |
2519 } | 2519 } |
2520 | 2520 |
2521 | 2521 |
2522 static Condition BranchCondition(HHasInstanceTypeAndBranch* instr) { | 2522 static Condition BranchCondition(HHasInstanceTypeAndBranch* instr) { |
2523 InstanceType from = instr->from(); | 2523 InstanceType from = instr->from(); |
2524 InstanceType to = instr->to(); | 2524 InstanceType to = instr->to(); |
2525 if (from == to) return equal; | 2525 if (from == to) return equal; |
2526 if (to == LAST_TYPE) return above_equal; | 2526 if (to == LAST_TYPE) return above_equal; |
2527 if (from == FIRST_TYPE) return below_equal; | 2527 if (from == FIRST_TYPE) return below_equal; |
(...skipping 14 matching lines...) Expand all Loading... |
2542 } | 2542 } |
2543 | 2543 |
2544 | 2544 |
2545 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) { | 2545 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) { |
2546 Register input = ToRegister(instr->value()); | 2546 Register input = ToRegister(instr->value()); |
2547 Register result = ToRegister(instr->result()); | 2547 Register result = ToRegister(instr->result()); |
2548 | 2548 |
2549 __ AssertString(input); | 2549 __ AssertString(input); |
2550 | 2550 |
2551 __ movl(result, FieldOperand(input, String::kHashFieldOffset)); | 2551 __ movl(result, FieldOperand(input, String::kHashFieldOffset)); |
2552 ASSERT(String::kHashShift >= kSmiTagSize); | 2552 DCHECK(String::kHashShift >= kSmiTagSize); |
2553 __ IndexFromHash(result, result); | 2553 __ IndexFromHash(result, result); |
2554 } | 2554 } |
2555 | 2555 |
2556 | 2556 |
2557 void LCodeGen::DoHasCachedArrayIndexAndBranch( | 2557 void LCodeGen::DoHasCachedArrayIndexAndBranch( |
2558 LHasCachedArrayIndexAndBranch* instr) { | 2558 LHasCachedArrayIndexAndBranch* instr) { |
2559 Register input = ToRegister(instr->value()); | 2559 Register input = ToRegister(instr->value()); |
2560 | 2560 |
2561 __ testl(FieldOperand(input, String::kHashFieldOffset), | 2561 __ testl(FieldOperand(input, String::kHashFieldOffset), |
2562 Immediate(String::kContainsCachedArrayIndexMask)); | 2562 Immediate(String::kContainsCachedArrayIndexMask)); |
2563 EmitBranch(instr, equal); | 2563 EmitBranch(instr, equal); |
2564 } | 2564 } |
2565 | 2565 |
2566 | 2566 |
2567 // Branches to a label or falls through with the answer in the z flag. | 2567 // Branches to a label or falls through with the answer in the z flag. |
2568 // Trashes the temp register. | 2568 // Trashes the temp register. |
2569 void LCodeGen::EmitClassOfTest(Label* is_true, | 2569 void LCodeGen::EmitClassOfTest(Label* is_true, |
2570 Label* is_false, | 2570 Label* is_false, |
2571 Handle<String> class_name, | 2571 Handle<String> class_name, |
2572 Register input, | 2572 Register input, |
2573 Register temp, | 2573 Register temp, |
2574 Register temp2) { | 2574 Register temp2) { |
2575 ASSERT(!input.is(temp)); | 2575 DCHECK(!input.is(temp)); |
2576 ASSERT(!input.is(temp2)); | 2576 DCHECK(!input.is(temp2)); |
2577 ASSERT(!temp.is(temp2)); | 2577 DCHECK(!temp.is(temp2)); |
2578 | 2578 |
2579 __ JumpIfSmi(input, is_false); | 2579 __ JumpIfSmi(input, is_false); |
2580 | 2580 |
2581 if (class_name->IsOneByteEqualTo(STATIC_ASCII_VECTOR("Function"))) { | 2581 if (class_name->IsOneByteEqualTo(STATIC_ASCII_VECTOR("Function"))) { |
2582 // Assuming the following assertions, we can use the same compares to test | 2582 // Assuming the following assertions, we can use the same compares to test |
2583 // for both being a function type and being in the object type range. | 2583 // for both being a function type and being in the object type range. |
2584 STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); | 2584 STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); |
2585 STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE == | 2585 STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE == |
2586 FIRST_SPEC_OBJECT_TYPE + 1); | 2586 FIRST_SPEC_OBJECT_TYPE + 1); |
2587 STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == | 2587 STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2619 // instance class name from there. | 2619 // instance class name from there. |
2620 __ movp(temp, FieldOperand(temp, JSFunction::kSharedFunctionInfoOffset)); | 2620 __ movp(temp, FieldOperand(temp, JSFunction::kSharedFunctionInfoOffset)); |
2621 __ movp(temp, FieldOperand(temp, | 2621 __ movp(temp, FieldOperand(temp, |
2622 SharedFunctionInfo::kInstanceClassNameOffset)); | 2622 SharedFunctionInfo::kInstanceClassNameOffset)); |
2623 // The class name we are testing against is internalized since it's a literal. | 2623 // The class name we are testing against is internalized since it's a literal. |
2624 // The name in the constructor is internalized because of the way the context | 2624 // The name in the constructor is internalized because of the way the context |
2625 // is booted. This routine isn't expected to work for random API-created | 2625 // is booted. This routine isn't expected to work for random API-created |
2626 // classes and it doesn't have to because you can't access it with natives | 2626 // classes and it doesn't have to because you can't access it with natives |
2627 // syntax. Since both sides are internalized it is sufficient to use an | 2627 // syntax. Since both sides are internalized it is sufficient to use an |
2628 // identity comparison. | 2628 // identity comparison. |
2629 ASSERT(class_name->IsInternalizedString()); | 2629 DCHECK(class_name->IsInternalizedString()); |
2630 __ Cmp(temp, class_name); | 2630 __ Cmp(temp, class_name); |
2631 // End with the answer in the z flag. | 2631 // End with the answer in the z flag. |
2632 } | 2632 } |
2633 | 2633 |
2634 | 2634 |
2635 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { | 2635 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { |
2636 Register input = ToRegister(instr->value()); | 2636 Register input = ToRegister(instr->value()); |
2637 Register temp = ToRegister(instr->temp()); | 2637 Register temp = ToRegister(instr->temp()); |
2638 Register temp2 = ToRegister(instr->temp2()); | 2638 Register temp2 = ToRegister(instr->temp2()); |
2639 Handle<String> class_name = instr->hydrogen()->class_name(); | 2639 Handle<String> class_name = instr->hydrogen()->class_name(); |
2640 | 2640 |
2641 EmitClassOfTest(instr->TrueLabel(chunk_), instr->FalseLabel(chunk_), | 2641 EmitClassOfTest(instr->TrueLabel(chunk_), instr->FalseLabel(chunk_), |
2642 class_name, input, temp, temp2); | 2642 class_name, input, temp, temp2); |
2643 | 2643 |
2644 EmitBranch(instr, equal); | 2644 EmitBranch(instr, equal); |
2645 } | 2645 } |
2646 | 2646 |
2647 | 2647 |
2648 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { | 2648 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { |
2649 Register reg = ToRegister(instr->value()); | 2649 Register reg = ToRegister(instr->value()); |
2650 | 2650 |
2651 __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map()); | 2651 __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map()); |
2652 EmitBranch(instr, equal); | 2652 EmitBranch(instr, equal); |
2653 } | 2653 } |
2654 | 2654 |
2655 | 2655 |
2656 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { | 2656 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { |
2657 ASSERT(ToRegister(instr->context()).is(rsi)); | 2657 DCHECK(ToRegister(instr->context()).is(rsi)); |
2658 InstanceofStub stub(isolate(), InstanceofStub::kNoFlags); | 2658 InstanceofStub stub(isolate(), InstanceofStub::kNoFlags); |
2659 __ Push(ToRegister(instr->left())); | 2659 __ Push(ToRegister(instr->left())); |
2660 __ Push(ToRegister(instr->right())); | 2660 __ Push(ToRegister(instr->right())); |
2661 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 2661 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
2662 Label true_value, done; | 2662 Label true_value, done; |
2663 __ testp(rax, rax); | 2663 __ testp(rax, rax); |
2664 __ j(zero, &true_value, Label::kNear); | 2664 __ j(zero, &true_value, Label::kNear); |
2665 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex); | 2665 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex); |
2666 __ jmp(&done, Label::kNear); | 2666 __ jmp(&done, Label::kNear); |
2667 __ bind(&true_value); | 2667 __ bind(&true_value); |
(...skipping 11 matching lines...) Expand all Loading... |
2679 virtual void Generate() V8_OVERRIDE { | 2679 virtual void Generate() V8_OVERRIDE { |
2680 codegen()->DoDeferredInstanceOfKnownGlobal(instr_, &map_check_); | 2680 codegen()->DoDeferredInstanceOfKnownGlobal(instr_, &map_check_); |
2681 } | 2681 } |
2682 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } | 2682 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
2683 Label* map_check() { return &map_check_; } | 2683 Label* map_check() { return &map_check_; } |
2684 private: | 2684 private: |
2685 LInstanceOfKnownGlobal* instr_; | 2685 LInstanceOfKnownGlobal* instr_; |
2686 Label map_check_; | 2686 Label map_check_; |
2687 }; | 2687 }; |
2688 | 2688 |
2689 ASSERT(ToRegister(instr->context()).is(rsi)); | 2689 DCHECK(ToRegister(instr->context()).is(rsi)); |
2690 DeferredInstanceOfKnownGlobal* deferred; | 2690 DeferredInstanceOfKnownGlobal* deferred; |
2691 deferred = new(zone()) DeferredInstanceOfKnownGlobal(this, instr); | 2691 deferred = new(zone()) DeferredInstanceOfKnownGlobal(this, instr); |
2692 | 2692 |
2693 Label done, false_result; | 2693 Label done, false_result; |
2694 Register object = ToRegister(instr->value()); | 2694 Register object = ToRegister(instr->value()); |
2695 | 2695 |
2696 // A Smi is not an instance of anything. | 2696 // A Smi is not an instance of anything. |
2697 __ JumpIfSmi(object, &false_result, Label::kNear); | 2697 __ JumpIfSmi(object, &false_result, Label::kNear); |
2698 | 2698 |
2699 // This is the inlined call site instanceof cache. The two occurences of the | 2699 // This is the inlined call site instanceof cache. The two occurences of the |
2700 // hole value will be patched to the last map/result pair generated by the | 2700 // hole value will be patched to the last map/result pair generated by the |
2701 // instanceof stub. | 2701 // instanceof stub. |
2702 Label cache_miss; | 2702 Label cache_miss; |
2703 // Use a temp register to avoid memory operands with variable lengths. | 2703 // Use a temp register to avoid memory operands with variable lengths. |
2704 Register map = ToRegister(instr->temp()); | 2704 Register map = ToRegister(instr->temp()); |
2705 __ movp(map, FieldOperand(object, HeapObject::kMapOffset)); | 2705 __ movp(map, FieldOperand(object, HeapObject::kMapOffset)); |
2706 __ bind(deferred->map_check()); // Label for calculating code patching. | 2706 __ bind(deferred->map_check()); // Label for calculating code patching. |
2707 Handle<Cell> cache_cell = factory()->NewCell(factory()->the_hole_value()); | 2707 Handle<Cell> cache_cell = factory()->NewCell(factory()->the_hole_value()); |
2708 __ Move(kScratchRegister, cache_cell, RelocInfo::CELL); | 2708 __ Move(kScratchRegister, cache_cell, RelocInfo::CELL); |
2709 __ cmpp(map, Operand(kScratchRegister, 0)); | 2709 __ cmpp(map, Operand(kScratchRegister, 0)); |
2710 __ j(not_equal, &cache_miss, Label::kNear); | 2710 __ j(not_equal, &cache_miss, Label::kNear); |
2711 // Patched to load either true or false. | 2711 // Patched to load either true or false. |
2712 __ LoadRoot(ToRegister(instr->result()), Heap::kTheHoleValueRootIndex); | 2712 __ LoadRoot(ToRegister(instr->result()), Heap::kTheHoleValueRootIndex); |
2713 #ifdef DEBUG | 2713 #ifdef DEBUG |
2714 // Check that the code size between patch label and patch sites is invariant. | 2714 // Check that the code size between patch label and patch sites is invariant. |
2715 Label end_of_patched_code; | 2715 Label end_of_patched_code; |
2716 __ bind(&end_of_patched_code); | 2716 __ bind(&end_of_patched_code); |
2717 ASSERT(true); | 2717 DCHECK(true); |
2718 #endif | 2718 #endif |
2719 __ jmp(&done, Label::kNear); | 2719 __ jmp(&done, Label::kNear); |
2720 | 2720 |
2721 // The inlined call site cache did not match. Check for null and string | 2721 // The inlined call site cache did not match. Check for null and string |
2722 // before calling the deferred code. | 2722 // before calling the deferred code. |
2723 __ bind(&cache_miss); // Null is not an instance of anything. | 2723 __ bind(&cache_miss); // Null is not an instance of anything. |
2724 __ CompareRoot(object, Heap::kNullValueRootIndex); | 2724 __ CompareRoot(object, Heap::kNullValueRootIndex); |
2725 __ j(equal, &false_result, Label::kNear); | 2725 __ j(equal, &false_result, Label::kNear); |
2726 | 2726 |
2727 // String values are not instances of anything. | 2727 // String values are not instances of anything. |
(...skipping 14 matching lines...) Expand all Loading... |
2742 InstanceofStub::Flags flags = static_cast<InstanceofStub::Flags>( | 2742 InstanceofStub::Flags flags = static_cast<InstanceofStub::Flags>( |
2743 InstanceofStub::kNoFlags | InstanceofStub::kCallSiteInlineCheck); | 2743 InstanceofStub::kNoFlags | InstanceofStub::kCallSiteInlineCheck); |
2744 InstanceofStub stub(isolate(), flags); | 2744 InstanceofStub stub(isolate(), flags); |
2745 | 2745 |
2746 __ Push(ToRegister(instr->value())); | 2746 __ Push(ToRegister(instr->value())); |
2747 __ Push(instr->function()); | 2747 __ Push(instr->function()); |
2748 | 2748 |
2749 static const int kAdditionalDelta = kPointerSize == kInt64Size ? 10 : 16; | 2749 static const int kAdditionalDelta = kPointerSize == kInt64Size ? 10 : 16; |
2750 int delta = | 2750 int delta = |
2751 masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta; | 2751 masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta; |
2752 ASSERT(delta >= 0); | 2752 DCHECK(delta >= 0); |
2753 __ PushImm32(delta); | 2753 __ PushImm32(delta); |
2754 | 2754 |
2755 // We are pushing three values on the stack but recording a | 2755 // We are pushing three values on the stack but recording a |
2756 // safepoint with two arguments because stub is going to | 2756 // safepoint with two arguments because stub is going to |
2757 // remove the third argument from the stack before jumping | 2757 // remove the third argument from the stack before jumping |
2758 // to instanceof builtin on the slow path. | 2758 // to instanceof builtin on the slow path. |
2759 CallCodeGeneric(stub.GetCode(), | 2759 CallCodeGeneric(stub.GetCode(), |
2760 RelocInfo::CODE_TARGET, | 2760 RelocInfo::CODE_TARGET, |
2761 instr, | 2761 instr, |
2762 RECORD_SAFEPOINT_WITH_REGISTERS, | 2762 RECORD_SAFEPOINT_WITH_REGISTERS, |
2763 2); | 2763 2); |
2764 ASSERT(delta == masm_->SizeOfCodeGeneratedSince(map_check)); | 2764 DCHECK(delta == masm_->SizeOfCodeGeneratedSince(map_check)); |
2765 LEnvironment* env = instr->GetDeferredLazyDeoptimizationEnvironment(); | 2765 LEnvironment* env = instr->GetDeferredLazyDeoptimizationEnvironment(); |
2766 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); | 2766 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); |
2767 // Move result to a register that survives the end of the | 2767 // Move result to a register that survives the end of the |
2768 // PushSafepointRegisterScope. | 2768 // PushSafepointRegisterScope. |
2769 __ movp(kScratchRegister, rax); | 2769 __ movp(kScratchRegister, rax); |
2770 } | 2770 } |
2771 __ testp(kScratchRegister, kScratchRegister); | 2771 __ testp(kScratchRegister, kScratchRegister); |
2772 Label load_false; | 2772 Label load_false; |
2773 Label done; | 2773 Label done; |
2774 __ j(not_zero, &load_false, Label::kNear); | 2774 __ j(not_zero, &load_false, Label::kNear); |
2775 __ LoadRoot(rax, Heap::kTrueValueRootIndex); | 2775 __ LoadRoot(rax, Heap::kTrueValueRootIndex); |
2776 __ jmp(&done, Label::kNear); | 2776 __ jmp(&done, Label::kNear); |
2777 __ bind(&load_false); | 2777 __ bind(&load_false); |
2778 __ LoadRoot(rax, Heap::kFalseValueRootIndex); | 2778 __ LoadRoot(rax, Heap::kFalseValueRootIndex); |
2779 __ bind(&done); | 2779 __ bind(&done); |
2780 } | 2780 } |
2781 | 2781 |
2782 | 2782 |
2783 void LCodeGen::DoCmpT(LCmpT* instr) { | 2783 void LCodeGen::DoCmpT(LCmpT* instr) { |
2784 ASSERT(ToRegister(instr->context()).is(rsi)); | 2784 DCHECK(ToRegister(instr->context()).is(rsi)); |
2785 Token::Value op = instr->op(); | 2785 Token::Value op = instr->op(); |
2786 | 2786 |
2787 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); | 2787 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); |
2788 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2788 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
2789 | 2789 |
2790 Condition condition = TokenToCondition(op, false); | 2790 Condition condition = TokenToCondition(op, false); |
2791 Label true_value, done; | 2791 Label true_value, done; |
2792 __ testp(rax, rax); | 2792 __ testp(rax, rax); |
2793 __ j(condition, &true_value, Label::kNear); | 2793 __ j(condition, &true_value, Label::kNear); |
2794 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex); | 2794 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2841 Register result = ToRegister(instr->result()); | 2841 Register result = ToRegister(instr->result()); |
2842 __ LoadGlobalCell(result, instr->hydrogen()->cell().handle()); | 2842 __ LoadGlobalCell(result, instr->hydrogen()->cell().handle()); |
2843 if (instr->hydrogen()->RequiresHoleCheck()) { | 2843 if (instr->hydrogen()->RequiresHoleCheck()) { |
2844 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); | 2844 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); |
2845 DeoptimizeIf(equal, instr->environment()); | 2845 DeoptimizeIf(equal, instr->environment()); |
2846 } | 2846 } |
2847 } | 2847 } |
2848 | 2848 |
2849 | 2849 |
2850 void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { | 2850 void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { |
2851 ASSERT(ToRegister(instr->context()).is(rsi)); | 2851 DCHECK(ToRegister(instr->context()).is(rsi)); |
2852 ASSERT(ToRegister(instr->global_object()).is(LoadIC::ReceiverRegister())); | 2852 DCHECK(ToRegister(instr->global_object()).is(LoadIC::ReceiverRegister())); |
2853 ASSERT(ToRegister(instr->result()).is(rax)); | 2853 DCHECK(ToRegister(instr->result()).is(rax)); |
2854 | 2854 |
2855 __ Move(LoadIC::NameRegister(), instr->name()); | 2855 __ Move(LoadIC::NameRegister(), instr->name()); |
2856 if (FLAG_vector_ics) { | 2856 if (FLAG_vector_ics) { |
2857 Register vector = ToRegister(instr->temp_vector()); | 2857 Register vector = ToRegister(instr->temp_vector()); |
2858 ASSERT(vector.is(LoadIC::VectorRegister())); | 2858 DCHECK(vector.is(LoadIC::VectorRegister())); |
2859 __ Move(vector, instr->hydrogen()->feedback_vector()); | 2859 __ Move(vector, instr->hydrogen()->feedback_vector()); |
2860 // No need to allocate this register. | 2860 // No need to allocate this register. |
2861 ASSERT(LoadIC::SlotRegister().is(rax)); | 2861 DCHECK(LoadIC::SlotRegister().is(rax)); |
2862 __ Move(LoadIC::SlotRegister(), Smi::FromInt(instr->hydrogen()->slot())); | 2862 __ Move(LoadIC::SlotRegister(), Smi::FromInt(instr->hydrogen()->slot())); |
2863 } | 2863 } |
2864 ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL; | 2864 ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL; |
2865 Handle<Code> ic = LoadIC::initialize_stub(isolate(), mode); | 2865 Handle<Code> ic = LoadIC::initialize_stub(isolate(), mode); |
2866 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2866 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
2867 } | 2867 } |
2868 | 2868 |
2869 | 2869 |
2870 void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) { | 2870 void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) { |
2871 Register value = ToRegister(instr->value()); | 2871 Register value = ToRegister(instr->value()); |
2872 Handle<Cell> cell_handle = instr->hydrogen()->cell().handle(); | 2872 Handle<Cell> cell_handle = instr->hydrogen()->cell().handle(); |
2873 | 2873 |
2874 // If the cell we are storing to contains the hole it could have | 2874 // If the cell we are storing to contains the hole it could have |
2875 // been deleted from the property dictionary. In that case, we need | 2875 // been deleted from the property dictionary. In that case, we need |
2876 // to update the property details in the property dictionary to mark | 2876 // to update the property details in the property dictionary to mark |
2877 // it as no longer deleted. We deoptimize in that case. | 2877 // it as no longer deleted. We deoptimize in that case. |
2878 if (instr->hydrogen()->RequiresHoleCheck()) { | 2878 if (instr->hydrogen()->RequiresHoleCheck()) { |
2879 // We have a temp because CompareRoot might clobber kScratchRegister. | 2879 // We have a temp because CompareRoot might clobber kScratchRegister. |
2880 Register cell = ToRegister(instr->temp()); | 2880 Register cell = ToRegister(instr->temp()); |
2881 ASSERT(!value.is(cell)); | 2881 DCHECK(!value.is(cell)); |
2882 __ Move(cell, cell_handle, RelocInfo::CELL); | 2882 __ Move(cell, cell_handle, RelocInfo::CELL); |
2883 __ CompareRoot(Operand(cell, 0), Heap::kTheHoleValueRootIndex); | 2883 __ CompareRoot(Operand(cell, 0), Heap::kTheHoleValueRootIndex); |
2884 DeoptimizeIf(equal, instr->environment()); | 2884 DeoptimizeIf(equal, instr->environment()); |
2885 // Store the value. | 2885 // Store the value. |
2886 __ movp(Operand(cell, 0), value); | 2886 __ movp(Operand(cell, 0), value); |
2887 } else { | 2887 } else { |
2888 // Store the value. | 2888 // Store the value. |
2889 __ Move(kScratchRegister, cell_handle, RelocInfo::CELL); | 2889 __ Move(kScratchRegister, cell_handle, RelocInfo::CELL); |
2890 __ movp(Operand(kScratchRegister, 0), value); | 2890 __ movp(Operand(kScratchRegister, 0), value); |
2891 } | 2891 } |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2947 } | 2947 } |
2948 | 2948 |
2949 | 2949 |
2950 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { | 2950 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { |
2951 HObjectAccess access = instr->hydrogen()->access(); | 2951 HObjectAccess access = instr->hydrogen()->access(); |
2952 int offset = access.offset(); | 2952 int offset = access.offset(); |
2953 | 2953 |
2954 if (access.IsExternalMemory()) { | 2954 if (access.IsExternalMemory()) { |
2955 Register result = ToRegister(instr->result()); | 2955 Register result = ToRegister(instr->result()); |
2956 if (instr->object()->IsConstantOperand()) { | 2956 if (instr->object()->IsConstantOperand()) { |
2957 ASSERT(result.is(rax)); | 2957 DCHECK(result.is(rax)); |
2958 __ load_rax(ToExternalReference(LConstantOperand::cast(instr->object()))); | 2958 __ load_rax(ToExternalReference(LConstantOperand::cast(instr->object()))); |
2959 } else { | 2959 } else { |
2960 Register object = ToRegister(instr->object()); | 2960 Register object = ToRegister(instr->object()); |
2961 __ Load(result, MemOperand(object, offset), access.representation()); | 2961 __ Load(result, MemOperand(object, offset), access.representation()); |
2962 } | 2962 } |
2963 return; | 2963 return; |
2964 } | 2964 } |
2965 | 2965 |
2966 Register object = ToRegister(instr->object()); | 2966 Register object = ToRegister(instr->object()); |
2967 if (instr->hydrogen()->representation().IsDouble()) { | 2967 if (instr->hydrogen()->representation().IsDouble()) { |
(...skipping 12 matching lines...) Expand all Loading... |
2980 if (representation.IsSmi() && SmiValuesAre32Bits() && | 2980 if (representation.IsSmi() && SmiValuesAre32Bits() && |
2981 instr->hydrogen()->representation().IsInteger32()) { | 2981 instr->hydrogen()->representation().IsInteger32()) { |
2982 if (FLAG_debug_code) { | 2982 if (FLAG_debug_code) { |
2983 Register scratch = kScratchRegister; | 2983 Register scratch = kScratchRegister; |
2984 __ Load(scratch, FieldOperand(object, offset), representation); | 2984 __ Load(scratch, FieldOperand(object, offset), representation); |
2985 __ AssertSmi(scratch); | 2985 __ AssertSmi(scratch); |
2986 } | 2986 } |
2987 | 2987 |
2988 // Read int value directly from upper half of the smi. | 2988 // Read int value directly from upper half of the smi. |
2989 STATIC_ASSERT(kSmiTag == 0); | 2989 STATIC_ASSERT(kSmiTag == 0); |
2990 ASSERT(kSmiTagSize + kSmiShiftSize == 32); | 2990 DCHECK(kSmiTagSize + kSmiShiftSize == 32); |
2991 offset += kPointerSize / 2; | 2991 offset += kPointerSize / 2; |
2992 representation = Representation::Integer32(); | 2992 representation = Representation::Integer32(); |
2993 } | 2993 } |
2994 __ Load(result, FieldOperand(object, offset), representation); | 2994 __ Load(result, FieldOperand(object, offset), representation); |
2995 } | 2995 } |
2996 | 2996 |
2997 | 2997 |
2998 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { | 2998 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { |
2999 ASSERT(ToRegister(instr->context()).is(rsi)); | 2999 DCHECK(ToRegister(instr->context()).is(rsi)); |
3000 ASSERT(ToRegister(instr->object()).is(LoadIC::ReceiverRegister())); | 3000 DCHECK(ToRegister(instr->object()).is(LoadIC::ReceiverRegister())); |
3001 ASSERT(ToRegister(instr->result()).is(rax)); | 3001 DCHECK(ToRegister(instr->result()).is(rax)); |
3002 | 3002 |
3003 __ Move(LoadIC::NameRegister(), instr->name()); | 3003 __ Move(LoadIC::NameRegister(), instr->name()); |
3004 if (FLAG_vector_ics) { | 3004 if (FLAG_vector_ics) { |
3005 Register vector = ToRegister(instr->temp_vector()); | 3005 Register vector = ToRegister(instr->temp_vector()); |
3006 ASSERT(vector.is(LoadIC::VectorRegister())); | 3006 DCHECK(vector.is(LoadIC::VectorRegister())); |
3007 __ Move(vector, instr->hydrogen()->feedback_vector()); | 3007 __ Move(vector, instr->hydrogen()->feedback_vector()); |
3008 // No need to allocate this register. | 3008 // No need to allocate this register. |
3009 ASSERT(LoadIC::SlotRegister().is(rax)); | 3009 DCHECK(LoadIC::SlotRegister().is(rax)); |
3010 __ Move(LoadIC::SlotRegister(), Smi::FromInt(instr->hydrogen()->slot())); | 3010 __ Move(LoadIC::SlotRegister(), Smi::FromInt(instr->hydrogen()->slot())); |
3011 } | 3011 } |
3012 Handle<Code> ic = LoadIC::initialize_stub(isolate(), NOT_CONTEXTUAL); | 3012 Handle<Code> ic = LoadIC::initialize_stub(isolate(), NOT_CONTEXTUAL); |
3013 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 3013 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
3014 } | 3014 } |
3015 | 3015 |
3016 | 3016 |
3017 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { | 3017 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { |
3018 Register function = ToRegister(instr->function()); | 3018 Register function = ToRegister(instr->function()); |
3019 Register result = ToRegister(instr->result()); | 3019 Register result = ToRegister(instr->result()); |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3197 int offset = instr->base_offset(); | 3197 int offset = instr->base_offset(); |
3198 | 3198 |
3199 if (kPointerSize == kInt32Size && !key->IsConstantOperand() && | 3199 if (kPointerSize == kInt32Size && !key->IsConstantOperand() && |
3200 instr->hydrogen()->IsDehoisted()) { | 3200 instr->hydrogen()->IsDehoisted()) { |
3201 // Sign extend key because it could be a 32 bit negative value | 3201 // Sign extend key because it could be a 32 bit negative value |
3202 // and the dehoisted address computation happens in 64 bits | 3202 // and the dehoisted address computation happens in 64 bits |
3203 __ movsxlq(ToRegister(key), ToRegister(key)); | 3203 __ movsxlq(ToRegister(key), ToRegister(key)); |
3204 } | 3204 } |
3205 if (representation.IsInteger32() && SmiValuesAre32Bits() && | 3205 if (representation.IsInteger32() && SmiValuesAre32Bits() && |
3206 hinstr->elements_kind() == FAST_SMI_ELEMENTS) { | 3206 hinstr->elements_kind() == FAST_SMI_ELEMENTS) { |
3207 ASSERT(!requires_hole_check); | 3207 DCHECK(!requires_hole_check); |
3208 if (FLAG_debug_code) { | 3208 if (FLAG_debug_code) { |
3209 Register scratch = kScratchRegister; | 3209 Register scratch = kScratchRegister; |
3210 __ Load(scratch, | 3210 __ Load(scratch, |
3211 BuildFastArrayOperand(instr->elements(), | 3211 BuildFastArrayOperand(instr->elements(), |
3212 key, | 3212 key, |
3213 instr->hydrogen()->key()->representation(), | 3213 instr->hydrogen()->key()->representation(), |
3214 FAST_ELEMENTS, | 3214 FAST_ELEMENTS, |
3215 offset), | 3215 offset), |
3216 Representation::Smi()); | 3216 Representation::Smi()); |
3217 __ AssertSmi(scratch); | 3217 __ AssertSmi(scratch); |
3218 } | 3218 } |
3219 // Read int value directly from upper half of the smi. | 3219 // Read int value directly from upper half of the smi. |
3220 STATIC_ASSERT(kSmiTag == 0); | 3220 STATIC_ASSERT(kSmiTag == 0); |
3221 ASSERT(kSmiTagSize + kSmiShiftSize == 32); | 3221 DCHECK(kSmiTagSize + kSmiShiftSize == 32); |
3222 offset += kPointerSize / 2; | 3222 offset += kPointerSize / 2; |
3223 } | 3223 } |
3224 | 3224 |
3225 __ Load(result, | 3225 __ Load(result, |
3226 BuildFastArrayOperand(instr->elements(), | 3226 BuildFastArrayOperand(instr->elements(), |
3227 key, | 3227 key, |
3228 instr->hydrogen()->key()->representation(), | 3228 instr->hydrogen()->key()->representation(), |
3229 FAST_ELEMENTS, | 3229 FAST_ELEMENTS, |
3230 offset), | 3230 offset), |
3231 representation); | 3231 representation); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3265 if (key->IsConstantOperand()) { | 3265 if (key->IsConstantOperand()) { |
3266 int32_t constant_value = ToInteger32(LConstantOperand::cast(key)); | 3266 int32_t constant_value = ToInteger32(LConstantOperand::cast(key)); |
3267 if (constant_value & 0xF0000000) { | 3267 if (constant_value & 0xF0000000) { |
3268 Abort(kArrayIndexConstantValueTooBig); | 3268 Abort(kArrayIndexConstantValueTooBig); |
3269 } | 3269 } |
3270 return Operand(elements_pointer_reg, | 3270 return Operand(elements_pointer_reg, |
3271 (constant_value << shift_size) + offset); | 3271 (constant_value << shift_size) + offset); |
3272 } else { | 3272 } else { |
3273 // Take the tag bit into account while computing the shift size. | 3273 // Take the tag bit into account while computing the shift size. |
3274 if (key_representation.IsSmi() && (shift_size >= 1)) { | 3274 if (key_representation.IsSmi() && (shift_size >= 1)) { |
3275 ASSERT(SmiValuesAre31Bits()); | 3275 DCHECK(SmiValuesAre31Bits()); |
3276 shift_size -= kSmiTagSize; | 3276 shift_size -= kSmiTagSize; |
3277 } | 3277 } |
3278 ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size); | 3278 ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size); |
3279 return Operand(elements_pointer_reg, | 3279 return Operand(elements_pointer_reg, |
3280 ToRegister(key), | 3280 ToRegister(key), |
3281 scale_factor, | 3281 scale_factor, |
3282 offset); | 3282 offset); |
3283 } | 3283 } |
3284 } | 3284 } |
3285 | 3285 |
3286 | 3286 |
3287 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { | 3287 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { |
3288 ASSERT(ToRegister(instr->context()).is(rsi)); | 3288 DCHECK(ToRegister(instr->context()).is(rsi)); |
3289 ASSERT(ToRegister(instr->object()).is(LoadIC::ReceiverRegister())); | 3289 DCHECK(ToRegister(instr->object()).is(LoadIC::ReceiverRegister())); |
3290 ASSERT(ToRegister(instr->key()).is(LoadIC::NameRegister())); | 3290 DCHECK(ToRegister(instr->key()).is(LoadIC::NameRegister())); |
3291 | 3291 |
3292 if (FLAG_vector_ics) { | 3292 if (FLAG_vector_ics) { |
3293 Register vector = ToRegister(instr->temp_vector()); | 3293 Register vector = ToRegister(instr->temp_vector()); |
3294 ASSERT(vector.is(LoadIC::VectorRegister())); | 3294 DCHECK(vector.is(LoadIC::VectorRegister())); |
3295 __ Move(vector, instr->hydrogen()->feedback_vector()); | 3295 __ Move(vector, instr->hydrogen()->feedback_vector()); |
3296 // No need to allocate this register. | 3296 // No need to allocate this register. |
3297 ASSERT(LoadIC::SlotRegister().is(rax)); | 3297 DCHECK(LoadIC::SlotRegister().is(rax)); |
3298 __ Move(LoadIC::SlotRegister(), Smi::FromInt(instr->hydrogen()->slot())); | 3298 __ Move(LoadIC::SlotRegister(), Smi::FromInt(instr->hydrogen()->slot())); |
3299 } | 3299 } |
3300 | 3300 |
3301 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 3301 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
3302 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 3302 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
3303 } | 3303 } |
3304 | 3304 |
3305 | 3305 |
3306 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { | 3306 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { |
3307 Register result = ToRegister(instr->result()); | 3307 Register result = ToRegister(instr->result()); |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3405 | 3405 |
3406 __ bind(&receiver_ok); | 3406 __ bind(&receiver_ok); |
3407 } | 3407 } |
3408 | 3408 |
3409 | 3409 |
3410 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { | 3410 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { |
3411 Register receiver = ToRegister(instr->receiver()); | 3411 Register receiver = ToRegister(instr->receiver()); |
3412 Register function = ToRegister(instr->function()); | 3412 Register function = ToRegister(instr->function()); |
3413 Register length = ToRegister(instr->length()); | 3413 Register length = ToRegister(instr->length()); |
3414 Register elements = ToRegister(instr->elements()); | 3414 Register elements = ToRegister(instr->elements()); |
3415 ASSERT(receiver.is(rax)); // Used for parameter count. | 3415 DCHECK(receiver.is(rax)); // Used for parameter count. |
3416 ASSERT(function.is(rdi)); // Required by InvokeFunction. | 3416 DCHECK(function.is(rdi)); // Required by InvokeFunction. |
3417 ASSERT(ToRegister(instr->result()).is(rax)); | 3417 DCHECK(ToRegister(instr->result()).is(rax)); |
3418 | 3418 |
3419 // Copy the arguments to this function possibly from the | 3419 // Copy the arguments to this function possibly from the |
3420 // adaptor frame below it. | 3420 // adaptor frame below it. |
3421 const uint32_t kArgumentsLimit = 1 * KB; | 3421 const uint32_t kArgumentsLimit = 1 * KB; |
3422 __ cmpp(length, Immediate(kArgumentsLimit)); | 3422 __ cmpp(length, Immediate(kArgumentsLimit)); |
3423 DeoptimizeIf(above, instr->environment()); | 3423 DeoptimizeIf(above, instr->environment()); |
3424 | 3424 |
3425 __ Push(receiver); | 3425 __ Push(receiver); |
3426 __ movp(receiver, length); | 3426 __ movp(receiver, length); |
3427 | 3427 |
3428 // Loop through the arguments pushing them onto the execution | 3428 // Loop through the arguments pushing them onto the execution |
3429 // stack. | 3429 // stack. |
3430 Label invoke, loop; | 3430 Label invoke, loop; |
3431 // length is a small non-negative integer, due to the test above. | 3431 // length is a small non-negative integer, due to the test above. |
3432 __ testl(length, length); | 3432 __ testl(length, length); |
3433 __ j(zero, &invoke, Label::kNear); | 3433 __ j(zero, &invoke, Label::kNear); |
3434 __ bind(&loop); | 3434 __ bind(&loop); |
3435 StackArgumentsAccessor args(elements, length, | 3435 StackArgumentsAccessor args(elements, length, |
3436 ARGUMENTS_DONT_CONTAIN_RECEIVER); | 3436 ARGUMENTS_DONT_CONTAIN_RECEIVER); |
3437 __ Push(args.GetArgumentOperand(0)); | 3437 __ Push(args.GetArgumentOperand(0)); |
3438 __ decl(length); | 3438 __ decl(length); |
3439 __ j(not_zero, &loop); | 3439 __ j(not_zero, &loop); |
3440 | 3440 |
3441 // Invoke the function. | 3441 // Invoke the function. |
3442 __ bind(&invoke); | 3442 __ bind(&invoke); |
3443 ASSERT(instr->HasPointerMap()); | 3443 DCHECK(instr->HasPointerMap()); |
3444 LPointerMap* pointers = instr->pointer_map(); | 3444 LPointerMap* pointers = instr->pointer_map(); |
3445 SafepointGenerator safepoint_generator( | 3445 SafepointGenerator safepoint_generator( |
3446 this, pointers, Safepoint::kLazyDeopt); | 3446 this, pointers, Safepoint::kLazyDeopt); |
3447 ParameterCount actual(rax); | 3447 ParameterCount actual(rax); |
3448 __ InvokeFunction(function, actual, CALL_FUNCTION, safepoint_generator); | 3448 __ InvokeFunction(function, actual, CALL_FUNCTION, safepoint_generator); |
3449 } | 3449 } |
3450 | 3450 |
3451 | 3451 |
3452 void LCodeGen::DoPushArgument(LPushArgument* instr) { | 3452 void LCodeGen::DoPushArgument(LPushArgument* instr) { |
3453 LOperand* argument = instr->value(); | 3453 LOperand* argument = instr->value(); |
(...skipping 11 matching lines...) Expand all Loading... |
3465 __ movp(result, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); | 3465 __ movp(result, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); |
3466 } | 3466 } |
3467 | 3467 |
3468 | 3468 |
3469 void LCodeGen::DoContext(LContext* instr) { | 3469 void LCodeGen::DoContext(LContext* instr) { |
3470 Register result = ToRegister(instr->result()); | 3470 Register result = ToRegister(instr->result()); |
3471 if (info()->IsOptimizing()) { | 3471 if (info()->IsOptimizing()) { |
3472 __ movp(result, Operand(rbp, StandardFrameConstants::kContextOffset)); | 3472 __ movp(result, Operand(rbp, StandardFrameConstants::kContextOffset)); |
3473 } else { | 3473 } else { |
3474 // If there is no frame, the context must be in rsi. | 3474 // If there is no frame, the context must be in rsi. |
3475 ASSERT(result.is(rsi)); | 3475 DCHECK(result.is(rsi)); |
3476 } | 3476 } |
3477 } | 3477 } |
3478 | 3478 |
3479 | 3479 |
3480 void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) { | 3480 void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) { |
3481 ASSERT(ToRegister(instr->context()).is(rsi)); | 3481 DCHECK(ToRegister(instr->context()).is(rsi)); |
3482 __ Push(rsi); // The context is the first argument. | 3482 __ Push(rsi); // The context is the first argument. |
3483 __ Push(instr->hydrogen()->pairs()); | 3483 __ Push(instr->hydrogen()->pairs()); |
3484 __ Push(Smi::FromInt(instr->hydrogen()->flags())); | 3484 __ Push(Smi::FromInt(instr->hydrogen()->flags())); |
3485 CallRuntime(Runtime::kDeclareGlobals, 3, instr); | 3485 CallRuntime(Runtime::kDeclareGlobals, 3, instr); |
3486 } | 3486 } |
3487 | 3487 |
3488 | 3488 |
3489 void LCodeGen::CallKnownFunction(Handle<JSFunction> function, | 3489 void LCodeGen::CallKnownFunction(Handle<JSFunction> function, |
3490 int formal_parameter_count, | 3490 int formal_parameter_count, |
3491 int arity, | 3491 int arity, |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3526 SafepointGenerator generator( | 3526 SafepointGenerator generator( |
3527 this, pointers, Safepoint::kLazyDeopt); | 3527 this, pointers, Safepoint::kLazyDeopt); |
3528 ParameterCount count(arity); | 3528 ParameterCount count(arity); |
3529 ParameterCount expected(formal_parameter_count); | 3529 ParameterCount expected(formal_parameter_count); |
3530 __ InvokeFunction(function, expected, count, CALL_FUNCTION, generator); | 3530 __ InvokeFunction(function, expected, count, CALL_FUNCTION, generator); |
3531 } | 3531 } |
3532 } | 3532 } |
3533 | 3533 |
3534 | 3534 |
3535 void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) { | 3535 void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) { |
3536 ASSERT(ToRegister(instr->result()).is(rax)); | 3536 DCHECK(ToRegister(instr->result()).is(rax)); |
3537 | 3537 |
3538 LPointerMap* pointers = instr->pointer_map(); | 3538 LPointerMap* pointers = instr->pointer_map(); |
3539 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); | 3539 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); |
3540 | 3540 |
3541 if (instr->target()->IsConstantOperand()) { | 3541 if (instr->target()->IsConstantOperand()) { |
3542 LConstantOperand* target = LConstantOperand::cast(instr->target()); | 3542 LConstantOperand* target = LConstantOperand::cast(instr->target()); |
3543 Handle<Code> code = Handle<Code>::cast(ToHandle(target)); | 3543 Handle<Code> code = Handle<Code>::cast(ToHandle(target)); |
3544 generator.BeforeCall(__ CallSize(code)); | 3544 generator.BeforeCall(__ CallSize(code)); |
3545 __ call(code, RelocInfo::CODE_TARGET); | 3545 __ call(code, RelocInfo::CODE_TARGET); |
3546 } else { | 3546 } else { |
3547 ASSERT(instr->target()->IsRegister()); | 3547 DCHECK(instr->target()->IsRegister()); |
3548 Register target = ToRegister(instr->target()); | 3548 Register target = ToRegister(instr->target()); |
3549 generator.BeforeCall(__ CallSize(target)); | 3549 generator.BeforeCall(__ CallSize(target)); |
3550 __ addp(target, Immediate(Code::kHeaderSize - kHeapObjectTag)); | 3550 __ addp(target, Immediate(Code::kHeaderSize - kHeapObjectTag)); |
3551 __ call(target); | 3551 __ call(target); |
3552 } | 3552 } |
3553 generator.AfterCall(); | 3553 generator.AfterCall(); |
3554 } | 3554 } |
3555 | 3555 |
3556 | 3556 |
3557 void LCodeGen::DoCallJSFunction(LCallJSFunction* instr) { | 3557 void LCodeGen::DoCallJSFunction(LCallJSFunction* instr) { |
3558 ASSERT(ToRegister(instr->function()).is(rdi)); | 3558 DCHECK(ToRegister(instr->function()).is(rdi)); |
3559 ASSERT(ToRegister(instr->result()).is(rax)); | 3559 DCHECK(ToRegister(instr->result()).is(rax)); |
3560 | 3560 |
3561 if (instr->hydrogen()->pass_argument_count()) { | 3561 if (instr->hydrogen()->pass_argument_count()) { |
3562 __ Set(rax, instr->arity()); | 3562 __ Set(rax, instr->arity()); |
3563 } | 3563 } |
3564 | 3564 |
3565 // Change context. | 3565 // Change context. |
3566 __ movp(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); | 3566 __ movp(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); |
3567 | 3567 |
3568 LPointerMap* pointers = instr->pointer_map(); | 3568 LPointerMap* pointers = instr->pointer_map(); |
3569 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); | 3569 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3660 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, LMathAbs* instr) | 3660 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, LMathAbs* instr) |
3661 : LDeferredCode(codegen), instr_(instr) { } | 3661 : LDeferredCode(codegen), instr_(instr) { } |
3662 virtual void Generate() V8_OVERRIDE { | 3662 virtual void Generate() V8_OVERRIDE { |
3663 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); | 3663 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); |
3664 } | 3664 } |
3665 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } | 3665 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
3666 private: | 3666 private: |
3667 LMathAbs* instr_; | 3667 LMathAbs* instr_; |
3668 }; | 3668 }; |
3669 | 3669 |
3670 ASSERT(instr->value()->Equals(instr->result())); | 3670 DCHECK(instr->value()->Equals(instr->result())); |
3671 Representation r = instr->hydrogen()->value()->representation(); | 3671 Representation r = instr->hydrogen()->value()->representation(); |
3672 | 3672 |
3673 if (r.IsDouble()) { | 3673 if (r.IsDouble()) { |
3674 XMMRegister scratch = double_scratch0(); | 3674 XMMRegister scratch = double_scratch0(); |
3675 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 3675 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
3676 __ xorps(scratch, scratch); | 3676 __ xorps(scratch, scratch); |
3677 __ subsd(scratch, input_reg); | 3677 __ subsd(scratch, input_reg); |
3678 __ andps(input_reg, scratch); | 3678 __ andps(input_reg, scratch); |
3679 } else if (r.IsInteger32()) { | 3679 } else if (r.IsInteger32()) { |
3680 EmitIntegerMathAbs(instr); | 3680 EmitIntegerMathAbs(instr); |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3828 } else { | 3828 } else { |
3829 Operand input = ToOperand(instr->value()); | 3829 Operand input = ToOperand(instr->value()); |
3830 __ sqrtsd(output, input); | 3830 __ sqrtsd(output, input); |
3831 } | 3831 } |
3832 } | 3832 } |
3833 | 3833 |
3834 | 3834 |
3835 void LCodeGen::DoMathPowHalf(LMathPowHalf* instr) { | 3835 void LCodeGen::DoMathPowHalf(LMathPowHalf* instr) { |
3836 XMMRegister xmm_scratch = double_scratch0(); | 3836 XMMRegister xmm_scratch = double_scratch0(); |
3837 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 3837 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
3838 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); | 3838 DCHECK(ToDoubleRegister(instr->result()).is(input_reg)); |
3839 | 3839 |
3840 // Note that according to ECMA-262 15.8.2.13: | 3840 // Note that according to ECMA-262 15.8.2.13: |
3841 // Math.pow(-Infinity, 0.5) == Infinity | 3841 // Math.pow(-Infinity, 0.5) == Infinity |
3842 // Math.sqrt(-Infinity) == NaN | 3842 // Math.sqrt(-Infinity) == NaN |
3843 Label done, sqrt; | 3843 Label done, sqrt; |
3844 // Check base for -Infinity. According to IEEE-754, double-precision | 3844 // Check base for -Infinity. According to IEEE-754, double-precision |
3845 // -Infinity has the highest 12 bits set and the lowest 52 bits cleared. | 3845 // -Infinity has the highest 12 bits set and the lowest 52 bits cleared. |
3846 __ movq(kScratchRegister, V8_INT64_C(0xFFF0000000000000)); | 3846 __ movq(kScratchRegister, V8_INT64_C(0xFFF0000000000000)); |
3847 __ movq(xmm_scratch, kScratchRegister); | 3847 __ movq(xmm_scratch, kScratchRegister); |
3848 __ ucomisd(xmm_scratch, input_reg); | 3848 __ ucomisd(xmm_scratch, input_reg); |
(...skipping 14 matching lines...) Expand all Loading... |
3863 __ bind(&done); | 3863 __ bind(&done); |
3864 } | 3864 } |
3865 | 3865 |
3866 | 3866 |
3867 void LCodeGen::DoPower(LPower* instr) { | 3867 void LCodeGen::DoPower(LPower* instr) { |
3868 Representation exponent_type = instr->hydrogen()->right()->representation(); | 3868 Representation exponent_type = instr->hydrogen()->right()->representation(); |
3869 // Having marked this as a call, we can use any registers. | 3869 // Having marked this as a call, we can use any registers. |
3870 // Just make sure that the input/output registers are the expected ones. | 3870 // Just make sure that the input/output registers are the expected ones. |
3871 | 3871 |
3872 Register exponent = rdx; | 3872 Register exponent = rdx; |
3873 ASSERT(!instr->right()->IsRegister() || | 3873 DCHECK(!instr->right()->IsRegister() || |
3874 ToRegister(instr->right()).is(exponent)); | 3874 ToRegister(instr->right()).is(exponent)); |
3875 ASSERT(!instr->right()->IsDoubleRegister() || | 3875 DCHECK(!instr->right()->IsDoubleRegister() || |
3876 ToDoubleRegister(instr->right()).is(xmm1)); | 3876 ToDoubleRegister(instr->right()).is(xmm1)); |
3877 ASSERT(ToDoubleRegister(instr->left()).is(xmm2)); | 3877 DCHECK(ToDoubleRegister(instr->left()).is(xmm2)); |
3878 ASSERT(ToDoubleRegister(instr->result()).is(xmm3)); | 3878 DCHECK(ToDoubleRegister(instr->result()).is(xmm3)); |
3879 | 3879 |
3880 if (exponent_type.IsSmi()) { | 3880 if (exponent_type.IsSmi()) { |
3881 MathPowStub stub(isolate(), MathPowStub::TAGGED); | 3881 MathPowStub stub(isolate(), MathPowStub::TAGGED); |
3882 __ CallStub(&stub); | 3882 __ CallStub(&stub); |
3883 } else if (exponent_type.IsTagged()) { | 3883 } else if (exponent_type.IsTagged()) { |
3884 Label no_deopt; | 3884 Label no_deopt; |
3885 __ JumpIfSmi(exponent, &no_deopt, Label::kNear); | 3885 __ JumpIfSmi(exponent, &no_deopt, Label::kNear); |
3886 __ CmpObjectType(exponent, HEAP_NUMBER_TYPE, rcx); | 3886 __ CmpObjectType(exponent, HEAP_NUMBER_TYPE, rcx); |
3887 DeoptimizeIf(not_equal, instr->environment()); | 3887 DeoptimizeIf(not_equal, instr->environment()); |
3888 __ bind(&no_deopt); | 3888 __ bind(&no_deopt); |
3889 MathPowStub stub(isolate(), MathPowStub::TAGGED); | 3889 MathPowStub stub(isolate(), MathPowStub::TAGGED); |
3890 __ CallStub(&stub); | 3890 __ CallStub(&stub); |
3891 } else if (exponent_type.IsInteger32()) { | 3891 } else if (exponent_type.IsInteger32()) { |
3892 MathPowStub stub(isolate(), MathPowStub::INTEGER); | 3892 MathPowStub stub(isolate(), MathPowStub::INTEGER); |
3893 __ CallStub(&stub); | 3893 __ CallStub(&stub); |
3894 } else { | 3894 } else { |
3895 ASSERT(exponent_type.IsDouble()); | 3895 DCHECK(exponent_type.IsDouble()); |
3896 MathPowStub stub(isolate(), MathPowStub::DOUBLE); | 3896 MathPowStub stub(isolate(), MathPowStub::DOUBLE); |
3897 __ CallStub(&stub); | 3897 __ CallStub(&stub); |
3898 } | 3898 } |
3899 } | 3899 } |
3900 | 3900 |
3901 | 3901 |
3902 void LCodeGen::DoMathExp(LMathExp* instr) { | 3902 void LCodeGen::DoMathExp(LMathExp* instr) { |
3903 XMMRegister input = ToDoubleRegister(instr->value()); | 3903 XMMRegister input = ToDoubleRegister(instr->value()); |
3904 XMMRegister result = ToDoubleRegister(instr->result()); | 3904 XMMRegister result = ToDoubleRegister(instr->result()); |
3905 XMMRegister temp0 = double_scratch0(); | 3905 XMMRegister temp0 = double_scratch0(); |
3906 Register temp1 = ToRegister(instr->temp1()); | 3906 Register temp1 = ToRegister(instr->temp1()); |
3907 Register temp2 = ToRegister(instr->temp2()); | 3907 Register temp2 = ToRegister(instr->temp2()); |
3908 | 3908 |
3909 MathExpGenerator::EmitMathExp(masm(), input, result, temp0, temp1, temp2); | 3909 MathExpGenerator::EmitMathExp(masm(), input, result, temp0, temp1, temp2); |
3910 } | 3910 } |
3911 | 3911 |
3912 | 3912 |
3913 void LCodeGen::DoMathLog(LMathLog* instr) { | 3913 void LCodeGen::DoMathLog(LMathLog* instr) { |
3914 ASSERT(instr->value()->Equals(instr->result())); | 3914 DCHECK(instr->value()->Equals(instr->result())); |
3915 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 3915 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
3916 XMMRegister xmm_scratch = double_scratch0(); | 3916 XMMRegister xmm_scratch = double_scratch0(); |
3917 Label positive, done, zero; | 3917 Label positive, done, zero; |
3918 __ xorps(xmm_scratch, xmm_scratch); | 3918 __ xorps(xmm_scratch, xmm_scratch); |
3919 __ ucomisd(input_reg, xmm_scratch); | 3919 __ ucomisd(input_reg, xmm_scratch); |
3920 __ j(above, &positive, Label::kNear); | 3920 __ j(above, &positive, Label::kNear); |
3921 __ j(not_carry, &zero, Label::kNear); | 3921 __ j(not_carry, &zero, Label::kNear); |
3922 ExternalReference nan = | 3922 ExternalReference nan = |
3923 ExternalReference::address_of_canonical_non_hole_nan(); | 3923 ExternalReference::address_of_canonical_non_hole_nan(); |
3924 Operand nan_operand = masm()->ExternalOperand(nan); | 3924 Operand nan_operand = masm()->ExternalOperand(nan); |
(...skipping 26 matching lines...) Expand all Loading... |
3951 | 3951 |
3952 __ j(not_zero, ¬_zero_input); | 3952 __ j(not_zero, ¬_zero_input); |
3953 __ Set(result, 63); // 63^31 == 32 | 3953 __ Set(result, 63); // 63^31 == 32 |
3954 | 3954 |
3955 __ bind(¬_zero_input); | 3955 __ bind(¬_zero_input); |
3956 __ xorl(result, Immediate(31)); // for x in [0..31], 31^x == 31-x. | 3956 __ xorl(result, Immediate(31)); // for x in [0..31], 31^x == 31-x. |
3957 } | 3957 } |
3958 | 3958 |
3959 | 3959 |
3960 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { | 3960 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { |
3961 ASSERT(ToRegister(instr->context()).is(rsi)); | 3961 DCHECK(ToRegister(instr->context()).is(rsi)); |
3962 ASSERT(ToRegister(instr->function()).is(rdi)); | 3962 DCHECK(ToRegister(instr->function()).is(rdi)); |
3963 ASSERT(instr->HasPointerMap()); | 3963 DCHECK(instr->HasPointerMap()); |
3964 | 3964 |
3965 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); | 3965 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); |
3966 if (known_function.is_null()) { | 3966 if (known_function.is_null()) { |
3967 LPointerMap* pointers = instr->pointer_map(); | 3967 LPointerMap* pointers = instr->pointer_map(); |
3968 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); | 3968 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); |
3969 ParameterCount count(instr->arity()); | 3969 ParameterCount count(instr->arity()); |
3970 __ InvokeFunction(rdi, count, CALL_FUNCTION, generator); | 3970 __ InvokeFunction(rdi, count, CALL_FUNCTION, generator); |
3971 } else { | 3971 } else { |
3972 CallKnownFunction(known_function, | 3972 CallKnownFunction(known_function, |
3973 instr->hydrogen()->formal_parameter_count(), | 3973 instr->hydrogen()->formal_parameter_count(), |
3974 instr->arity(), | 3974 instr->arity(), |
3975 instr, | 3975 instr, |
3976 RDI_CONTAINS_TARGET); | 3976 RDI_CONTAINS_TARGET); |
3977 } | 3977 } |
3978 } | 3978 } |
3979 | 3979 |
3980 | 3980 |
3981 void LCodeGen::DoCallFunction(LCallFunction* instr) { | 3981 void LCodeGen::DoCallFunction(LCallFunction* instr) { |
3982 ASSERT(ToRegister(instr->context()).is(rsi)); | 3982 DCHECK(ToRegister(instr->context()).is(rsi)); |
3983 ASSERT(ToRegister(instr->function()).is(rdi)); | 3983 DCHECK(ToRegister(instr->function()).is(rdi)); |
3984 ASSERT(ToRegister(instr->result()).is(rax)); | 3984 DCHECK(ToRegister(instr->result()).is(rax)); |
3985 | 3985 |
3986 int arity = instr->arity(); | 3986 int arity = instr->arity(); |
3987 CallFunctionStub stub(isolate(), arity, instr->hydrogen()->function_flags()); | 3987 CallFunctionStub stub(isolate(), arity, instr->hydrogen()->function_flags()); |
3988 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 3988 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
3989 } | 3989 } |
3990 | 3990 |
3991 | 3991 |
3992 void LCodeGen::DoCallNew(LCallNew* instr) { | 3992 void LCodeGen::DoCallNew(LCallNew* instr) { |
3993 ASSERT(ToRegister(instr->context()).is(rsi)); | 3993 DCHECK(ToRegister(instr->context()).is(rsi)); |
3994 ASSERT(ToRegister(instr->constructor()).is(rdi)); | 3994 DCHECK(ToRegister(instr->constructor()).is(rdi)); |
3995 ASSERT(ToRegister(instr->result()).is(rax)); | 3995 DCHECK(ToRegister(instr->result()).is(rax)); |
3996 | 3996 |
3997 __ Set(rax, instr->arity()); | 3997 __ Set(rax, instr->arity()); |
3998 // No cell in ebx for construct type feedback in optimized code | 3998 // No cell in ebx for construct type feedback in optimized code |
3999 __ LoadRoot(rbx, Heap::kUndefinedValueRootIndex); | 3999 __ LoadRoot(rbx, Heap::kUndefinedValueRootIndex); |
4000 CallConstructStub stub(isolate(), NO_CALL_CONSTRUCTOR_FLAGS); | 4000 CallConstructStub stub(isolate(), NO_CALL_CONSTRUCTOR_FLAGS); |
4001 CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr); | 4001 CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr); |
4002 } | 4002 } |
4003 | 4003 |
4004 | 4004 |
4005 void LCodeGen::DoCallNewArray(LCallNewArray* instr) { | 4005 void LCodeGen::DoCallNewArray(LCallNewArray* instr) { |
4006 ASSERT(ToRegister(instr->context()).is(rsi)); | 4006 DCHECK(ToRegister(instr->context()).is(rsi)); |
4007 ASSERT(ToRegister(instr->constructor()).is(rdi)); | 4007 DCHECK(ToRegister(instr->constructor()).is(rdi)); |
4008 ASSERT(ToRegister(instr->result()).is(rax)); | 4008 DCHECK(ToRegister(instr->result()).is(rax)); |
4009 | 4009 |
4010 __ Set(rax, instr->arity()); | 4010 __ Set(rax, instr->arity()); |
4011 __ LoadRoot(rbx, Heap::kUndefinedValueRootIndex); | 4011 __ LoadRoot(rbx, Heap::kUndefinedValueRootIndex); |
4012 ElementsKind kind = instr->hydrogen()->elements_kind(); | 4012 ElementsKind kind = instr->hydrogen()->elements_kind(); |
4013 AllocationSiteOverrideMode override_mode = | 4013 AllocationSiteOverrideMode override_mode = |
4014 (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE) | 4014 (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE) |
4015 ? DISABLE_ALLOCATION_SITES | 4015 ? DISABLE_ALLOCATION_SITES |
4016 : DONT_OVERRIDE; | 4016 : DONT_OVERRIDE; |
4017 | 4017 |
4018 if (instr->arity() == 0) { | 4018 if (instr->arity() == 0) { |
(...skipping 22 matching lines...) Expand all Loading... |
4041 CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr); | 4041 CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr); |
4042 __ bind(&done); | 4042 __ bind(&done); |
4043 } else { | 4043 } else { |
4044 ArrayNArgumentsConstructorStub stub(isolate(), kind, override_mode); | 4044 ArrayNArgumentsConstructorStub stub(isolate(), kind, override_mode); |
4045 CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr); | 4045 CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr); |
4046 } | 4046 } |
4047 } | 4047 } |
4048 | 4048 |
4049 | 4049 |
4050 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { | 4050 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { |
4051 ASSERT(ToRegister(instr->context()).is(rsi)); | 4051 DCHECK(ToRegister(instr->context()).is(rsi)); |
4052 CallRuntime(instr->function(), instr->arity(), instr, instr->save_doubles()); | 4052 CallRuntime(instr->function(), instr->arity(), instr, instr->save_doubles()); |
4053 } | 4053 } |
4054 | 4054 |
4055 | 4055 |
4056 void LCodeGen::DoStoreCodeEntry(LStoreCodeEntry* instr) { | 4056 void LCodeGen::DoStoreCodeEntry(LStoreCodeEntry* instr) { |
4057 Register function = ToRegister(instr->function()); | 4057 Register function = ToRegister(instr->function()); |
4058 Register code_object = ToRegister(instr->code_object()); | 4058 Register code_object = ToRegister(instr->code_object()); |
4059 __ leap(code_object, FieldOperand(code_object, Code::kHeaderSize)); | 4059 __ leap(code_object, FieldOperand(code_object, Code::kHeaderSize)); |
4060 __ movp(FieldOperand(function, JSFunction::kCodeEntryOffset), code_object); | 4060 __ movp(FieldOperand(function, JSFunction::kCodeEntryOffset), code_object); |
4061 } | 4061 } |
(...skipping 13 matching lines...) Expand all Loading... |
4075 | 4075 |
4076 | 4076 |
4077 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { | 4077 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { |
4078 HStoreNamedField* hinstr = instr->hydrogen(); | 4078 HStoreNamedField* hinstr = instr->hydrogen(); |
4079 Representation representation = instr->representation(); | 4079 Representation representation = instr->representation(); |
4080 | 4080 |
4081 HObjectAccess access = hinstr->access(); | 4081 HObjectAccess access = hinstr->access(); |
4082 int offset = access.offset(); | 4082 int offset = access.offset(); |
4083 | 4083 |
4084 if (access.IsExternalMemory()) { | 4084 if (access.IsExternalMemory()) { |
4085 ASSERT(!hinstr->NeedsWriteBarrier()); | 4085 DCHECK(!hinstr->NeedsWriteBarrier()); |
4086 Register value = ToRegister(instr->value()); | 4086 Register value = ToRegister(instr->value()); |
4087 if (instr->object()->IsConstantOperand()) { | 4087 if (instr->object()->IsConstantOperand()) { |
4088 ASSERT(value.is(rax)); | 4088 DCHECK(value.is(rax)); |
4089 LConstantOperand* object = LConstantOperand::cast(instr->object()); | 4089 LConstantOperand* object = LConstantOperand::cast(instr->object()); |
4090 __ store_rax(ToExternalReference(object)); | 4090 __ store_rax(ToExternalReference(object)); |
4091 } else { | 4091 } else { |
4092 Register object = ToRegister(instr->object()); | 4092 Register object = ToRegister(instr->object()); |
4093 __ Store(MemOperand(object, offset), value, representation); | 4093 __ Store(MemOperand(object, offset), value, representation); |
4094 } | 4094 } |
4095 return; | 4095 return; |
4096 } | 4096 } |
4097 | 4097 |
4098 Register object = ToRegister(instr->object()); | 4098 Register object = ToRegister(instr->object()); |
4099 __ AssertNotSmi(object); | 4099 __ AssertNotSmi(object); |
4100 | 4100 |
4101 ASSERT(!representation.IsSmi() || | 4101 DCHECK(!representation.IsSmi() || |
4102 !instr->value()->IsConstantOperand() || | 4102 !instr->value()->IsConstantOperand() || |
4103 IsInteger32Constant(LConstantOperand::cast(instr->value()))); | 4103 IsInteger32Constant(LConstantOperand::cast(instr->value()))); |
4104 if (representation.IsDouble()) { | 4104 if (representation.IsDouble()) { |
4105 ASSERT(access.IsInobject()); | 4105 DCHECK(access.IsInobject()); |
4106 ASSERT(!hinstr->has_transition()); | 4106 DCHECK(!hinstr->has_transition()); |
4107 ASSERT(!hinstr->NeedsWriteBarrier()); | 4107 DCHECK(!hinstr->NeedsWriteBarrier()); |
4108 XMMRegister value = ToDoubleRegister(instr->value()); | 4108 XMMRegister value = ToDoubleRegister(instr->value()); |
4109 __ movsd(FieldOperand(object, offset), value); | 4109 __ movsd(FieldOperand(object, offset), value); |
4110 return; | 4110 return; |
4111 } | 4111 } |
4112 | 4112 |
4113 if (hinstr->has_transition()) { | 4113 if (hinstr->has_transition()) { |
4114 Handle<Map> transition = hinstr->transition_map(); | 4114 Handle<Map> transition = hinstr->transition_map(); |
4115 AddDeprecationDependency(transition); | 4115 AddDeprecationDependency(transition); |
4116 if (!hinstr->NeedsWriteBarrierForMap()) { | 4116 if (!hinstr->NeedsWriteBarrierForMap()) { |
4117 __ Move(FieldOperand(object, HeapObject::kMapOffset), transition); | 4117 __ Move(FieldOperand(object, HeapObject::kMapOffset), transition); |
(...skipping 11 matching lines...) Expand all Loading... |
4129 | 4129 |
4130 // Do the store. | 4130 // Do the store. |
4131 Register write_register = object; | 4131 Register write_register = object; |
4132 if (!access.IsInobject()) { | 4132 if (!access.IsInobject()) { |
4133 write_register = ToRegister(instr->temp()); | 4133 write_register = ToRegister(instr->temp()); |
4134 __ movp(write_register, FieldOperand(object, JSObject::kPropertiesOffset)); | 4134 __ movp(write_register, FieldOperand(object, JSObject::kPropertiesOffset)); |
4135 } | 4135 } |
4136 | 4136 |
4137 if (representation.IsSmi() && SmiValuesAre32Bits() && | 4137 if (representation.IsSmi() && SmiValuesAre32Bits() && |
4138 hinstr->value()->representation().IsInteger32()) { | 4138 hinstr->value()->representation().IsInteger32()) { |
4139 ASSERT(hinstr->store_mode() == STORE_TO_INITIALIZED_ENTRY); | 4139 DCHECK(hinstr->store_mode() == STORE_TO_INITIALIZED_ENTRY); |
4140 if (FLAG_debug_code) { | 4140 if (FLAG_debug_code) { |
4141 Register scratch = kScratchRegister; | 4141 Register scratch = kScratchRegister; |
4142 __ Load(scratch, FieldOperand(write_register, offset), representation); | 4142 __ Load(scratch, FieldOperand(write_register, offset), representation); |
4143 __ AssertSmi(scratch); | 4143 __ AssertSmi(scratch); |
4144 } | 4144 } |
4145 // Store int value directly to upper half of the smi. | 4145 // Store int value directly to upper half of the smi. |
4146 STATIC_ASSERT(kSmiTag == 0); | 4146 STATIC_ASSERT(kSmiTag == 0); |
4147 ASSERT(kSmiTagSize + kSmiShiftSize == 32); | 4147 DCHECK(kSmiTagSize + kSmiShiftSize == 32); |
4148 offset += kPointerSize / 2; | 4148 offset += kPointerSize / 2; |
4149 representation = Representation::Integer32(); | 4149 representation = Representation::Integer32(); |
4150 } | 4150 } |
4151 | 4151 |
4152 Operand operand = FieldOperand(write_register, offset); | 4152 Operand operand = FieldOperand(write_register, offset); |
4153 | 4153 |
4154 if (instr->value()->IsRegister()) { | 4154 if (instr->value()->IsRegister()) { |
4155 Register value = ToRegister(instr->value()); | 4155 Register value = ToRegister(instr->value()); |
4156 __ Store(operand, value, representation); | 4156 __ Store(operand, value, representation); |
4157 } else { | 4157 } else { |
4158 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); | 4158 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); |
4159 if (IsInteger32Constant(operand_value)) { | 4159 if (IsInteger32Constant(operand_value)) { |
4160 ASSERT(!hinstr->NeedsWriteBarrier()); | 4160 DCHECK(!hinstr->NeedsWriteBarrier()); |
4161 int32_t value = ToInteger32(operand_value); | 4161 int32_t value = ToInteger32(operand_value); |
4162 if (representation.IsSmi()) { | 4162 if (representation.IsSmi()) { |
4163 __ Move(operand, Smi::FromInt(value)); | 4163 __ Move(operand, Smi::FromInt(value)); |
4164 | 4164 |
4165 } else { | 4165 } else { |
4166 __ movl(operand, Immediate(value)); | 4166 __ movl(operand, Immediate(value)); |
4167 } | 4167 } |
4168 | 4168 |
4169 } else { | 4169 } else { |
4170 Handle<Object> handle_value = ToHandle(operand_value); | 4170 Handle<Object> handle_value = ToHandle(operand_value); |
4171 ASSERT(!hinstr->NeedsWriteBarrier()); | 4171 DCHECK(!hinstr->NeedsWriteBarrier()); |
4172 __ Move(operand, handle_value); | 4172 __ Move(operand, handle_value); |
4173 } | 4173 } |
4174 } | 4174 } |
4175 | 4175 |
4176 if (hinstr->NeedsWriteBarrier()) { | 4176 if (hinstr->NeedsWriteBarrier()) { |
4177 Register value = ToRegister(instr->value()); | 4177 Register value = ToRegister(instr->value()); |
4178 Register temp = access.IsInobject() ? ToRegister(instr->temp()) : object; | 4178 Register temp = access.IsInobject() ? ToRegister(instr->temp()) : object; |
4179 // Update the write barrier for the object for in-object properties. | 4179 // Update the write barrier for the object for in-object properties. |
4180 __ RecordWriteField(write_register, | 4180 __ RecordWriteField(write_register, |
4181 offset, | 4181 offset, |
4182 value, | 4182 value, |
4183 temp, | 4183 temp, |
4184 kSaveFPRegs, | 4184 kSaveFPRegs, |
4185 EMIT_REMEMBERED_SET, | 4185 EMIT_REMEMBERED_SET, |
4186 hinstr->SmiCheckForWriteBarrier(), | 4186 hinstr->SmiCheckForWriteBarrier(), |
4187 hinstr->PointersToHereCheckForValue()); | 4187 hinstr->PointersToHereCheckForValue()); |
4188 } | 4188 } |
4189 } | 4189 } |
4190 | 4190 |
4191 | 4191 |
4192 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { | 4192 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { |
4193 ASSERT(ToRegister(instr->context()).is(rsi)); | 4193 DCHECK(ToRegister(instr->context()).is(rsi)); |
4194 ASSERT(ToRegister(instr->object()).is(StoreIC::ReceiverRegister())); | 4194 DCHECK(ToRegister(instr->object()).is(StoreIC::ReceiverRegister())); |
4195 ASSERT(ToRegister(instr->value()).is(StoreIC::ValueRegister())); | 4195 DCHECK(ToRegister(instr->value()).is(StoreIC::ValueRegister())); |
4196 | 4196 |
4197 __ Move(StoreIC::NameRegister(), instr->hydrogen()->name()); | 4197 __ Move(StoreIC::NameRegister(), instr->hydrogen()->name()); |
4198 Handle<Code> ic = StoreIC::initialize_stub(isolate(), instr->strict_mode()); | 4198 Handle<Code> ic = StoreIC::initialize_stub(isolate(), instr->strict_mode()); |
4199 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 4199 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
4200 } | 4200 } |
4201 | 4201 |
4202 | 4202 |
4203 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { | 4203 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { |
4204 Representation representation = instr->hydrogen()->length()->representation(); | 4204 Representation representation = instr->hydrogen()->length()->representation(); |
4205 ASSERT(representation.Equals(instr->hydrogen()->index()->representation())); | 4205 DCHECK(representation.Equals(instr->hydrogen()->index()->representation())); |
4206 ASSERT(representation.IsSmiOrInteger32()); | 4206 DCHECK(representation.IsSmiOrInteger32()); |
4207 | 4207 |
4208 Condition cc = instr->hydrogen()->allow_equality() ? below : below_equal; | 4208 Condition cc = instr->hydrogen()->allow_equality() ? below : below_equal; |
4209 if (instr->length()->IsConstantOperand()) { | 4209 if (instr->length()->IsConstantOperand()) { |
4210 int32_t length = ToInteger32(LConstantOperand::cast(instr->length())); | 4210 int32_t length = ToInteger32(LConstantOperand::cast(instr->length())); |
4211 Register index = ToRegister(instr->index()); | 4211 Register index = ToRegister(instr->index()); |
4212 if (representation.IsSmi()) { | 4212 if (representation.IsSmi()) { |
4213 __ Cmp(index, Smi::FromInt(length)); | 4213 __ Cmp(index, Smi::FromInt(length)); |
4214 } else { | 4214 } else { |
4215 __ cmpl(index, Immediate(length)); | 4215 __ cmpl(index, Immediate(length)); |
4216 } | 4216 } |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4372 int offset = instr->base_offset(); | 4372 int offset = instr->base_offset(); |
4373 Representation representation = hinstr->value()->representation(); | 4373 Representation representation = hinstr->value()->representation(); |
4374 | 4374 |
4375 if (kPointerSize == kInt32Size && !key->IsConstantOperand() && | 4375 if (kPointerSize == kInt32Size && !key->IsConstantOperand() && |
4376 instr->hydrogen()->IsDehoisted()) { | 4376 instr->hydrogen()->IsDehoisted()) { |
4377 // Sign extend key because it could be a 32 bit negative value | 4377 // Sign extend key because it could be a 32 bit negative value |
4378 // and the dehoisted address computation happens in 64 bits | 4378 // and the dehoisted address computation happens in 64 bits |
4379 __ movsxlq(ToRegister(key), ToRegister(key)); | 4379 __ movsxlq(ToRegister(key), ToRegister(key)); |
4380 } | 4380 } |
4381 if (representation.IsInteger32() && SmiValuesAre32Bits()) { | 4381 if (representation.IsInteger32() && SmiValuesAre32Bits()) { |
4382 ASSERT(hinstr->store_mode() == STORE_TO_INITIALIZED_ENTRY); | 4382 DCHECK(hinstr->store_mode() == STORE_TO_INITIALIZED_ENTRY); |
4383 ASSERT(hinstr->elements_kind() == FAST_SMI_ELEMENTS); | 4383 DCHECK(hinstr->elements_kind() == FAST_SMI_ELEMENTS); |
4384 if (FLAG_debug_code) { | 4384 if (FLAG_debug_code) { |
4385 Register scratch = kScratchRegister; | 4385 Register scratch = kScratchRegister; |
4386 __ Load(scratch, | 4386 __ Load(scratch, |
4387 BuildFastArrayOperand(instr->elements(), | 4387 BuildFastArrayOperand(instr->elements(), |
4388 key, | 4388 key, |
4389 instr->hydrogen()->key()->representation(), | 4389 instr->hydrogen()->key()->representation(), |
4390 FAST_ELEMENTS, | 4390 FAST_ELEMENTS, |
4391 offset), | 4391 offset), |
4392 Representation::Smi()); | 4392 Representation::Smi()); |
4393 __ AssertSmi(scratch); | 4393 __ AssertSmi(scratch); |
4394 } | 4394 } |
4395 // Store int value directly to upper half of the smi. | 4395 // Store int value directly to upper half of the smi. |
4396 STATIC_ASSERT(kSmiTag == 0); | 4396 STATIC_ASSERT(kSmiTag == 0); |
4397 ASSERT(kSmiTagSize + kSmiShiftSize == 32); | 4397 DCHECK(kSmiTagSize + kSmiShiftSize == 32); |
4398 offset += kPointerSize / 2; | 4398 offset += kPointerSize / 2; |
4399 } | 4399 } |
4400 | 4400 |
4401 Operand operand = | 4401 Operand operand = |
4402 BuildFastArrayOperand(instr->elements(), | 4402 BuildFastArrayOperand(instr->elements(), |
4403 key, | 4403 key, |
4404 instr->hydrogen()->key()->representation(), | 4404 instr->hydrogen()->key()->representation(), |
4405 FAST_ELEMENTS, | 4405 FAST_ELEMENTS, |
4406 offset); | 4406 offset); |
4407 if (instr->value()->IsRegister()) { | 4407 if (instr->value()->IsRegister()) { |
4408 __ Store(operand, ToRegister(instr->value()), representation); | 4408 __ Store(operand, ToRegister(instr->value()), representation); |
4409 } else { | 4409 } else { |
4410 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); | 4410 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); |
4411 if (IsInteger32Constant(operand_value)) { | 4411 if (IsInteger32Constant(operand_value)) { |
4412 int32_t value = ToInteger32(operand_value); | 4412 int32_t value = ToInteger32(operand_value); |
4413 if (representation.IsSmi()) { | 4413 if (representation.IsSmi()) { |
4414 __ Move(operand, Smi::FromInt(value)); | 4414 __ Move(operand, Smi::FromInt(value)); |
4415 | 4415 |
4416 } else { | 4416 } else { |
4417 __ movl(operand, Immediate(value)); | 4417 __ movl(operand, Immediate(value)); |
4418 } | 4418 } |
4419 } else { | 4419 } else { |
4420 Handle<Object> handle_value = ToHandle(operand_value); | 4420 Handle<Object> handle_value = ToHandle(operand_value); |
4421 __ Move(operand, handle_value); | 4421 __ Move(operand, handle_value); |
4422 } | 4422 } |
4423 } | 4423 } |
4424 | 4424 |
4425 if (hinstr->NeedsWriteBarrier()) { | 4425 if (hinstr->NeedsWriteBarrier()) { |
4426 Register elements = ToRegister(instr->elements()); | 4426 Register elements = ToRegister(instr->elements()); |
4427 ASSERT(instr->value()->IsRegister()); | 4427 DCHECK(instr->value()->IsRegister()); |
4428 Register value = ToRegister(instr->value()); | 4428 Register value = ToRegister(instr->value()); |
4429 ASSERT(!key->IsConstantOperand()); | 4429 DCHECK(!key->IsConstantOperand()); |
4430 SmiCheck check_needed = hinstr->value()->type().IsHeapObject() | 4430 SmiCheck check_needed = hinstr->value()->type().IsHeapObject() |
4431 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; | 4431 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
4432 // Compute address of modified element and store it into key register. | 4432 // Compute address of modified element and store it into key register. |
4433 Register key_reg(ToRegister(key)); | 4433 Register key_reg(ToRegister(key)); |
4434 __ leap(key_reg, operand); | 4434 __ leap(key_reg, operand); |
4435 __ RecordWrite(elements, | 4435 __ RecordWrite(elements, |
4436 key_reg, | 4436 key_reg, |
4437 value, | 4437 value, |
4438 kSaveFPRegs, | 4438 kSaveFPRegs, |
4439 EMIT_REMEMBERED_SET, | 4439 EMIT_REMEMBERED_SET, |
4440 check_needed, | 4440 check_needed, |
4441 hinstr->PointersToHereCheckForValue()); | 4441 hinstr->PointersToHereCheckForValue()); |
4442 } | 4442 } |
4443 } | 4443 } |
4444 | 4444 |
4445 | 4445 |
4446 void LCodeGen::DoStoreKeyed(LStoreKeyed* instr) { | 4446 void LCodeGen::DoStoreKeyed(LStoreKeyed* instr) { |
4447 if (instr->is_typed_elements()) { | 4447 if (instr->is_typed_elements()) { |
4448 DoStoreKeyedExternalArray(instr); | 4448 DoStoreKeyedExternalArray(instr); |
4449 } else if (instr->hydrogen()->value()->representation().IsDouble()) { | 4449 } else if (instr->hydrogen()->value()->representation().IsDouble()) { |
4450 DoStoreKeyedFixedDoubleArray(instr); | 4450 DoStoreKeyedFixedDoubleArray(instr); |
4451 } else { | 4451 } else { |
4452 DoStoreKeyedFixedArray(instr); | 4452 DoStoreKeyedFixedArray(instr); |
4453 } | 4453 } |
4454 } | 4454 } |
4455 | 4455 |
4456 | 4456 |
4457 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { | 4457 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { |
4458 ASSERT(ToRegister(instr->context()).is(rsi)); | 4458 DCHECK(ToRegister(instr->context()).is(rsi)); |
4459 ASSERT(ToRegister(instr->object()).is(KeyedStoreIC::ReceiverRegister())); | 4459 DCHECK(ToRegister(instr->object()).is(KeyedStoreIC::ReceiverRegister())); |
4460 ASSERT(ToRegister(instr->key()).is(KeyedStoreIC::NameRegister())); | 4460 DCHECK(ToRegister(instr->key()).is(KeyedStoreIC::NameRegister())); |
4461 ASSERT(ToRegister(instr->value()).is(KeyedStoreIC::ValueRegister())); | 4461 DCHECK(ToRegister(instr->value()).is(KeyedStoreIC::ValueRegister())); |
4462 | 4462 |
4463 Handle<Code> ic = instr->strict_mode() == STRICT | 4463 Handle<Code> ic = instr->strict_mode() == STRICT |
4464 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 4464 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() |
4465 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 4465 : isolate()->builtins()->KeyedStoreIC_Initialize(); |
4466 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 4466 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
4467 } | 4467 } |
4468 | 4468 |
4469 | 4469 |
4470 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { | 4470 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { |
4471 Register object_reg = ToRegister(instr->object()); | 4471 Register object_reg = ToRegister(instr->object()); |
4472 | 4472 |
4473 Handle<Map> from_map = instr->original_map(); | 4473 Handle<Map> from_map = instr->original_map(); |
4474 Handle<Map> to_map = instr->transitioned_map(); | 4474 Handle<Map> to_map = instr->transitioned_map(); |
4475 ElementsKind from_kind = instr->from_kind(); | 4475 ElementsKind from_kind = instr->from_kind(); |
4476 ElementsKind to_kind = instr->to_kind(); | 4476 ElementsKind to_kind = instr->to_kind(); |
4477 | 4477 |
4478 Label not_applicable; | 4478 Label not_applicable; |
4479 __ Cmp(FieldOperand(object_reg, HeapObject::kMapOffset), from_map); | 4479 __ Cmp(FieldOperand(object_reg, HeapObject::kMapOffset), from_map); |
4480 __ j(not_equal, ¬_applicable); | 4480 __ j(not_equal, ¬_applicable); |
4481 if (IsSimpleMapChangeTransition(from_kind, to_kind)) { | 4481 if (IsSimpleMapChangeTransition(from_kind, to_kind)) { |
4482 Register new_map_reg = ToRegister(instr->new_map_temp()); | 4482 Register new_map_reg = ToRegister(instr->new_map_temp()); |
4483 __ Move(new_map_reg, to_map, RelocInfo::EMBEDDED_OBJECT); | 4483 __ Move(new_map_reg, to_map, RelocInfo::EMBEDDED_OBJECT); |
4484 __ movp(FieldOperand(object_reg, HeapObject::kMapOffset), new_map_reg); | 4484 __ movp(FieldOperand(object_reg, HeapObject::kMapOffset), new_map_reg); |
4485 // Write barrier. | 4485 // Write barrier. |
4486 __ RecordWriteForMap(object_reg, new_map_reg, ToRegister(instr->temp()), | 4486 __ RecordWriteForMap(object_reg, new_map_reg, ToRegister(instr->temp()), |
4487 kDontSaveFPRegs); | 4487 kDontSaveFPRegs); |
4488 } else { | 4488 } else { |
4489 ASSERT(object_reg.is(rax)); | 4489 DCHECK(object_reg.is(rax)); |
4490 ASSERT(ToRegister(instr->context()).is(rsi)); | 4490 DCHECK(ToRegister(instr->context()).is(rsi)); |
4491 PushSafepointRegistersScope scope(this); | 4491 PushSafepointRegistersScope scope(this); |
4492 __ Move(rbx, to_map); | 4492 __ Move(rbx, to_map); |
4493 bool is_js_array = from_map->instance_type() == JS_ARRAY_TYPE; | 4493 bool is_js_array = from_map->instance_type() == JS_ARRAY_TYPE; |
4494 TransitionElementsKindStub stub(isolate(), from_kind, to_kind, is_js_array); | 4494 TransitionElementsKindStub stub(isolate(), from_kind, to_kind, is_js_array); |
4495 __ CallStub(&stub); | 4495 __ CallStub(&stub); |
4496 RecordSafepointWithLazyDeopt(instr, RECORD_SAFEPOINT_WITH_REGISTERS, 0); | 4496 RecordSafepointWithLazyDeopt(instr, RECORD_SAFEPOINT_WITH_REGISTERS, 0); |
4497 } | 4497 } |
4498 __ bind(¬_applicable); | 4498 __ bind(¬_applicable); |
4499 } | 4499 } |
4500 | 4500 |
4501 | 4501 |
4502 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { | 4502 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { |
4503 Register object = ToRegister(instr->object()); | 4503 Register object = ToRegister(instr->object()); |
4504 Register temp = ToRegister(instr->temp()); | 4504 Register temp = ToRegister(instr->temp()); |
4505 Label no_memento_found; | 4505 Label no_memento_found; |
4506 __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found); | 4506 __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found); |
4507 DeoptimizeIf(equal, instr->environment()); | 4507 DeoptimizeIf(equal, instr->environment()); |
4508 __ bind(&no_memento_found); | 4508 __ bind(&no_memento_found); |
4509 } | 4509 } |
4510 | 4510 |
4511 | 4511 |
4512 void LCodeGen::DoStringAdd(LStringAdd* instr) { | 4512 void LCodeGen::DoStringAdd(LStringAdd* instr) { |
4513 ASSERT(ToRegister(instr->context()).is(rsi)); | 4513 DCHECK(ToRegister(instr->context()).is(rsi)); |
4514 ASSERT(ToRegister(instr->left()).is(rdx)); | 4514 DCHECK(ToRegister(instr->left()).is(rdx)); |
4515 ASSERT(ToRegister(instr->right()).is(rax)); | 4515 DCHECK(ToRegister(instr->right()).is(rax)); |
4516 StringAddStub stub(isolate(), | 4516 StringAddStub stub(isolate(), |
4517 instr->hydrogen()->flags(), | 4517 instr->hydrogen()->flags(), |
4518 instr->hydrogen()->pretenure_flag()); | 4518 instr->hydrogen()->pretenure_flag()); |
4519 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 4519 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
4520 } | 4520 } |
4521 | 4521 |
4522 | 4522 |
4523 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { | 4523 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { |
4524 class DeferredStringCharCodeAt V8_FINAL : public LDeferredCode { | 4524 class DeferredStringCharCodeAt V8_FINAL : public LDeferredCode { |
4525 public: | 4525 public: |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4584 codegen()->DoDeferredStringCharFromCode(instr_); | 4584 codegen()->DoDeferredStringCharFromCode(instr_); |
4585 } | 4585 } |
4586 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } | 4586 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
4587 private: | 4587 private: |
4588 LStringCharFromCode* instr_; | 4588 LStringCharFromCode* instr_; |
4589 }; | 4589 }; |
4590 | 4590 |
4591 DeferredStringCharFromCode* deferred = | 4591 DeferredStringCharFromCode* deferred = |
4592 new(zone()) DeferredStringCharFromCode(this, instr); | 4592 new(zone()) DeferredStringCharFromCode(this, instr); |
4593 | 4593 |
4594 ASSERT(instr->hydrogen()->value()->representation().IsInteger32()); | 4594 DCHECK(instr->hydrogen()->value()->representation().IsInteger32()); |
4595 Register char_code = ToRegister(instr->char_code()); | 4595 Register char_code = ToRegister(instr->char_code()); |
4596 Register result = ToRegister(instr->result()); | 4596 Register result = ToRegister(instr->result()); |
4597 ASSERT(!char_code.is(result)); | 4597 DCHECK(!char_code.is(result)); |
4598 | 4598 |
4599 __ cmpl(char_code, Immediate(String::kMaxOneByteCharCode)); | 4599 __ cmpl(char_code, Immediate(String::kMaxOneByteCharCode)); |
4600 __ j(above, deferred->entry()); | 4600 __ j(above, deferred->entry()); |
4601 __ movsxlq(char_code, char_code); | 4601 __ movsxlq(char_code, char_code); |
4602 __ LoadRoot(result, Heap::kSingleCharacterStringCacheRootIndex); | 4602 __ LoadRoot(result, Heap::kSingleCharacterStringCacheRootIndex); |
4603 __ movp(result, FieldOperand(result, | 4603 __ movp(result, FieldOperand(result, |
4604 char_code, times_pointer_size, | 4604 char_code, times_pointer_size, |
4605 FixedArray::kHeaderSize)); | 4605 FixedArray::kHeaderSize)); |
4606 __ CompareRoot(result, Heap::kUndefinedValueRootIndex); | 4606 __ CompareRoot(result, Heap::kUndefinedValueRootIndex); |
4607 __ j(equal, deferred->entry()); | 4607 __ j(equal, deferred->entry()); |
(...skipping 13 matching lines...) Expand all Loading... |
4621 PushSafepointRegistersScope scope(this); | 4621 PushSafepointRegistersScope scope(this); |
4622 __ Integer32ToSmi(char_code, char_code); | 4622 __ Integer32ToSmi(char_code, char_code); |
4623 __ Push(char_code); | 4623 __ Push(char_code); |
4624 CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr, instr->context()); | 4624 CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr, instr->context()); |
4625 __ StoreToSafepointRegisterSlot(result, rax); | 4625 __ StoreToSafepointRegisterSlot(result, rax); |
4626 } | 4626 } |
4627 | 4627 |
4628 | 4628 |
4629 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { | 4629 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { |
4630 LOperand* input = instr->value(); | 4630 LOperand* input = instr->value(); |
4631 ASSERT(input->IsRegister() || input->IsStackSlot()); | 4631 DCHECK(input->IsRegister() || input->IsStackSlot()); |
4632 LOperand* output = instr->result(); | 4632 LOperand* output = instr->result(); |
4633 ASSERT(output->IsDoubleRegister()); | 4633 DCHECK(output->IsDoubleRegister()); |
4634 if (input->IsRegister()) { | 4634 if (input->IsRegister()) { |
4635 __ Cvtlsi2sd(ToDoubleRegister(output), ToRegister(input)); | 4635 __ Cvtlsi2sd(ToDoubleRegister(output), ToRegister(input)); |
4636 } else { | 4636 } else { |
4637 __ Cvtlsi2sd(ToDoubleRegister(output), ToOperand(input)); | 4637 __ Cvtlsi2sd(ToDoubleRegister(output), ToOperand(input)); |
4638 } | 4638 } |
4639 } | 4639 } |
4640 | 4640 |
4641 | 4641 |
4642 void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) { | 4642 void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) { |
4643 LOperand* input = instr->value(); | 4643 LOperand* input = instr->value(); |
(...skipping 11 matching lines...) Expand all Loading... |
4655 virtual void Generate() V8_OVERRIDE { | 4655 virtual void Generate() V8_OVERRIDE { |
4656 codegen()->DoDeferredNumberTagIU(instr_, instr_->value(), instr_->temp1(), | 4656 codegen()->DoDeferredNumberTagIU(instr_, instr_->value(), instr_->temp1(), |
4657 instr_->temp2(), SIGNED_INT32); | 4657 instr_->temp2(), SIGNED_INT32); |
4658 } | 4658 } |
4659 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } | 4659 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
4660 private: | 4660 private: |
4661 LNumberTagI* instr_; | 4661 LNumberTagI* instr_; |
4662 }; | 4662 }; |
4663 | 4663 |
4664 LOperand* input = instr->value(); | 4664 LOperand* input = instr->value(); |
4665 ASSERT(input->IsRegister() && input->Equals(instr->result())); | 4665 DCHECK(input->IsRegister() && input->Equals(instr->result())); |
4666 Register reg = ToRegister(input); | 4666 Register reg = ToRegister(input); |
4667 | 4667 |
4668 if (SmiValuesAre32Bits()) { | 4668 if (SmiValuesAre32Bits()) { |
4669 __ Integer32ToSmi(reg, reg); | 4669 __ Integer32ToSmi(reg, reg); |
4670 } else { | 4670 } else { |
4671 ASSERT(SmiValuesAre31Bits()); | 4671 DCHECK(SmiValuesAre31Bits()); |
4672 DeferredNumberTagI* deferred = new(zone()) DeferredNumberTagI(this, instr); | 4672 DeferredNumberTagI* deferred = new(zone()) DeferredNumberTagI(this, instr); |
4673 __ Integer32ToSmi(reg, reg); | 4673 __ Integer32ToSmi(reg, reg); |
4674 __ j(overflow, deferred->entry()); | 4674 __ j(overflow, deferred->entry()); |
4675 __ bind(deferred->exit()); | 4675 __ bind(deferred->exit()); |
4676 } | 4676 } |
4677 } | 4677 } |
4678 | 4678 |
4679 | 4679 |
4680 void LCodeGen::DoNumberTagU(LNumberTagU* instr) { | 4680 void LCodeGen::DoNumberTagU(LNumberTagU* instr) { |
4681 class DeferredNumberTagU V8_FINAL : public LDeferredCode { | 4681 class DeferredNumberTagU V8_FINAL : public LDeferredCode { |
4682 public: | 4682 public: |
4683 DeferredNumberTagU(LCodeGen* codegen, LNumberTagU* instr) | 4683 DeferredNumberTagU(LCodeGen* codegen, LNumberTagU* instr) |
4684 : LDeferredCode(codegen), instr_(instr) { } | 4684 : LDeferredCode(codegen), instr_(instr) { } |
4685 virtual void Generate() V8_OVERRIDE { | 4685 virtual void Generate() V8_OVERRIDE { |
4686 codegen()->DoDeferredNumberTagIU(instr_, instr_->value(), instr_->temp1(), | 4686 codegen()->DoDeferredNumberTagIU(instr_, instr_->value(), instr_->temp1(), |
4687 instr_->temp2(), UNSIGNED_INT32); | 4687 instr_->temp2(), UNSIGNED_INT32); |
4688 } | 4688 } |
4689 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } | 4689 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
4690 private: | 4690 private: |
4691 LNumberTagU* instr_; | 4691 LNumberTagU* instr_; |
4692 }; | 4692 }; |
4693 | 4693 |
4694 LOperand* input = instr->value(); | 4694 LOperand* input = instr->value(); |
4695 ASSERT(input->IsRegister() && input->Equals(instr->result())); | 4695 DCHECK(input->IsRegister() && input->Equals(instr->result())); |
4696 Register reg = ToRegister(input); | 4696 Register reg = ToRegister(input); |
4697 | 4697 |
4698 DeferredNumberTagU* deferred = new(zone()) DeferredNumberTagU(this, instr); | 4698 DeferredNumberTagU* deferred = new(zone()) DeferredNumberTagU(this, instr); |
4699 __ cmpl(reg, Immediate(Smi::kMaxValue)); | 4699 __ cmpl(reg, Immediate(Smi::kMaxValue)); |
4700 __ j(above, deferred->entry()); | 4700 __ j(above, deferred->entry()); |
4701 __ Integer32ToSmi(reg, reg); | 4701 __ Integer32ToSmi(reg, reg); |
4702 __ bind(deferred->exit()); | 4702 __ bind(deferred->exit()); |
4703 } | 4703 } |
4704 | 4704 |
4705 | 4705 |
4706 void LCodeGen::DoDeferredNumberTagIU(LInstruction* instr, | 4706 void LCodeGen::DoDeferredNumberTagIU(LInstruction* instr, |
4707 LOperand* value, | 4707 LOperand* value, |
4708 LOperand* temp1, | 4708 LOperand* temp1, |
4709 LOperand* temp2, | 4709 LOperand* temp2, |
4710 IntegerSignedness signedness) { | 4710 IntegerSignedness signedness) { |
4711 Label done, slow; | 4711 Label done, slow; |
4712 Register reg = ToRegister(value); | 4712 Register reg = ToRegister(value); |
4713 Register tmp = ToRegister(temp1); | 4713 Register tmp = ToRegister(temp1); |
4714 XMMRegister temp_xmm = ToDoubleRegister(temp2); | 4714 XMMRegister temp_xmm = ToDoubleRegister(temp2); |
4715 | 4715 |
4716 // Load value into temp_xmm which will be preserved across potential call to | 4716 // Load value into temp_xmm which will be preserved across potential call to |
4717 // runtime (MacroAssembler::EnterExitFrameEpilogue preserves only allocatable | 4717 // runtime (MacroAssembler::EnterExitFrameEpilogue preserves only allocatable |
4718 // XMM registers on x64). | 4718 // XMM registers on x64). |
4719 if (signedness == SIGNED_INT32) { | 4719 if (signedness == SIGNED_INT32) { |
4720 ASSERT(SmiValuesAre31Bits()); | 4720 DCHECK(SmiValuesAre31Bits()); |
4721 // There was overflow, so bits 30 and 31 of the original integer | 4721 // There was overflow, so bits 30 and 31 of the original integer |
4722 // disagree. Try to allocate a heap number in new space and store | 4722 // disagree. Try to allocate a heap number in new space and store |
4723 // the value in there. If that fails, call the runtime system. | 4723 // the value in there. If that fails, call the runtime system. |
4724 __ SmiToInteger32(reg, reg); | 4724 __ SmiToInteger32(reg, reg); |
4725 __ xorl(reg, Immediate(0x80000000)); | 4725 __ xorl(reg, Immediate(0x80000000)); |
4726 __ cvtlsi2sd(temp_xmm, reg); | 4726 __ cvtlsi2sd(temp_xmm, reg); |
4727 } else { | 4727 } else { |
4728 ASSERT(signedness == UNSIGNED_INT32); | 4728 DCHECK(signedness == UNSIGNED_INT32); |
4729 __ LoadUint32(temp_xmm, reg); | 4729 __ LoadUint32(temp_xmm, reg); |
4730 } | 4730 } |
4731 | 4731 |
4732 if (FLAG_inline_new) { | 4732 if (FLAG_inline_new) { |
4733 __ AllocateHeapNumber(reg, tmp, &slow); | 4733 __ AllocateHeapNumber(reg, tmp, &slow); |
4734 __ jmp(&done, kPointerSize == kInt64Size ? Label::kNear : Label::kFar); | 4734 __ jmp(&done, kPointerSize == kInt64Size ? Label::kNear : Label::kFar); |
4735 } | 4735 } |
4736 | 4736 |
4737 // Slow case: Call the runtime system to do the number allocation. | 4737 // Slow case: Call the runtime system to do the number allocation. |
4738 __ bind(&slow); | 4738 __ bind(&slow); |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4827 } | 4827 } |
4828 __ Integer32ToSmi(output, input); | 4828 __ Integer32ToSmi(output, input); |
4829 if (hchange->CheckFlag(HValue::kCanOverflow) && | 4829 if (hchange->CheckFlag(HValue::kCanOverflow) && |
4830 !hchange->value()->CheckFlag(HValue::kUint32)) { | 4830 !hchange->value()->CheckFlag(HValue::kUint32)) { |
4831 DeoptimizeIf(overflow, instr->environment()); | 4831 DeoptimizeIf(overflow, instr->environment()); |
4832 } | 4832 } |
4833 } | 4833 } |
4834 | 4834 |
4835 | 4835 |
4836 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { | 4836 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { |
4837 ASSERT(instr->value()->Equals(instr->result())); | 4837 DCHECK(instr->value()->Equals(instr->result())); |
4838 Register input = ToRegister(instr->value()); | 4838 Register input = ToRegister(instr->value()); |
4839 if (instr->needs_check()) { | 4839 if (instr->needs_check()) { |
4840 Condition is_smi = __ CheckSmi(input); | 4840 Condition is_smi = __ CheckSmi(input); |
4841 DeoptimizeIf(NegateCondition(is_smi), instr->environment()); | 4841 DeoptimizeIf(NegateCondition(is_smi), instr->environment()); |
4842 } else { | 4842 } else { |
4843 __ AssertSmi(input); | 4843 __ AssertSmi(input); |
4844 } | 4844 } |
4845 __ SmiToInteger32(input, input); | 4845 __ SmiToInteger32(input, input); |
4846 } | 4846 } |
4847 | 4847 |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4888 | 4888 |
4889 // Convert undefined (and hole) to NaN. Compute NaN as 0/0. | 4889 // Convert undefined (and hole) to NaN. Compute NaN as 0/0. |
4890 __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex); | 4890 __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex); |
4891 DeoptimizeIf(not_equal, env); | 4891 DeoptimizeIf(not_equal, env); |
4892 | 4892 |
4893 __ xorps(result_reg, result_reg); | 4893 __ xorps(result_reg, result_reg); |
4894 __ divsd(result_reg, result_reg); | 4894 __ divsd(result_reg, result_reg); |
4895 __ jmp(&done, Label::kNear); | 4895 __ jmp(&done, Label::kNear); |
4896 } | 4896 } |
4897 } else { | 4897 } else { |
4898 ASSERT(mode == NUMBER_CANDIDATE_IS_SMI); | 4898 DCHECK(mode == NUMBER_CANDIDATE_IS_SMI); |
4899 } | 4899 } |
4900 | 4900 |
4901 // Smi to XMM conversion | 4901 // Smi to XMM conversion |
4902 __ bind(&load_smi); | 4902 __ bind(&load_smi); |
4903 __ SmiToInteger32(kScratchRegister, input_reg); | 4903 __ SmiToInteger32(kScratchRegister, input_reg); |
4904 __ Cvtlsi2sd(result_reg, kScratchRegister); | 4904 __ Cvtlsi2sd(result_reg, kScratchRegister); |
4905 __ bind(&done); | 4905 __ bind(&done); |
4906 } | 4906 } |
4907 | 4907 |
4908 | 4908 |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4959 : LDeferredCode(codegen), instr_(instr) { } | 4959 : LDeferredCode(codegen), instr_(instr) { } |
4960 virtual void Generate() V8_OVERRIDE { | 4960 virtual void Generate() V8_OVERRIDE { |
4961 codegen()->DoDeferredTaggedToI(instr_, done()); | 4961 codegen()->DoDeferredTaggedToI(instr_, done()); |
4962 } | 4962 } |
4963 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } | 4963 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
4964 private: | 4964 private: |
4965 LTaggedToI* instr_; | 4965 LTaggedToI* instr_; |
4966 }; | 4966 }; |
4967 | 4967 |
4968 LOperand* input = instr->value(); | 4968 LOperand* input = instr->value(); |
4969 ASSERT(input->IsRegister()); | 4969 DCHECK(input->IsRegister()); |
4970 ASSERT(input->Equals(instr->result())); | 4970 DCHECK(input->Equals(instr->result())); |
4971 Register input_reg = ToRegister(input); | 4971 Register input_reg = ToRegister(input); |
4972 | 4972 |
4973 if (instr->hydrogen()->value()->representation().IsSmi()) { | 4973 if (instr->hydrogen()->value()->representation().IsSmi()) { |
4974 __ SmiToInteger32(input_reg, input_reg); | 4974 __ SmiToInteger32(input_reg, input_reg); |
4975 } else { | 4975 } else { |
4976 DeferredTaggedToI* deferred = new(zone()) DeferredTaggedToI(this, instr); | 4976 DeferredTaggedToI* deferred = new(zone()) DeferredTaggedToI(this, instr); |
4977 __ JumpIfNotSmi(input_reg, deferred->entry()); | 4977 __ JumpIfNotSmi(input_reg, deferred->entry()); |
4978 __ SmiToInteger32(input_reg, input_reg); | 4978 __ SmiToInteger32(input_reg, input_reg); |
4979 __ bind(deferred->exit()); | 4979 __ bind(deferred->exit()); |
4980 } | 4980 } |
4981 } | 4981 } |
4982 | 4982 |
4983 | 4983 |
4984 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { | 4984 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { |
4985 LOperand* input = instr->value(); | 4985 LOperand* input = instr->value(); |
4986 ASSERT(input->IsRegister()); | 4986 DCHECK(input->IsRegister()); |
4987 LOperand* result = instr->result(); | 4987 LOperand* result = instr->result(); |
4988 ASSERT(result->IsDoubleRegister()); | 4988 DCHECK(result->IsDoubleRegister()); |
4989 | 4989 |
4990 Register input_reg = ToRegister(input); | 4990 Register input_reg = ToRegister(input); |
4991 XMMRegister result_reg = ToDoubleRegister(result); | 4991 XMMRegister result_reg = ToDoubleRegister(result); |
4992 | 4992 |
4993 HValue* value = instr->hydrogen()->value(); | 4993 HValue* value = instr->hydrogen()->value(); |
4994 NumberUntagDMode mode = value->representation().IsSmi() | 4994 NumberUntagDMode mode = value->representation().IsSmi() |
4995 ? NUMBER_CANDIDATE_IS_SMI : NUMBER_CANDIDATE_IS_ANY_TAGGED; | 4995 ? NUMBER_CANDIDATE_IS_SMI : NUMBER_CANDIDATE_IS_ANY_TAGGED; |
4996 | 4996 |
4997 EmitNumberUntagD(input_reg, result_reg, | 4997 EmitNumberUntagD(input_reg, result_reg, |
4998 instr->hydrogen()->can_convert_undefined_to_nan(), | 4998 instr->hydrogen()->can_convert_undefined_to_nan(), |
4999 instr->hydrogen()->deoptimize_on_minus_zero(), | 4999 instr->hydrogen()->deoptimize_on_minus_zero(), |
5000 instr->environment(), | 5000 instr->environment(), |
5001 mode); | 5001 mode); |
5002 } | 5002 } |
5003 | 5003 |
5004 | 5004 |
5005 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { | 5005 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { |
5006 LOperand* input = instr->value(); | 5006 LOperand* input = instr->value(); |
5007 ASSERT(input->IsDoubleRegister()); | 5007 DCHECK(input->IsDoubleRegister()); |
5008 LOperand* result = instr->result(); | 5008 LOperand* result = instr->result(); |
5009 ASSERT(result->IsRegister()); | 5009 DCHECK(result->IsRegister()); |
5010 | 5010 |
5011 XMMRegister input_reg = ToDoubleRegister(input); | 5011 XMMRegister input_reg = ToDoubleRegister(input); |
5012 Register result_reg = ToRegister(result); | 5012 Register result_reg = ToRegister(result); |
5013 | 5013 |
5014 if (instr->truncating()) { | 5014 if (instr->truncating()) { |
5015 __ TruncateDoubleToI(result_reg, input_reg); | 5015 __ TruncateDoubleToI(result_reg, input_reg); |
5016 } else { | 5016 } else { |
5017 Label bailout, done; | 5017 Label bailout, done; |
5018 XMMRegister xmm_scratch = double_scratch0(); | 5018 XMMRegister xmm_scratch = double_scratch0(); |
5019 __ DoubleToI(result_reg, input_reg, xmm_scratch, | 5019 __ DoubleToI(result_reg, input_reg, xmm_scratch, |
5020 instr->hydrogen()->GetMinusZeroMode(), &bailout, Label::kNear); | 5020 instr->hydrogen()->GetMinusZeroMode(), &bailout, Label::kNear); |
5021 | 5021 |
5022 __ jmp(&done, Label::kNear); | 5022 __ jmp(&done, Label::kNear); |
5023 __ bind(&bailout); | 5023 __ bind(&bailout); |
5024 DeoptimizeIf(no_condition, instr->environment()); | 5024 DeoptimizeIf(no_condition, instr->environment()); |
5025 __ bind(&done); | 5025 __ bind(&done); |
5026 } | 5026 } |
5027 } | 5027 } |
5028 | 5028 |
5029 | 5029 |
5030 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { | 5030 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { |
5031 LOperand* input = instr->value(); | 5031 LOperand* input = instr->value(); |
5032 ASSERT(input->IsDoubleRegister()); | 5032 DCHECK(input->IsDoubleRegister()); |
5033 LOperand* result = instr->result(); | 5033 LOperand* result = instr->result(); |
5034 ASSERT(result->IsRegister()); | 5034 DCHECK(result->IsRegister()); |
5035 | 5035 |
5036 XMMRegister input_reg = ToDoubleRegister(input); | 5036 XMMRegister input_reg = ToDoubleRegister(input); |
5037 Register result_reg = ToRegister(result); | 5037 Register result_reg = ToRegister(result); |
5038 | 5038 |
5039 Label bailout, done; | 5039 Label bailout, done; |
5040 XMMRegister xmm_scratch = double_scratch0(); | 5040 XMMRegister xmm_scratch = double_scratch0(); |
5041 __ DoubleToI(result_reg, input_reg, xmm_scratch, | 5041 __ DoubleToI(result_reg, input_reg, xmm_scratch, |
5042 instr->hydrogen()->GetMinusZeroMode(), &bailout, Label::kNear); | 5042 instr->hydrogen()->GetMinusZeroMode(), &bailout, Label::kNear); |
5043 | 5043 |
5044 __ jmp(&done, Label::kNear); | 5044 __ jmp(&done, Label::kNear); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5091 Immediate(static_cast<int8_t>(last))); | 5091 Immediate(static_cast<int8_t>(last))); |
5092 DeoptimizeIf(above, instr->environment()); | 5092 DeoptimizeIf(above, instr->environment()); |
5093 } | 5093 } |
5094 } | 5094 } |
5095 } else { | 5095 } else { |
5096 uint8_t mask; | 5096 uint8_t mask; |
5097 uint8_t tag; | 5097 uint8_t tag; |
5098 instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag); | 5098 instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag); |
5099 | 5099 |
5100 if (IsPowerOf2(mask)) { | 5100 if (IsPowerOf2(mask)) { |
5101 ASSERT(tag == 0 || IsPowerOf2(tag)); | 5101 DCHECK(tag == 0 || IsPowerOf2(tag)); |
5102 __ testb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset), | 5102 __ testb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset), |
5103 Immediate(mask)); | 5103 Immediate(mask)); |
5104 DeoptimizeIf(tag == 0 ? not_zero : zero, instr->environment()); | 5104 DeoptimizeIf(tag == 0 ? not_zero : zero, instr->environment()); |
5105 } else { | 5105 } else { |
5106 __ movzxbl(kScratchRegister, | 5106 __ movzxbl(kScratchRegister, |
5107 FieldOperand(kScratchRegister, Map::kInstanceTypeOffset)); | 5107 FieldOperand(kScratchRegister, Map::kInstanceTypeOffset)); |
5108 __ andb(kScratchRegister, Immediate(mask)); | 5108 __ andb(kScratchRegister, Immediate(mask)); |
5109 __ cmpb(kScratchRegister, Immediate(tag)); | 5109 __ cmpb(kScratchRegister, Immediate(tag)); |
5110 DeoptimizeIf(not_equal, instr->environment()); | 5110 DeoptimizeIf(not_equal, instr->environment()); |
5111 } | 5111 } |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5155 | 5155 |
5156 if (instr->hydrogen()->IsStabilityCheck()) { | 5156 if (instr->hydrogen()->IsStabilityCheck()) { |
5157 const UniqueSet<Map>* maps = instr->hydrogen()->maps(); | 5157 const UniqueSet<Map>* maps = instr->hydrogen()->maps(); |
5158 for (int i = 0; i < maps->size(); ++i) { | 5158 for (int i = 0; i < maps->size(); ++i) { |
5159 AddStabilityDependency(maps->at(i).handle()); | 5159 AddStabilityDependency(maps->at(i).handle()); |
5160 } | 5160 } |
5161 return; | 5161 return; |
5162 } | 5162 } |
5163 | 5163 |
5164 LOperand* input = instr->value(); | 5164 LOperand* input = instr->value(); |
5165 ASSERT(input->IsRegister()); | 5165 DCHECK(input->IsRegister()); |
5166 Register reg = ToRegister(input); | 5166 Register reg = ToRegister(input); |
5167 | 5167 |
5168 DeferredCheckMaps* deferred = NULL; | 5168 DeferredCheckMaps* deferred = NULL; |
5169 if (instr->hydrogen()->HasMigrationTarget()) { | 5169 if (instr->hydrogen()->HasMigrationTarget()) { |
5170 deferred = new(zone()) DeferredCheckMaps(this, instr, reg); | 5170 deferred = new(zone()) DeferredCheckMaps(this, instr, reg); |
5171 __ bind(deferred->check_maps()); | 5171 __ bind(deferred->check_maps()); |
5172 } | 5172 } |
5173 | 5173 |
5174 const UniqueSet<Map>* maps = instr->hydrogen()->maps(); | 5174 const UniqueSet<Map>* maps = instr->hydrogen()->maps(); |
5175 Label success; | 5175 Label success; |
(...skipping 17 matching lines...) Expand all Loading... |
5193 | 5193 |
5194 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { | 5194 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { |
5195 XMMRegister value_reg = ToDoubleRegister(instr->unclamped()); | 5195 XMMRegister value_reg = ToDoubleRegister(instr->unclamped()); |
5196 XMMRegister xmm_scratch = double_scratch0(); | 5196 XMMRegister xmm_scratch = double_scratch0(); |
5197 Register result_reg = ToRegister(instr->result()); | 5197 Register result_reg = ToRegister(instr->result()); |
5198 __ ClampDoubleToUint8(value_reg, xmm_scratch, result_reg); | 5198 __ ClampDoubleToUint8(value_reg, xmm_scratch, result_reg); |
5199 } | 5199 } |
5200 | 5200 |
5201 | 5201 |
5202 void LCodeGen::DoClampIToUint8(LClampIToUint8* instr) { | 5202 void LCodeGen::DoClampIToUint8(LClampIToUint8* instr) { |
5203 ASSERT(instr->unclamped()->Equals(instr->result())); | 5203 DCHECK(instr->unclamped()->Equals(instr->result())); |
5204 Register value_reg = ToRegister(instr->result()); | 5204 Register value_reg = ToRegister(instr->result()); |
5205 __ ClampUint8(value_reg); | 5205 __ ClampUint8(value_reg); |
5206 } | 5206 } |
5207 | 5207 |
5208 | 5208 |
5209 void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) { | 5209 void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) { |
5210 ASSERT(instr->unclamped()->Equals(instr->result())); | 5210 DCHECK(instr->unclamped()->Equals(instr->result())); |
5211 Register input_reg = ToRegister(instr->unclamped()); | 5211 Register input_reg = ToRegister(instr->unclamped()); |
5212 XMMRegister temp_xmm_reg = ToDoubleRegister(instr->temp_xmm()); | 5212 XMMRegister temp_xmm_reg = ToDoubleRegister(instr->temp_xmm()); |
5213 XMMRegister xmm_scratch = double_scratch0(); | 5213 XMMRegister xmm_scratch = double_scratch0(); |
5214 Label is_smi, done, heap_number; | 5214 Label is_smi, done, heap_number; |
5215 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear; | 5215 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear; |
5216 __ JumpIfSmi(input_reg, &is_smi, dist); | 5216 __ JumpIfSmi(input_reg, &is_smi, dist); |
5217 | 5217 |
5218 // Check for heap number | 5218 // Check for heap number |
5219 __ Cmp(FieldOperand(input_reg, HeapObject::kMapOffset), | 5219 __ Cmp(FieldOperand(input_reg, HeapObject::kMapOffset), |
5220 factory()->heap_number_map()); | 5220 factory()->heap_number_map()); |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5284 | 5284 |
5285 Register result = ToRegister(instr->result()); | 5285 Register result = ToRegister(instr->result()); |
5286 Register temp = ToRegister(instr->temp()); | 5286 Register temp = ToRegister(instr->temp()); |
5287 | 5287 |
5288 // Allocate memory for the object. | 5288 // Allocate memory for the object. |
5289 AllocationFlags flags = TAG_OBJECT; | 5289 AllocationFlags flags = TAG_OBJECT; |
5290 if (instr->hydrogen()->MustAllocateDoubleAligned()) { | 5290 if (instr->hydrogen()->MustAllocateDoubleAligned()) { |
5291 flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT); | 5291 flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT); |
5292 } | 5292 } |
5293 if (instr->hydrogen()->IsOldPointerSpaceAllocation()) { | 5293 if (instr->hydrogen()->IsOldPointerSpaceAllocation()) { |
5294 ASSERT(!instr->hydrogen()->IsOldDataSpaceAllocation()); | 5294 DCHECK(!instr->hydrogen()->IsOldDataSpaceAllocation()); |
5295 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); | 5295 DCHECK(!instr->hydrogen()->IsNewSpaceAllocation()); |
5296 flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_POINTER_SPACE); | 5296 flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_POINTER_SPACE); |
5297 } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) { | 5297 } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) { |
5298 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); | 5298 DCHECK(!instr->hydrogen()->IsNewSpaceAllocation()); |
5299 flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_DATA_SPACE); | 5299 flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_DATA_SPACE); |
5300 } | 5300 } |
5301 | 5301 |
5302 if (instr->size()->IsConstantOperand()) { | 5302 if (instr->size()->IsConstantOperand()) { |
5303 int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); | 5303 int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); |
5304 if (size <= Page::kMaxRegularHeapObjectSize) { | 5304 if (size <= Page::kMaxRegularHeapObjectSize) { |
5305 __ Allocate(size, result, temp, no_reg, deferred->entry(), flags); | 5305 __ Allocate(size, result, temp, no_reg, deferred->entry(), flags); |
5306 } else { | 5306 } else { |
5307 __ jmp(deferred->entry()); | 5307 __ jmp(deferred->entry()); |
5308 } | 5308 } |
(...skipping 27 matching lines...) Expand all Loading... |
5336 Register result = ToRegister(instr->result()); | 5336 Register result = ToRegister(instr->result()); |
5337 | 5337 |
5338 // TODO(3095996): Get rid of this. For now, we need to make the | 5338 // TODO(3095996): Get rid of this. For now, we need to make the |
5339 // result register contain a valid pointer because it is already | 5339 // result register contain a valid pointer because it is already |
5340 // contained in the register pointer map. | 5340 // contained in the register pointer map. |
5341 __ Move(result, Smi::FromInt(0)); | 5341 __ Move(result, Smi::FromInt(0)); |
5342 | 5342 |
5343 PushSafepointRegistersScope scope(this); | 5343 PushSafepointRegistersScope scope(this); |
5344 if (instr->size()->IsRegister()) { | 5344 if (instr->size()->IsRegister()) { |
5345 Register size = ToRegister(instr->size()); | 5345 Register size = ToRegister(instr->size()); |
5346 ASSERT(!size.is(result)); | 5346 DCHECK(!size.is(result)); |
5347 __ Integer32ToSmi(size, size); | 5347 __ Integer32ToSmi(size, size); |
5348 __ Push(size); | 5348 __ Push(size); |
5349 } else { | 5349 } else { |
5350 int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); | 5350 int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); |
5351 __ Push(Smi::FromInt(size)); | 5351 __ Push(Smi::FromInt(size)); |
5352 } | 5352 } |
5353 | 5353 |
5354 int flags = 0; | 5354 int flags = 0; |
5355 if (instr->hydrogen()->IsOldPointerSpaceAllocation()) { | 5355 if (instr->hydrogen()->IsOldPointerSpaceAllocation()) { |
5356 ASSERT(!instr->hydrogen()->IsOldDataSpaceAllocation()); | 5356 DCHECK(!instr->hydrogen()->IsOldDataSpaceAllocation()); |
5357 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); | 5357 DCHECK(!instr->hydrogen()->IsNewSpaceAllocation()); |
5358 flags = AllocateTargetSpace::update(flags, OLD_POINTER_SPACE); | 5358 flags = AllocateTargetSpace::update(flags, OLD_POINTER_SPACE); |
5359 } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) { | 5359 } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) { |
5360 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); | 5360 DCHECK(!instr->hydrogen()->IsNewSpaceAllocation()); |
5361 flags = AllocateTargetSpace::update(flags, OLD_DATA_SPACE); | 5361 flags = AllocateTargetSpace::update(flags, OLD_DATA_SPACE); |
5362 } else { | 5362 } else { |
5363 flags = AllocateTargetSpace::update(flags, NEW_SPACE); | 5363 flags = AllocateTargetSpace::update(flags, NEW_SPACE); |
5364 } | 5364 } |
5365 __ Push(Smi::FromInt(flags)); | 5365 __ Push(Smi::FromInt(flags)); |
5366 | 5366 |
5367 CallRuntimeFromDeferred( | 5367 CallRuntimeFromDeferred( |
5368 Runtime::kAllocateInTargetSpace, 2, instr, instr->context()); | 5368 Runtime::kAllocateInTargetSpace, 2, instr, instr->context()); |
5369 __ StoreToSafepointRegisterSlot(result, rax); | 5369 __ StoreToSafepointRegisterSlot(result, rax); |
5370 } | 5370 } |
5371 | 5371 |
5372 | 5372 |
5373 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { | 5373 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { |
5374 ASSERT(ToRegister(instr->value()).is(rax)); | 5374 DCHECK(ToRegister(instr->value()).is(rax)); |
5375 __ Push(rax); | 5375 __ Push(rax); |
5376 CallRuntime(Runtime::kToFastProperties, 1, instr); | 5376 CallRuntime(Runtime::kToFastProperties, 1, instr); |
5377 } | 5377 } |
5378 | 5378 |
5379 | 5379 |
5380 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { | 5380 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { |
5381 ASSERT(ToRegister(instr->context()).is(rsi)); | 5381 DCHECK(ToRegister(instr->context()).is(rsi)); |
5382 Label materialized; | 5382 Label materialized; |
5383 // Registers will be used as follows: | 5383 // Registers will be used as follows: |
5384 // rcx = literals array. | 5384 // rcx = literals array. |
5385 // rbx = regexp literal. | 5385 // rbx = regexp literal. |
5386 // rax = regexp literal clone. | 5386 // rax = regexp literal clone. |
5387 int literal_offset = | 5387 int literal_offset = |
5388 FixedArray::OffsetOfElementAt(instr->hydrogen()->literal_index()); | 5388 FixedArray::OffsetOfElementAt(instr->hydrogen()->literal_index()); |
5389 __ Move(rcx, instr->hydrogen()->literals()); | 5389 __ Move(rcx, instr->hydrogen()->literals()); |
5390 __ movp(rbx, FieldOperand(rcx, literal_offset)); | 5390 __ movp(rbx, FieldOperand(rcx, literal_offset)); |
5391 __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex); | 5391 __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex); |
(...skipping 30 matching lines...) Expand all Loading... |
5422 __ movp(FieldOperand(rax, i + kPointerSize), rcx); | 5422 __ movp(FieldOperand(rax, i + kPointerSize), rcx); |
5423 } | 5423 } |
5424 if ((size % (2 * kPointerSize)) != 0) { | 5424 if ((size % (2 * kPointerSize)) != 0) { |
5425 __ movp(rdx, FieldOperand(rbx, size - kPointerSize)); | 5425 __ movp(rdx, FieldOperand(rbx, size - kPointerSize)); |
5426 __ movp(FieldOperand(rax, size - kPointerSize), rdx); | 5426 __ movp(FieldOperand(rax, size - kPointerSize), rdx); |
5427 } | 5427 } |
5428 } | 5428 } |
5429 | 5429 |
5430 | 5430 |
5431 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) { | 5431 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) { |
5432 ASSERT(ToRegister(instr->context()).is(rsi)); | 5432 DCHECK(ToRegister(instr->context()).is(rsi)); |
5433 // Use the fast case closure allocation code that allocates in new | 5433 // Use the fast case closure allocation code that allocates in new |
5434 // space for nested functions that don't need literals cloning. | 5434 // space for nested functions that don't need literals cloning. |
5435 bool pretenure = instr->hydrogen()->pretenure(); | 5435 bool pretenure = instr->hydrogen()->pretenure(); |
5436 if (!pretenure && instr->hydrogen()->has_no_literals()) { | 5436 if (!pretenure && instr->hydrogen()->has_no_literals()) { |
5437 FastNewClosureStub stub(isolate(), | 5437 FastNewClosureStub stub(isolate(), |
5438 instr->hydrogen()->strict_mode(), | 5438 instr->hydrogen()->strict_mode(), |
5439 instr->hydrogen()->is_generator()); | 5439 instr->hydrogen()->is_generator()); |
5440 __ Move(rbx, instr->hydrogen()->shared_info()); | 5440 __ Move(rbx, instr->hydrogen()->shared_info()); |
5441 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 5441 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
5442 } else { | 5442 } else { |
5443 __ Push(rsi); | 5443 __ Push(rsi); |
5444 __ Push(instr->hydrogen()->shared_info()); | 5444 __ Push(instr->hydrogen()->shared_info()); |
5445 __ PushRoot(pretenure ? Heap::kTrueValueRootIndex : | 5445 __ PushRoot(pretenure ? Heap::kTrueValueRootIndex : |
5446 Heap::kFalseValueRootIndex); | 5446 Heap::kFalseValueRootIndex); |
5447 CallRuntime(Runtime::kNewClosure, 3, instr); | 5447 CallRuntime(Runtime::kNewClosure, 3, instr); |
5448 } | 5448 } |
5449 } | 5449 } |
5450 | 5450 |
5451 | 5451 |
5452 void LCodeGen::DoTypeof(LTypeof* instr) { | 5452 void LCodeGen::DoTypeof(LTypeof* instr) { |
5453 ASSERT(ToRegister(instr->context()).is(rsi)); | 5453 DCHECK(ToRegister(instr->context()).is(rsi)); |
5454 LOperand* input = instr->value(); | 5454 LOperand* input = instr->value(); |
5455 EmitPushTaggedOperand(input); | 5455 EmitPushTaggedOperand(input); |
5456 CallRuntime(Runtime::kTypeof, 1, instr); | 5456 CallRuntime(Runtime::kTypeof, 1, instr); |
5457 } | 5457 } |
5458 | 5458 |
5459 | 5459 |
5460 void LCodeGen::EmitPushTaggedOperand(LOperand* operand) { | 5460 void LCodeGen::EmitPushTaggedOperand(LOperand* operand) { |
5461 ASSERT(!operand->IsDoubleRegister()); | 5461 DCHECK(!operand->IsDoubleRegister()); |
5462 if (operand->IsConstantOperand()) { | 5462 if (operand->IsConstantOperand()) { |
5463 __ Push(ToHandle(LConstantOperand::cast(operand))); | 5463 __ Push(ToHandle(LConstantOperand::cast(operand))); |
5464 } else if (operand->IsRegister()) { | 5464 } else if (operand->IsRegister()) { |
5465 __ Push(ToRegister(operand)); | 5465 __ Push(ToRegister(operand)); |
5466 } else { | 5466 } else { |
5467 __ Push(ToOperand(operand)); | 5467 __ Push(ToOperand(operand)); |
5468 } | 5468 } |
5469 } | 5469 } |
5470 | 5470 |
5471 | 5471 |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5592 int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; | 5592 int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; |
5593 __ Nop(padding_size); | 5593 __ Nop(padding_size); |
5594 } | 5594 } |
5595 } | 5595 } |
5596 last_lazy_deopt_pc_ = masm()->pc_offset(); | 5596 last_lazy_deopt_pc_ = masm()->pc_offset(); |
5597 } | 5597 } |
5598 | 5598 |
5599 | 5599 |
5600 void LCodeGen::DoLazyBailout(LLazyBailout* instr) { | 5600 void LCodeGen::DoLazyBailout(LLazyBailout* instr) { |
5601 last_lazy_deopt_pc_ = masm()->pc_offset(); | 5601 last_lazy_deopt_pc_ = masm()->pc_offset(); |
5602 ASSERT(instr->HasEnvironment()); | 5602 DCHECK(instr->HasEnvironment()); |
5603 LEnvironment* env = instr->environment(); | 5603 LEnvironment* env = instr->environment(); |
5604 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); | 5604 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); |
5605 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); | 5605 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); |
5606 } | 5606 } |
5607 | 5607 |
5608 | 5608 |
5609 void LCodeGen::DoDeoptimize(LDeoptimize* instr) { | 5609 void LCodeGen::DoDeoptimize(LDeoptimize* instr) { |
5610 Deoptimizer::BailoutType type = instr->hydrogen()->type(); | 5610 Deoptimizer::BailoutType type = instr->hydrogen()->type(); |
5611 // TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the | 5611 // TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the |
5612 // needed return address), even though the implementation of LAZY and EAGER is | 5612 // needed return address), even though the implementation of LAZY and EAGER is |
(...skipping 16 matching lines...) Expand all Loading... |
5629 void LCodeGen::DoDummyUse(LDummyUse* instr) { | 5629 void LCodeGen::DoDummyUse(LDummyUse* instr) { |
5630 // Nothing to see here, move on! | 5630 // Nothing to see here, move on! |
5631 } | 5631 } |
5632 | 5632 |
5633 | 5633 |
5634 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) { | 5634 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) { |
5635 PushSafepointRegistersScope scope(this); | 5635 PushSafepointRegistersScope scope(this); |
5636 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 5636 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
5637 __ CallRuntimeSaveDoubles(Runtime::kStackGuard); | 5637 __ CallRuntimeSaveDoubles(Runtime::kStackGuard); |
5638 RecordSafepointWithLazyDeopt(instr, RECORD_SAFEPOINT_WITH_REGISTERS, 0); | 5638 RecordSafepointWithLazyDeopt(instr, RECORD_SAFEPOINT_WITH_REGISTERS, 0); |
5639 ASSERT(instr->HasEnvironment()); | 5639 DCHECK(instr->HasEnvironment()); |
5640 LEnvironment* env = instr->environment(); | 5640 LEnvironment* env = instr->environment(); |
5641 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); | 5641 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); |
5642 } | 5642 } |
5643 | 5643 |
5644 | 5644 |
5645 void LCodeGen::DoStackCheck(LStackCheck* instr) { | 5645 void LCodeGen::DoStackCheck(LStackCheck* instr) { |
5646 class DeferredStackCheck V8_FINAL : public LDeferredCode { | 5646 class DeferredStackCheck V8_FINAL : public LDeferredCode { |
5647 public: | 5647 public: |
5648 DeferredStackCheck(LCodeGen* codegen, LStackCheck* instr) | 5648 DeferredStackCheck(LCodeGen* codegen, LStackCheck* instr) |
5649 : LDeferredCode(codegen), instr_(instr) { } | 5649 : LDeferredCode(codegen), instr_(instr) { } |
5650 virtual void Generate() V8_OVERRIDE { | 5650 virtual void Generate() V8_OVERRIDE { |
5651 codegen()->DoDeferredStackCheck(instr_); | 5651 codegen()->DoDeferredStackCheck(instr_); |
5652 } | 5652 } |
5653 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } | 5653 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
5654 private: | 5654 private: |
5655 LStackCheck* instr_; | 5655 LStackCheck* instr_; |
5656 }; | 5656 }; |
5657 | 5657 |
5658 ASSERT(instr->HasEnvironment()); | 5658 DCHECK(instr->HasEnvironment()); |
5659 LEnvironment* env = instr->environment(); | 5659 LEnvironment* env = instr->environment(); |
5660 // There is no LLazyBailout instruction for stack-checks. We have to | 5660 // There is no LLazyBailout instruction for stack-checks. We have to |
5661 // prepare for lazy deoptimization explicitly here. | 5661 // prepare for lazy deoptimization explicitly here. |
5662 if (instr->hydrogen()->is_function_entry()) { | 5662 if (instr->hydrogen()->is_function_entry()) { |
5663 // Perform stack overflow check. | 5663 // Perform stack overflow check. |
5664 Label done; | 5664 Label done; |
5665 __ CompareRoot(rsp, Heap::kStackLimitRootIndex); | 5665 __ CompareRoot(rsp, Heap::kStackLimitRootIndex); |
5666 __ j(above_equal, &done, Label::kNear); | 5666 __ j(above_equal, &done, Label::kNear); |
5667 | 5667 |
5668 ASSERT(instr->context()->IsRegister()); | 5668 DCHECK(instr->context()->IsRegister()); |
5669 ASSERT(ToRegister(instr->context()).is(rsi)); | 5669 DCHECK(ToRegister(instr->context()).is(rsi)); |
5670 CallCode(isolate()->builtins()->StackCheck(), | 5670 CallCode(isolate()->builtins()->StackCheck(), |
5671 RelocInfo::CODE_TARGET, | 5671 RelocInfo::CODE_TARGET, |
5672 instr); | 5672 instr); |
5673 __ bind(&done); | 5673 __ bind(&done); |
5674 } else { | 5674 } else { |
5675 ASSERT(instr->hydrogen()->is_backwards_branch()); | 5675 DCHECK(instr->hydrogen()->is_backwards_branch()); |
5676 // Perform stack overflow check if this goto needs it before jumping. | 5676 // Perform stack overflow check if this goto needs it before jumping. |
5677 DeferredStackCheck* deferred_stack_check = | 5677 DeferredStackCheck* deferred_stack_check = |
5678 new(zone()) DeferredStackCheck(this, instr); | 5678 new(zone()) DeferredStackCheck(this, instr); |
5679 __ CompareRoot(rsp, Heap::kStackLimitRootIndex); | 5679 __ CompareRoot(rsp, Heap::kStackLimitRootIndex); |
5680 __ j(below, deferred_stack_check->entry()); | 5680 __ j(below, deferred_stack_check->entry()); |
5681 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); | 5681 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); |
5682 __ bind(instr->done_label()); | 5682 __ bind(instr->done_label()); |
5683 deferred_stack_check->SetExit(instr->done_label()); | 5683 deferred_stack_check->SetExit(instr->done_label()); |
5684 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); | 5684 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); |
5685 // Don't record a deoptimization index for the safepoint here. | 5685 // Don't record a deoptimization index for the safepoint here. |
5686 // This will be done explicitly when emitting call and the safepoint in | 5686 // This will be done explicitly when emitting call and the safepoint in |
5687 // the deferred code. | 5687 // the deferred code. |
5688 } | 5688 } |
5689 } | 5689 } |
5690 | 5690 |
5691 | 5691 |
5692 void LCodeGen::DoOsrEntry(LOsrEntry* instr) { | 5692 void LCodeGen::DoOsrEntry(LOsrEntry* instr) { |
5693 // This is a pseudo-instruction that ensures that the environment here is | 5693 // This is a pseudo-instruction that ensures that the environment here is |
5694 // properly registered for deoptimization and records the assembler's PC | 5694 // properly registered for deoptimization and records the assembler's PC |
5695 // offset. | 5695 // offset. |
5696 LEnvironment* environment = instr->environment(); | 5696 LEnvironment* environment = instr->environment(); |
5697 | 5697 |
5698 // If the environment were already registered, we would have no way of | 5698 // If the environment were already registered, we would have no way of |
5699 // backpatching it with the spill slot operands. | 5699 // backpatching it with the spill slot operands. |
5700 ASSERT(!environment->HasBeenRegistered()); | 5700 DCHECK(!environment->HasBeenRegistered()); |
5701 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); | 5701 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); |
5702 | 5702 |
5703 GenerateOsrPrologue(); | 5703 GenerateOsrPrologue(); |
5704 } | 5704 } |
5705 | 5705 |
5706 | 5706 |
5707 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { | 5707 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { |
5708 ASSERT(ToRegister(instr->context()).is(rsi)); | 5708 DCHECK(ToRegister(instr->context()).is(rsi)); |
5709 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); | 5709 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); |
5710 DeoptimizeIf(equal, instr->environment()); | 5710 DeoptimizeIf(equal, instr->environment()); |
5711 | 5711 |
5712 Register null_value = rdi; | 5712 Register null_value = rdi; |
5713 __ LoadRoot(null_value, Heap::kNullValueRootIndex); | 5713 __ LoadRoot(null_value, Heap::kNullValueRootIndex); |
5714 __ cmpp(rax, null_value); | 5714 __ cmpp(rax, null_value); |
5715 DeoptimizeIf(equal, instr->environment()); | 5715 DeoptimizeIf(equal, instr->environment()); |
5716 | 5716 |
5717 Condition cc = masm()->CheckSmi(rax); | 5717 Condition cc = masm()->CheckSmi(rax); |
5718 DeoptimizeIf(cc, instr->environment()); | 5718 DeoptimizeIf(cc, instr->environment()); |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5852 CallRuntime(Runtime::kPushBlockContext, 2, instr); | 5852 CallRuntime(Runtime::kPushBlockContext, 2, instr); |
5853 RecordSafepoint(Safepoint::kNoLazyDeopt); | 5853 RecordSafepoint(Safepoint::kNoLazyDeopt); |
5854 } | 5854 } |
5855 | 5855 |
5856 | 5856 |
5857 #undef __ | 5857 #undef __ |
5858 | 5858 |
5859 } } // namespace v8::internal | 5859 } } // namespace v8::internal |
5860 | 5860 |
5861 #endif // V8_TARGET_ARCH_X64 | 5861 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |