OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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_MIPS64 | 7 #if V8_TARGET_ARCH_MIPS64 |
8 | 8 |
9 // Note on Mips implementation: | 9 // Note on Mips implementation: |
10 // | 10 // |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
43 // never be emitted by normal code. | 43 // never be emitted by normal code. |
44 class JumpPatchSite BASE_EMBEDDED { | 44 class JumpPatchSite BASE_EMBEDDED { |
45 public: | 45 public: |
46 explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm) { | 46 explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm) { |
47 #ifdef DEBUG | 47 #ifdef DEBUG |
48 info_emitted_ = false; | 48 info_emitted_ = false; |
49 #endif | 49 #endif |
50 } | 50 } |
51 | 51 |
52 ~JumpPatchSite() { | 52 ~JumpPatchSite() { |
53 ASSERT(patch_site_.is_bound() == info_emitted_); | 53 DCHECK(patch_site_.is_bound() == info_emitted_); |
54 } | 54 } |
55 | 55 |
56 // When initially emitting this ensure that a jump is always generated to skip | 56 // When initially emitting this ensure that a jump is always generated to skip |
57 // the inlined smi code. | 57 // the inlined smi code. |
58 void EmitJumpIfNotSmi(Register reg, Label* target) { | 58 void EmitJumpIfNotSmi(Register reg, Label* target) { |
59 ASSERT(!patch_site_.is_bound() && !info_emitted_); | 59 DCHECK(!patch_site_.is_bound() && !info_emitted_); |
60 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_); | 60 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_); |
61 __ bind(&patch_site_); | 61 __ bind(&patch_site_); |
62 __ andi(at, reg, 0); | 62 __ andi(at, reg, 0); |
63 // Always taken before patched. | 63 // Always taken before patched. |
64 __ BranchShort(target, eq, at, Operand(zero_reg)); | 64 __ BranchShort(target, eq, at, Operand(zero_reg)); |
65 } | 65 } |
66 | 66 |
67 // When initially emitting this ensure that a jump is never generated to skip | 67 // When initially emitting this ensure that a jump is never generated to skip |
68 // the inlined smi code. | 68 // the inlined smi code. |
69 void EmitJumpIfSmi(Register reg, Label* target) { | 69 void EmitJumpIfSmi(Register reg, Label* target) { |
70 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_); | 70 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_); |
71 ASSERT(!patch_site_.is_bound() && !info_emitted_); | 71 DCHECK(!patch_site_.is_bound() && !info_emitted_); |
72 __ bind(&patch_site_); | 72 __ bind(&patch_site_); |
73 __ andi(at, reg, 0); | 73 __ andi(at, reg, 0); |
74 // Never taken before patched. | 74 // Never taken before patched. |
75 __ BranchShort(target, ne, at, Operand(zero_reg)); | 75 __ BranchShort(target, ne, at, Operand(zero_reg)); |
76 } | 76 } |
77 | 77 |
78 void EmitPatchInfo() { | 78 void EmitPatchInfo() { |
79 if (patch_site_.is_bound()) { | 79 if (patch_site_.is_bound()) { |
80 int delta_to_patch_site = masm_->InstructionsGeneratedSince(&patch_site_); | 80 int delta_to_patch_site = masm_->InstructionsGeneratedSince(&patch_site_); |
81 Register reg = Register::from_code(delta_to_patch_site / kImm16Mask); | 81 Register reg = Register::from_code(delta_to_patch_site / kImm16Mask); |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
150 // MANUAL indicates that the scope shouldn't actually generate code to set up | 150 // MANUAL indicates that the scope shouldn't actually generate code to set up |
151 // the frame (that is done below). | 151 // the frame (that is done below). |
152 FrameScope frame_scope(masm_, StackFrame::MANUAL); | 152 FrameScope frame_scope(masm_, StackFrame::MANUAL); |
153 info->set_prologue_offset(masm_->pc_offset()); | 153 info->set_prologue_offset(masm_->pc_offset()); |
154 __ Prologue(info->IsCodePreAgingActive()); | 154 __ Prologue(info->IsCodePreAgingActive()); |
155 info->AddNoFrameRange(0, masm_->pc_offset()); | 155 info->AddNoFrameRange(0, masm_->pc_offset()); |
156 | 156 |
157 { Comment cmnt(masm_, "[ Allocate locals"); | 157 { Comment cmnt(masm_, "[ Allocate locals"); |
158 int locals_count = info->scope()->num_stack_slots(); | 158 int locals_count = info->scope()->num_stack_slots(); |
159 // Generators allocate locals, if any, in context slots. | 159 // Generators allocate locals, if any, in context slots. |
160 ASSERT(!info->function()->is_generator() || locals_count == 0); | 160 DCHECK(!info->function()->is_generator() || locals_count == 0); |
161 if (locals_count > 0) { | 161 if (locals_count > 0) { |
162 if (locals_count >= 128) { | 162 if (locals_count >= 128) { |
163 Label ok; | 163 Label ok; |
164 __ Dsubu(t1, sp, Operand(locals_count * kPointerSize)); | 164 __ Dsubu(t1, sp, Operand(locals_count * kPointerSize)); |
165 __ LoadRoot(a2, Heap::kRealStackLimitRootIndex); | 165 __ LoadRoot(a2, Heap::kRealStackLimitRootIndex); |
166 __ Branch(&ok, hs, t1, Operand(a2)); | 166 __ Branch(&ok, hs, t1, Operand(a2)); |
167 __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION); | 167 __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION); |
168 __ bind(&ok); | 168 __ bind(&ok); |
169 } | 169 } |
170 __ LoadRoot(t1, Heap::kUndefinedValueRootIndex); | 170 __ LoadRoot(t1, Heap::kUndefinedValueRootIndex); |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
289 Comment cmnt(masm_, "[ Declarations"); | 289 Comment cmnt(masm_, "[ Declarations"); |
290 scope()->VisitIllegalRedeclaration(this); | 290 scope()->VisitIllegalRedeclaration(this); |
291 | 291 |
292 } else { | 292 } else { |
293 PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS); | 293 PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS); |
294 { Comment cmnt(masm_, "[ Declarations"); | 294 { Comment cmnt(masm_, "[ Declarations"); |
295 // For named function expressions, declare the function name as a | 295 // For named function expressions, declare the function name as a |
296 // constant. | 296 // constant. |
297 if (scope()->is_function_scope() && scope()->function() != NULL) { | 297 if (scope()->is_function_scope() && scope()->function() != NULL) { |
298 VariableDeclaration* function = scope()->function(); | 298 VariableDeclaration* function = scope()->function(); |
299 ASSERT(function->proxy()->var()->mode() == CONST || | 299 DCHECK(function->proxy()->var()->mode() == CONST || |
300 function->proxy()->var()->mode() == CONST_LEGACY); | 300 function->proxy()->var()->mode() == CONST_LEGACY); |
301 ASSERT(function->proxy()->var()->location() != Variable::UNALLOCATED); | 301 DCHECK(function->proxy()->var()->location() != Variable::UNALLOCATED); |
302 VisitVariableDeclaration(function); | 302 VisitVariableDeclaration(function); |
303 } | 303 } |
304 VisitDeclarations(scope()->declarations()); | 304 VisitDeclarations(scope()->declarations()); |
305 } | 305 } |
306 { Comment cmnt(masm_, "[ Stack check"); | 306 { Comment cmnt(masm_, "[ Stack check"); |
307 PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS); | 307 PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS); |
308 Label ok; | 308 Label ok; |
309 __ LoadRoot(at, Heap::kStackLimitRootIndex); | 309 __ LoadRoot(at, Heap::kStackLimitRootIndex); |
310 __ Branch(&ok, hs, sp, Operand(at)); | 310 __ Branch(&ok, hs, sp, Operand(at)); |
311 Handle<Code> stack_check = isolate()->builtins()->StackCheck(); | 311 Handle<Code> stack_check = isolate()->builtins()->StackCheck(); |
312 PredictableCodeSizeScope predictable(masm_, | 312 PredictableCodeSizeScope predictable(masm_, |
313 masm_->CallSize(stack_check, RelocInfo::CODE_TARGET)); | 313 masm_->CallSize(stack_check, RelocInfo::CODE_TARGET)); |
314 __ Call(stack_check, RelocInfo::CODE_TARGET); | 314 __ Call(stack_check, RelocInfo::CODE_TARGET); |
315 __ bind(&ok); | 315 __ bind(&ok); |
316 } | 316 } |
317 | 317 |
318 { Comment cmnt(masm_, "[ Body"); | 318 { Comment cmnt(masm_, "[ Body"); |
319 ASSERT(loop_depth() == 0); | 319 DCHECK(loop_depth() == 0); |
320 | 320 |
321 VisitStatements(function()->body()); | 321 VisitStatements(function()->body()); |
322 | 322 |
323 ASSERT(loop_depth() == 0); | 323 DCHECK(loop_depth() == 0); |
324 } | 324 } |
325 } | 325 } |
326 | 326 |
327 // Always emit a 'return undefined' in case control fell off the end of | 327 // Always emit a 'return undefined' in case control fell off the end of |
328 // the body. | 328 // the body. |
329 { Comment cmnt(masm_, "[ return <undefined>;"); | 329 { Comment cmnt(masm_, "[ return <undefined>;"); |
330 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex); | 330 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex); |
331 } | 331 } |
332 EmitReturnSequence(); | 332 EmitReturnSequence(); |
333 } | 333 } |
334 | 334 |
335 | 335 |
336 void FullCodeGenerator::ClearAccumulator() { | 336 void FullCodeGenerator::ClearAccumulator() { |
337 ASSERT(Smi::FromInt(0) == 0); | 337 DCHECK(Smi::FromInt(0) == 0); |
338 __ mov(v0, zero_reg); | 338 __ mov(v0, zero_reg); |
339 } | 339 } |
340 | 340 |
341 | 341 |
342 void FullCodeGenerator::EmitProfilingCounterDecrement(int delta) { | 342 void FullCodeGenerator::EmitProfilingCounterDecrement(int delta) { |
343 __ li(a2, Operand(profiling_counter_)); | 343 __ li(a2, Operand(profiling_counter_)); |
344 __ ld(a3, FieldMemOperand(a2, Cell::kValueOffset)); | 344 __ ld(a3, FieldMemOperand(a2, Cell::kValueOffset)); |
345 __ Dsubu(a3, a3, Operand(Smi::FromInt(delta))); | 345 __ Dsubu(a3, a3, Operand(Smi::FromInt(delta))); |
346 __ sd(a3, FieldMemOperand(a2, Cell::kValueOffset)); | 346 __ sd(a3, FieldMemOperand(a2, Cell::kValueOffset)); |
347 } | 347 } |
(...skipping 14 matching lines...) Expand all Loading... |
362 void FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt, | 362 void FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt, |
363 Label* back_edge_target) { | 363 Label* back_edge_target) { |
364 // The generated code is used in Deoptimizer::PatchStackCheckCodeAt so we need | 364 // The generated code is used in Deoptimizer::PatchStackCheckCodeAt so we need |
365 // to make sure it is constant. Branch may emit a skip-or-jump sequence | 365 // to make sure it is constant. Branch may emit a skip-or-jump sequence |
366 // instead of the normal Branch. It seems that the "skip" part of that | 366 // instead of the normal Branch. It seems that the "skip" part of that |
367 // sequence is about as long as this Branch would be so it is safe to ignore | 367 // sequence is about as long as this Branch would be so it is safe to ignore |
368 // that. | 368 // that. |
369 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_); | 369 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_); |
370 Comment cmnt(masm_, "[ Back edge bookkeeping"); | 370 Comment cmnt(masm_, "[ Back edge bookkeeping"); |
371 Label ok; | 371 Label ok; |
372 ASSERT(back_edge_target->is_bound()); | 372 DCHECK(back_edge_target->is_bound()); |
373 int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target); | 373 int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target); |
374 int weight = Min(kMaxBackEdgeWeight, | 374 int weight = Min(kMaxBackEdgeWeight, |
375 Max(1, distance / kCodeSizeMultiplier)); | 375 Max(1, distance / kCodeSizeMultiplier)); |
376 EmitProfilingCounterDecrement(weight); | 376 EmitProfilingCounterDecrement(weight); |
377 __ slt(at, a3, zero_reg); | 377 __ slt(at, a3, zero_reg); |
378 __ beq(at, zero_reg, &ok); | 378 __ beq(at, zero_reg, &ok); |
379 // Call will emit a li t9 first, so it is safe to use the delay slot. | 379 // Call will emit a li t9 first, so it is safe to use the delay slot. |
380 __ Call(isolate()->builtins()->InterruptCheck(), RelocInfo::CODE_TARGET); | 380 __ Call(isolate()->builtins()->InterruptCheck(), RelocInfo::CODE_TARGET); |
381 // Record a mapping of this PC offset to the OSR id. This is used to find | 381 // Record a mapping of this PC offset to the OSR id. This is used to find |
382 // the AST id from the unoptimized code in order to use it as a key into | 382 // the AST id from the unoptimized code in order to use it as a key into |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
441 int no_frame_start = masm_->pc_offset(); | 441 int no_frame_start = masm_->pc_offset(); |
442 masm_->MultiPop(static_cast<RegList>(fp.bit() | ra.bit())); | 442 masm_->MultiPop(static_cast<RegList>(fp.bit() | ra.bit())); |
443 masm_->Daddu(sp, sp, Operand(sp_delta)); | 443 masm_->Daddu(sp, sp, Operand(sp_delta)); |
444 masm_->Jump(ra); | 444 masm_->Jump(ra); |
445 info_->AddNoFrameRange(no_frame_start, masm_->pc_offset()); | 445 info_->AddNoFrameRange(no_frame_start, masm_->pc_offset()); |
446 } | 446 } |
447 | 447 |
448 #ifdef DEBUG | 448 #ifdef DEBUG |
449 // Check that the size of the code used for returning is large enough | 449 // Check that the size of the code used for returning is large enough |
450 // for the debugger's requirements. | 450 // for the debugger's requirements. |
451 ASSERT(Assembler::kJSReturnSequenceInstructions <= | 451 DCHECK(Assembler::kJSReturnSequenceInstructions <= |
452 masm_->InstructionsGeneratedSince(&check_exit_codesize)); | 452 masm_->InstructionsGeneratedSince(&check_exit_codesize)); |
453 #endif | 453 #endif |
454 } | 454 } |
455 } | 455 } |
456 | 456 |
457 | 457 |
458 void FullCodeGenerator::EffectContext::Plug(Variable* var) const { | 458 void FullCodeGenerator::EffectContext::Plug(Variable* var) const { |
459 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); | 459 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
460 } | 460 } |
461 | 461 |
462 | 462 |
463 void FullCodeGenerator::AccumulatorValueContext::Plug(Variable* var) const { | 463 void FullCodeGenerator::AccumulatorValueContext::Plug(Variable* var) const { |
464 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); | 464 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
465 codegen()->GetVar(result_register(), var); | 465 codegen()->GetVar(result_register(), var); |
466 } | 466 } |
467 | 467 |
468 | 468 |
469 void FullCodeGenerator::StackValueContext::Plug(Variable* var) const { | 469 void FullCodeGenerator::StackValueContext::Plug(Variable* var) const { |
470 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); | 470 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
471 codegen()->GetVar(result_register(), var); | 471 codegen()->GetVar(result_register(), var); |
472 __ push(result_register()); | 472 __ push(result_register()); |
473 } | 473 } |
474 | 474 |
475 | 475 |
476 void FullCodeGenerator::TestContext::Plug(Variable* var) const { | 476 void FullCodeGenerator::TestContext::Plug(Variable* var) const { |
477 // For simplicity we always test the accumulator register. | 477 // For simplicity we always test the accumulator register. |
478 codegen()->GetVar(result_register(), var); | 478 codegen()->GetVar(result_register(), var); |
479 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); | 479 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); |
480 codegen()->DoTest(this); | 480 codegen()->DoTest(this); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
531 __ li(result_register(), Operand(lit)); | 531 __ li(result_register(), Operand(lit)); |
532 __ push(result_register()); | 532 __ push(result_register()); |
533 } | 533 } |
534 | 534 |
535 | 535 |
536 void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const { | 536 void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const { |
537 codegen()->PrepareForBailoutBeforeSplit(condition(), | 537 codegen()->PrepareForBailoutBeforeSplit(condition(), |
538 true, | 538 true, |
539 true_label_, | 539 true_label_, |
540 false_label_); | 540 false_label_); |
541 ASSERT(!lit->IsUndetectableObject()); // There are no undetectable literals. | 541 DCHECK(!lit->IsUndetectableObject()); // There are no undetectable literals. |
542 if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) { | 542 if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) { |
543 if (false_label_ != fall_through_) __ Branch(false_label_); | 543 if (false_label_ != fall_through_) __ Branch(false_label_); |
544 } else if (lit->IsTrue() || lit->IsJSObject()) { | 544 } else if (lit->IsTrue() || lit->IsJSObject()) { |
545 if (true_label_ != fall_through_) __ Branch(true_label_); | 545 if (true_label_ != fall_through_) __ Branch(true_label_); |
546 } else if (lit->IsString()) { | 546 } else if (lit->IsString()) { |
547 if (String::cast(*lit)->length() == 0) { | 547 if (String::cast(*lit)->length() == 0) { |
548 if (false_label_ != fall_through_) __ Branch(false_label_); | 548 if (false_label_ != fall_through_) __ Branch(false_label_); |
549 } else { | 549 } else { |
550 if (true_label_ != fall_through_) __ Branch(true_label_); | 550 if (true_label_ != fall_through_) __ Branch(true_label_); |
551 } | 551 } |
552 } else if (lit->IsSmi()) { | 552 } else if (lit->IsSmi()) { |
553 if (Smi::cast(*lit)->value() == 0) { | 553 if (Smi::cast(*lit)->value() == 0) { |
554 if (false_label_ != fall_through_) __ Branch(false_label_); | 554 if (false_label_ != fall_through_) __ Branch(false_label_); |
555 } else { | 555 } else { |
556 if (true_label_ != fall_through_) __ Branch(true_label_); | 556 if (true_label_ != fall_through_) __ Branch(true_label_); |
557 } | 557 } |
558 } else { | 558 } else { |
559 // For simplicity we always test the accumulator register. | 559 // For simplicity we always test the accumulator register. |
560 __ li(result_register(), Operand(lit)); | 560 __ li(result_register(), Operand(lit)); |
561 codegen()->DoTest(this); | 561 codegen()->DoTest(this); |
562 } | 562 } |
563 } | 563 } |
564 | 564 |
565 | 565 |
566 void FullCodeGenerator::EffectContext::DropAndPlug(int count, | 566 void FullCodeGenerator::EffectContext::DropAndPlug(int count, |
567 Register reg) const { | 567 Register reg) const { |
568 ASSERT(count > 0); | 568 DCHECK(count > 0); |
569 __ Drop(count); | 569 __ Drop(count); |
570 } | 570 } |
571 | 571 |
572 | 572 |
573 void FullCodeGenerator::AccumulatorValueContext::DropAndPlug( | 573 void FullCodeGenerator::AccumulatorValueContext::DropAndPlug( |
574 int count, | 574 int count, |
575 Register reg) const { | 575 Register reg) const { |
576 ASSERT(count > 0); | 576 DCHECK(count > 0); |
577 __ Drop(count); | 577 __ Drop(count); |
578 __ Move(result_register(), reg); | 578 __ Move(result_register(), reg); |
579 } | 579 } |
580 | 580 |
581 | 581 |
582 void FullCodeGenerator::StackValueContext::DropAndPlug(int count, | 582 void FullCodeGenerator::StackValueContext::DropAndPlug(int count, |
583 Register reg) const { | 583 Register reg) const { |
584 ASSERT(count > 0); | 584 DCHECK(count > 0); |
585 if (count > 1) __ Drop(count - 1); | 585 if (count > 1) __ Drop(count - 1); |
586 __ sd(reg, MemOperand(sp, 0)); | 586 __ sd(reg, MemOperand(sp, 0)); |
587 } | 587 } |
588 | 588 |
589 | 589 |
590 void FullCodeGenerator::TestContext::DropAndPlug(int count, | 590 void FullCodeGenerator::TestContext::DropAndPlug(int count, |
591 Register reg) const { | 591 Register reg) const { |
592 ASSERT(count > 0); | 592 DCHECK(count > 0); |
593 // For simplicity we always test the accumulator register. | 593 // For simplicity we always test the accumulator register. |
594 __ Drop(count); | 594 __ Drop(count); |
595 __ Move(result_register(), reg); | 595 __ Move(result_register(), reg); |
596 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); | 596 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); |
597 codegen()->DoTest(this); | 597 codegen()->DoTest(this); |
598 } | 598 } |
599 | 599 |
600 | 600 |
601 void FullCodeGenerator::EffectContext::Plug(Label* materialize_true, | 601 void FullCodeGenerator::EffectContext::Plug(Label* materialize_true, |
602 Label* materialize_false) const { | 602 Label* materialize_false) const { |
603 ASSERT(materialize_true == materialize_false); | 603 DCHECK(materialize_true == materialize_false); |
604 __ bind(materialize_true); | 604 __ bind(materialize_true); |
605 } | 605 } |
606 | 606 |
607 | 607 |
608 void FullCodeGenerator::AccumulatorValueContext::Plug( | 608 void FullCodeGenerator::AccumulatorValueContext::Plug( |
609 Label* materialize_true, | 609 Label* materialize_true, |
610 Label* materialize_false) const { | 610 Label* materialize_false) const { |
611 Label done; | 611 Label done; |
612 __ bind(materialize_true); | 612 __ bind(materialize_true); |
613 __ LoadRoot(result_register(), Heap::kTrueValueRootIndex); | 613 __ LoadRoot(result_register(), Heap::kTrueValueRootIndex); |
(...skipping 15 matching lines...) Expand all Loading... |
629 __ Branch(&done); | 629 __ Branch(&done); |
630 __ bind(materialize_false); | 630 __ bind(materialize_false); |
631 __ LoadRoot(at, Heap::kFalseValueRootIndex); | 631 __ LoadRoot(at, Heap::kFalseValueRootIndex); |
632 __ push(at); | 632 __ push(at); |
633 __ bind(&done); | 633 __ bind(&done); |
634 } | 634 } |
635 | 635 |
636 | 636 |
637 void FullCodeGenerator::TestContext::Plug(Label* materialize_true, | 637 void FullCodeGenerator::TestContext::Plug(Label* materialize_true, |
638 Label* materialize_false) const { | 638 Label* materialize_false) const { |
639 ASSERT(materialize_true == true_label_); | 639 DCHECK(materialize_true == true_label_); |
640 ASSERT(materialize_false == false_label_); | 640 DCHECK(materialize_false == false_label_); |
641 } | 641 } |
642 | 642 |
643 | 643 |
644 void FullCodeGenerator::EffectContext::Plug(bool flag) const { | 644 void FullCodeGenerator::EffectContext::Plug(bool flag) const { |
645 } | 645 } |
646 | 646 |
647 | 647 |
648 void FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const { | 648 void FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const { |
649 Heap::RootListIndex value_root_index = | 649 Heap::RootListIndex value_root_index = |
650 flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; | 650 flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
696 } else if (if_true == fall_through) { | 696 } else if (if_true == fall_through) { |
697 __ Branch(if_false, NegateCondition(cc), lhs, rhs); | 697 __ Branch(if_false, NegateCondition(cc), lhs, rhs); |
698 } else { | 698 } else { |
699 __ Branch(if_true, cc, lhs, rhs); | 699 __ Branch(if_true, cc, lhs, rhs); |
700 __ Branch(if_false); | 700 __ Branch(if_false); |
701 } | 701 } |
702 } | 702 } |
703 | 703 |
704 | 704 |
705 MemOperand FullCodeGenerator::StackOperand(Variable* var) { | 705 MemOperand FullCodeGenerator::StackOperand(Variable* var) { |
706 ASSERT(var->IsStackAllocated()); | 706 DCHECK(var->IsStackAllocated()); |
707 // Offset is negative because higher indexes are at lower addresses. | 707 // Offset is negative because higher indexes are at lower addresses. |
708 int offset = -var->index() * kPointerSize; | 708 int offset = -var->index() * kPointerSize; |
709 // Adjust by a (parameter or local) base offset. | 709 // Adjust by a (parameter or local) base offset. |
710 if (var->IsParameter()) { | 710 if (var->IsParameter()) { |
711 offset += (info_->scope()->num_parameters() + 1) * kPointerSize; | 711 offset += (info_->scope()->num_parameters() + 1) * kPointerSize; |
712 } else { | 712 } else { |
713 offset += JavaScriptFrameConstants::kLocal0Offset; | 713 offset += JavaScriptFrameConstants::kLocal0Offset; |
714 } | 714 } |
715 return MemOperand(fp, offset); | 715 return MemOperand(fp, offset); |
716 } | 716 } |
717 | 717 |
718 | 718 |
719 MemOperand FullCodeGenerator::VarOperand(Variable* var, Register scratch) { | 719 MemOperand FullCodeGenerator::VarOperand(Variable* var, Register scratch) { |
720 ASSERT(var->IsContextSlot() || var->IsStackAllocated()); | 720 DCHECK(var->IsContextSlot() || var->IsStackAllocated()); |
721 if (var->IsContextSlot()) { | 721 if (var->IsContextSlot()) { |
722 int context_chain_length = scope()->ContextChainLength(var->scope()); | 722 int context_chain_length = scope()->ContextChainLength(var->scope()); |
723 __ LoadContext(scratch, context_chain_length); | 723 __ LoadContext(scratch, context_chain_length); |
724 return ContextOperand(scratch, var->index()); | 724 return ContextOperand(scratch, var->index()); |
725 } else { | 725 } else { |
726 return StackOperand(var); | 726 return StackOperand(var); |
727 } | 727 } |
728 } | 728 } |
729 | 729 |
730 | 730 |
731 void FullCodeGenerator::GetVar(Register dest, Variable* var) { | 731 void FullCodeGenerator::GetVar(Register dest, Variable* var) { |
732 // Use destination as scratch. | 732 // Use destination as scratch. |
733 MemOperand location = VarOperand(var, dest); | 733 MemOperand location = VarOperand(var, dest); |
734 __ ld(dest, location); | 734 __ ld(dest, location); |
735 } | 735 } |
736 | 736 |
737 | 737 |
738 void FullCodeGenerator::SetVar(Variable* var, | 738 void FullCodeGenerator::SetVar(Variable* var, |
739 Register src, | 739 Register src, |
740 Register scratch0, | 740 Register scratch0, |
741 Register scratch1) { | 741 Register scratch1) { |
742 ASSERT(var->IsContextSlot() || var->IsStackAllocated()); | 742 DCHECK(var->IsContextSlot() || var->IsStackAllocated()); |
743 ASSERT(!scratch0.is(src)); | 743 DCHECK(!scratch0.is(src)); |
744 ASSERT(!scratch0.is(scratch1)); | 744 DCHECK(!scratch0.is(scratch1)); |
745 ASSERT(!scratch1.is(src)); | 745 DCHECK(!scratch1.is(src)); |
746 MemOperand location = VarOperand(var, scratch0); | 746 MemOperand location = VarOperand(var, scratch0); |
747 __ sd(src, location); | 747 __ sd(src, location); |
748 // Emit the write barrier code if the location is in the heap. | 748 // Emit the write barrier code if the location is in the heap. |
749 if (var->IsContextSlot()) { | 749 if (var->IsContextSlot()) { |
750 __ RecordWriteContextSlot(scratch0, | 750 __ RecordWriteContextSlot(scratch0, |
751 location.offset(), | 751 location.offset(), |
752 src, | 752 src, |
753 scratch1, | 753 scratch1, |
754 kRAHasBeenSaved, | 754 kRAHasBeenSaved, |
755 kDontSaveFPRegs); | 755 kDontSaveFPRegs); |
(...skipping 17 matching lines...) Expand all Loading... |
773 __ LoadRoot(a4, Heap::kTrueValueRootIndex); | 773 __ LoadRoot(a4, Heap::kTrueValueRootIndex); |
774 Split(eq, a0, Operand(a4), if_true, if_false, NULL); | 774 Split(eq, a0, Operand(a4), if_true, if_false, NULL); |
775 __ bind(&skip); | 775 __ bind(&skip); |
776 } | 776 } |
777 } | 777 } |
778 | 778 |
779 | 779 |
780 void FullCodeGenerator::EmitDebugCheckDeclarationContext(Variable* variable) { | 780 void FullCodeGenerator::EmitDebugCheckDeclarationContext(Variable* variable) { |
781 // The variable in the declaration always resides in the current function | 781 // The variable in the declaration always resides in the current function |
782 // context. | 782 // context. |
783 ASSERT_EQ(0, scope()->ContextChainLength(variable->scope())); | 783 DCHECK_EQ(0, scope()->ContextChainLength(variable->scope())); |
784 if (generate_debug_code_) { | 784 if (generate_debug_code_) { |
785 // Check that we're not inside a with or catch context. | 785 // Check that we're not inside a with or catch context. |
786 __ ld(a1, FieldMemOperand(cp, HeapObject::kMapOffset)); | 786 __ ld(a1, FieldMemOperand(cp, HeapObject::kMapOffset)); |
787 __ LoadRoot(a4, Heap::kWithContextMapRootIndex); | 787 __ LoadRoot(a4, Heap::kWithContextMapRootIndex); |
788 __ Check(ne, kDeclarationInWithContext, | 788 __ Check(ne, kDeclarationInWithContext, |
789 a1, Operand(a4)); | 789 a1, Operand(a4)); |
790 __ LoadRoot(a4, Heap::kCatchContextMapRootIndex); | 790 __ LoadRoot(a4, Heap::kCatchContextMapRootIndex); |
791 __ Check(ne, kDeclarationInCatchContext, | 791 __ Check(ne, kDeclarationInCatchContext, |
792 a1, Operand(a4)); | 792 a1, Operand(a4)); |
793 } | 793 } |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
829 __ sd(at, ContextOperand(cp, variable->index())); | 829 __ sd(at, ContextOperand(cp, variable->index())); |
830 // No write barrier since the_hole_value is in old space. | 830 // No write barrier since the_hole_value is in old space. |
831 PrepareForBailoutForId(proxy->id(), NO_REGISTERS); | 831 PrepareForBailoutForId(proxy->id(), NO_REGISTERS); |
832 } | 832 } |
833 break; | 833 break; |
834 | 834 |
835 case Variable::LOOKUP: { | 835 case Variable::LOOKUP: { |
836 Comment cmnt(masm_, "[ VariableDeclaration"); | 836 Comment cmnt(masm_, "[ VariableDeclaration"); |
837 __ li(a2, Operand(variable->name())); | 837 __ li(a2, Operand(variable->name())); |
838 // Declaration nodes are always introduced in one of four modes. | 838 // Declaration nodes are always introduced in one of four modes. |
839 ASSERT(IsDeclaredVariableMode(mode)); | 839 DCHECK(IsDeclaredVariableMode(mode)); |
840 PropertyAttributes attr = | 840 PropertyAttributes attr = |
841 IsImmutableVariableMode(mode) ? READ_ONLY : NONE; | 841 IsImmutableVariableMode(mode) ? READ_ONLY : NONE; |
842 __ li(a1, Operand(Smi::FromInt(attr))); | 842 __ li(a1, Operand(Smi::FromInt(attr))); |
843 // Push initial value, if any. | 843 // Push initial value, if any. |
844 // Note: For variables we must not push an initial value (such as | 844 // Note: For variables we must not push an initial value (such as |
845 // 'undefined') because we may have a (legal) redeclaration and we | 845 // 'undefined') because we may have a (legal) redeclaration and we |
846 // must not destroy the current value. | 846 // must not destroy the current value. |
847 if (hole_init) { | 847 if (hole_init) { |
848 __ LoadRoot(a0, Heap::kTheHoleValueRootIndex); | 848 __ LoadRoot(a0, Heap::kTheHoleValueRootIndex); |
849 __ Push(cp, a2, a1, a0); | 849 __ Push(cp, a2, a1, a0); |
850 } else { | 850 } else { |
851 ASSERT(Smi::FromInt(0) == 0); | 851 DCHECK(Smi::FromInt(0) == 0); |
852 __ mov(a0, zero_reg); // Smi::FromInt(0) indicates no initial value. | 852 __ mov(a0, zero_reg); // Smi::FromInt(0) indicates no initial value. |
853 __ Push(cp, a2, a1, a0); | 853 __ Push(cp, a2, a1, a0); |
854 } | 854 } |
855 __ CallRuntime(Runtime::kDeclareLookupSlot, 4); | 855 __ CallRuntime(Runtime::kDeclareLookupSlot, 4); |
856 break; | 856 break; |
857 } | 857 } |
858 } | 858 } |
859 } | 859 } |
860 | 860 |
861 | 861 |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
910 VisitForStackValue(declaration->fun()); | 910 VisitForStackValue(declaration->fun()); |
911 __ CallRuntime(Runtime::kDeclareLookupSlot, 4); | 911 __ CallRuntime(Runtime::kDeclareLookupSlot, 4); |
912 break; | 912 break; |
913 } | 913 } |
914 } | 914 } |
915 } | 915 } |
916 | 916 |
917 | 917 |
918 void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) { | 918 void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) { |
919 Variable* variable = declaration->proxy()->var(); | 919 Variable* variable = declaration->proxy()->var(); |
920 ASSERT(variable->location() == Variable::CONTEXT); | 920 DCHECK(variable->location() == Variable::CONTEXT); |
921 ASSERT(variable->interface()->IsFrozen()); | 921 DCHECK(variable->interface()->IsFrozen()); |
922 Comment cmnt(masm_, "[ ModuleDeclaration"); | 922 Comment cmnt(masm_, "[ ModuleDeclaration"); |
923 EmitDebugCheckDeclarationContext(variable); | 923 EmitDebugCheckDeclarationContext(variable); |
924 | 924 |
925 // Load instance object. | 925 // Load instance object. |
926 __ LoadContext(a1, scope_->ContextChainLength(scope_->GlobalScope())); | 926 __ LoadContext(a1, scope_->ContextChainLength(scope_->GlobalScope())); |
927 __ ld(a1, ContextOperand(a1, variable->interface()->Index())); | 927 __ ld(a1, ContextOperand(a1, variable->interface()->Index())); |
928 __ ld(a1, ContextOperand(a1, Context::EXTENSION_INDEX)); | 928 __ ld(a1, ContextOperand(a1, Context::EXTENSION_INDEX)); |
929 | 929 |
930 // Assign it. | 930 // Assign it. |
931 __ sd(a1, ContextOperand(cp, variable->index())); | 931 __ sd(a1, ContextOperand(cp, variable->index())); |
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1209 | 1209 |
1210 // Check if the expected map still matches that of the enumerable. | 1210 // Check if the expected map still matches that of the enumerable. |
1211 // If not, we may have to filter the key. | 1211 // If not, we may have to filter the key. |
1212 Label update_each; | 1212 Label update_each; |
1213 __ ld(a1, MemOperand(sp, 4 * kPointerSize)); | 1213 __ ld(a1, MemOperand(sp, 4 * kPointerSize)); |
1214 __ ld(a4, FieldMemOperand(a1, HeapObject::kMapOffset)); | 1214 __ ld(a4, FieldMemOperand(a1, HeapObject::kMapOffset)); |
1215 __ Branch(&update_each, eq, a4, Operand(a2)); | 1215 __ Branch(&update_each, eq, a4, Operand(a2)); |
1216 | 1216 |
1217 // For proxies, no filtering is done. | 1217 // For proxies, no filtering is done. |
1218 // TODO(rossberg): What if only a prototype is a proxy? Not specified yet. | 1218 // TODO(rossberg): What if only a prototype is a proxy? Not specified yet. |
1219 ASSERT_EQ(Smi::FromInt(0), 0); | 1219 DCHECK_EQ(Smi::FromInt(0), 0); |
1220 __ Branch(&update_each, eq, a2, Operand(zero_reg)); | 1220 __ Branch(&update_each, eq, a2, Operand(zero_reg)); |
1221 | 1221 |
1222 // Convert the entry to a string or (smi) 0 if it isn't a property | 1222 // Convert the entry to a string or (smi) 0 if it isn't a property |
1223 // any more. If the property has been removed while iterating, we | 1223 // any more. If the property has been removed while iterating, we |
1224 // just skip it. | 1224 // just skip it. |
1225 __ Push(a1, a3); // Enumerable and current entry. | 1225 __ Push(a1, a3); // Enumerable and current entry. |
1226 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION); | 1226 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION); |
1227 __ mov(a3, result_register()); | 1227 __ mov(a3, result_register()); |
1228 __ Branch(loop_statement.continue_label(), eq, a3, Operand(zero_reg)); | 1228 __ Branch(loop_statement.continue_label(), eq, a3, Operand(zero_reg)); |
1229 | 1229 |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1391 | 1391 |
1392 ContextualMode mode = (typeof_state == INSIDE_TYPEOF) | 1392 ContextualMode mode = (typeof_state == INSIDE_TYPEOF) |
1393 ? NOT_CONTEXTUAL | 1393 ? NOT_CONTEXTUAL |
1394 : CONTEXTUAL; | 1394 : CONTEXTUAL; |
1395 CallLoadIC(mode); | 1395 CallLoadIC(mode); |
1396 } | 1396 } |
1397 | 1397 |
1398 | 1398 |
1399 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, | 1399 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, |
1400 Label* slow) { | 1400 Label* slow) { |
1401 ASSERT(var->IsContextSlot()); | 1401 DCHECK(var->IsContextSlot()); |
1402 Register context = cp; | 1402 Register context = cp; |
1403 Register next = a3; | 1403 Register next = a3; |
1404 Register temp = a4; | 1404 Register temp = a4; |
1405 | 1405 |
1406 for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { | 1406 for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { |
1407 if (s->num_heap_slots() > 0) { | 1407 if (s->num_heap_slots() > 0) { |
1408 if (s->calls_sloppy_eval()) { | 1408 if (s->calls_sloppy_eval()) { |
1409 // Check that extension is NULL. | 1409 // Check that extension is NULL. |
1410 __ ld(temp, ContextOperand(context, Context::EXTENSION_INDEX)); | 1410 __ ld(temp, ContextOperand(context, Context::EXTENSION_INDEX)); |
1411 __ Branch(slow, ne, temp, Operand(zero_reg)); | 1411 __ Branch(slow, ne, temp, Operand(zero_reg)); |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1488 case Variable::LOCAL: | 1488 case Variable::LOCAL: |
1489 case Variable::CONTEXT: { | 1489 case Variable::CONTEXT: { |
1490 Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable" | 1490 Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable" |
1491 : "[ Stack variable"); | 1491 : "[ Stack variable"); |
1492 if (var->binding_needs_init()) { | 1492 if (var->binding_needs_init()) { |
1493 // var->scope() may be NULL when the proxy is located in eval code and | 1493 // var->scope() may be NULL when the proxy is located in eval code and |
1494 // refers to a potential outside binding. Currently those bindings are | 1494 // refers to a potential outside binding. Currently those bindings are |
1495 // always looked up dynamically, i.e. in that case | 1495 // always looked up dynamically, i.e. in that case |
1496 // var->location() == LOOKUP. | 1496 // var->location() == LOOKUP. |
1497 // always holds. | 1497 // always holds. |
1498 ASSERT(var->scope() != NULL); | 1498 DCHECK(var->scope() != NULL); |
1499 | 1499 |
1500 // Check if the binding really needs an initialization check. The check | 1500 // Check if the binding really needs an initialization check. The check |
1501 // can be skipped in the following situation: we have a LET or CONST | 1501 // can be skipped in the following situation: we have a LET or CONST |
1502 // binding in harmony mode, both the Variable and the VariableProxy have | 1502 // binding in harmony mode, both the Variable and the VariableProxy have |
1503 // the same declaration scope (i.e. they are both in global code, in the | 1503 // the same declaration scope (i.e. they are both in global code, in the |
1504 // same function or in the same eval code) and the VariableProxy is in | 1504 // same function or in the same eval code) and the VariableProxy is in |
1505 // the source physically located after the initializer of the variable. | 1505 // the source physically located after the initializer of the variable. |
1506 // | 1506 // |
1507 // We cannot skip any initialization checks for CONST in non-harmony | 1507 // We cannot skip any initialization checks for CONST in non-harmony |
1508 // mode because const variables may be declared but never initialized: | 1508 // mode because const variables may be declared but never initialized: |
1509 // if (false) { const x; }; var y = x; | 1509 // if (false) { const x; }; var y = x; |
1510 // | 1510 // |
1511 // The condition on the declaration scopes is a conservative check for | 1511 // The condition on the declaration scopes is a conservative check for |
1512 // nested functions that access a binding and are called before the | 1512 // nested functions that access a binding and are called before the |
1513 // binding is initialized: | 1513 // binding is initialized: |
1514 // function() { f(); let x = 1; function f() { x = 2; } } | 1514 // function() { f(); let x = 1; function f() { x = 2; } } |
1515 // | 1515 // |
1516 bool skip_init_check; | 1516 bool skip_init_check; |
1517 if (var->scope()->DeclarationScope() != scope()->DeclarationScope()) { | 1517 if (var->scope()->DeclarationScope() != scope()->DeclarationScope()) { |
1518 skip_init_check = false; | 1518 skip_init_check = false; |
1519 } else { | 1519 } else { |
1520 // Check that we always have valid source position. | 1520 // Check that we always have valid source position. |
1521 ASSERT(var->initializer_position() != RelocInfo::kNoPosition); | 1521 DCHECK(var->initializer_position() != RelocInfo::kNoPosition); |
1522 ASSERT(proxy->position() != RelocInfo::kNoPosition); | 1522 DCHECK(proxy->position() != RelocInfo::kNoPosition); |
1523 skip_init_check = var->mode() != CONST_LEGACY && | 1523 skip_init_check = var->mode() != CONST_LEGACY && |
1524 var->initializer_position() < proxy->position(); | 1524 var->initializer_position() < proxy->position(); |
1525 } | 1525 } |
1526 | 1526 |
1527 if (!skip_init_check) { | 1527 if (!skip_init_check) { |
1528 // Let and const need a read barrier. | 1528 // Let and const need a read barrier. |
1529 GetVar(v0, var); | 1529 GetVar(v0, var); |
1530 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 1530 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
1531 __ dsubu(at, v0, at); // Sub as compare: at == 0 on eq. | 1531 __ dsubu(at, v0, at); // Sub as compare: at == 0 on eq. |
1532 if (var->mode() == LET || var->mode() == CONST) { | 1532 if (var->mode() == LET || var->mode() == CONST) { |
1533 // Throw a reference error when using an uninitialized let/const | 1533 // Throw a reference error when using an uninitialized let/const |
1534 // binding in harmony mode. | 1534 // binding in harmony mode. |
1535 Label done; | 1535 Label done; |
1536 __ Branch(&done, ne, at, Operand(zero_reg)); | 1536 __ Branch(&done, ne, at, Operand(zero_reg)); |
1537 __ li(a0, Operand(var->name())); | 1537 __ li(a0, Operand(var->name())); |
1538 __ push(a0); | 1538 __ push(a0); |
1539 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 1539 __ CallRuntime(Runtime::kThrowReferenceError, 1); |
1540 __ bind(&done); | 1540 __ bind(&done); |
1541 } else { | 1541 } else { |
1542 // Uninitalized const bindings outside of harmony mode are unholed. | 1542 // Uninitalized const bindings outside of harmony mode are unholed. |
1543 ASSERT(var->mode() == CONST_LEGACY); | 1543 DCHECK(var->mode() == CONST_LEGACY); |
1544 __ LoadRoot(a0, Heap::kUndefinedValueRootIndex); | 1544 __ LoadRoot(a0, Heap::kUndefinedValueRootIndex); |
1545 __ Movz(v0, a0, at); // Conditional move: Undefined if TheHole. | 1545 __ Movz(v0, a0, at); // Conditional move: Undefined if TheHole. |
1546 } | 1546 } |
1547 context()->Plug(v0); | 1547 context()->Plug(v0); |
1548 break; | 1548 break; |
1549 } | 1549 } |
1550 } | 1550 } |
1551 context()->Plug(var); | 1551 context()->Plug(var); |
1552 break; | 1552 break; |
1553 } | 1553 } |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1673 Literal* key = property->key(); | 1673 Literal* key = property->key(); |
1674 Expression* value = property->value(); | 1674 Expression* value = property->value(); |
1675 if (!result_saved) { | 1675 if (!result_saved) { |
1676 __ push(v0); // Save result on stack. | 1676 __ push(v0); // Save result on stack. |
1677 result_saved = true; | 1677 result_saved = true; |
1678 } | 1678 } |
1679 switch (property->kind()) { | 1679 switch (property->kind()) { |
1680 case ObjectLiteral::Property::CONSTANT: | 1680 case ObjectLiteral::Property::CONSTANT: |
1681 UNREACHABLE(); | 1681 UNREACHABLE(); |
1682 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 1682 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
1683 ASSERT(!CompileTimeValue::IsCompileTimeValue(property->value())); | 1683 DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value())); |
1684 // Fall through. | 1684 // Fall through. |
1685 case ObjectLiteral::Property::COMPUTED: | 1685 case ObjectLiteral::Property::COMPUTED: |
1686 if (key->value()->IsInternalizedString()) { | 1686 if (key->value()->IsInternalizedString()) { |
1687 if (property->emit_store()) { | 1687 if (property->emit_store()) { |
1688 VisitForAccumulatorValue(value); | 1688 VisitForAccumulatorValue(value); |
1689 __ mov(StoreIC::ValueRegister(), result_register()); | 1689 __ mov(StoreIC::ValueRegister(), result_register()); |
1690 ASSERT(StoreIC::ValueRegister().is(a0)); | 1690 DCHECK(StoreIC::ValueRegister().is(a0)); |
1691 __ li(StoreIC::NameRegister(), Operand(key->value())); | 1691 __ li(StoreIC::NameRegister(), Operand(key->value())); |
1692 __ ld(StoreIC::ReceiverRegister(), MemOperand(sp)); | 1692 __ ld(StoreIC::ReceiverRegister(), MemOperand(sp)); |
1693 CallStoreIC(key->LiteralFeedbackId()); | 1693 CallStoreIC(key->LiteralFeedbackId()); |
1694 PrepareForBailoutForId(key->id(), NO_REGISTERS); | 1694 PrepareForBailoutForId(key->id(), NO_REGISTERS); |
1695 } else { | 1695 } else { |
1696 VisitForEffect(value); | 1696 VisitForEffect(value); |
1697 } | 1697 } |
1698 break; | 1698 break; |
1699 } | 1699 } |
1700 // Duplicate receiver on stack. | 1700 // Duplicate receiver on stack. |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1739 __ push(a0); | 1739 __ push(a0); |
1740 VisitForStackValue(it->first); | 1740 VisitForStackValue(it->first); |
1741 EmitAccessor(it->second->getter); | 1741 EmitAccessor(it->second->getter); |
1742 EmitAccessor(it->second->setter); | 1742 EmitAccessor(it->second->setter); |
1743 __ li(a0, Operand(Smi::FromInt(NONE))); | 1743 __ li(a0, Operand(Smi::FromInt(NONE))); |
1744 __ push(a0); | 1744 __ push(a0); |
1745 __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5); | 1745 __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5); |
1746 } | 1746 } |
1747 | 1747 |
1748 if (expr->has_function()) { | 1748 if (expr->has_function()) { |
1749 ASSERT(result_saved); | 1749 DCHECK(result_saved); |
1750 __ ld(a0, MemOperand(sp)); | 1750 __ ld(a0, MemOperand(sp)); |
1751 __ push(a0); | 1751 __ push(a0); |
1752 __ CallRuntime(Runtime::kToFastProperties, 1); | 1752 __ CallRuntime(Runtime::kToFastProperties, 1); |
1753 } | 1753 } |
1754 | 1754 |
1755 if (result_saved) { | 1755 if (result_saved) { |
1756 context()->PlugTOS(); | 1756 context()->PlugTOS(); |
1757 } else { | 1757 } else { |
1758 context()->Plug(v0); | 1758 context()->Plug(v0); |
1759 } | 1759 } |
1760 } | 1760 } |
1761 | 1761 |
1762 | 1762 |
1763 void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { | 1763 void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { |
1764 Comment cmnt(masm_, "[ ArrayLiteral"); | 1764 Comment cmnt(masm_, "[ ArrayLiteral"); |
1765 | 1765 |
1766 expr->BuildConstantElements(isolate()); | 1766 expr->BuildConstantElements(isolate()); |
1767 int flags = expr->depth() == 1 | 1767 int flags = expr->depth() == 1 |
1768 ? ArrayLiteral::kShallowElements | 1768 ? ArrayLiteral::kShallowElements |
1769 : ArrayLiteral::kNoFlags; | 1769 : ArrayLiteral::kNoFlags; |
1770 | 1770 |
1771 ZoneList<Expression*>* subexprs = expr->values(); | 1771 ZoneList<Expression*>* subexprs = expr->values(); |
1772 int length = subexprs->length(); | 1772 int length = subexprs->length(); |
1773 | 1773 |
1774 Handle<FixedArray> constant_elements = expr->constant_elements(); | 1774 Handle<FixedArray> constant_elements = expr->constant_elements(); |
1775 ASSERT_EQ(2, constant_elements->length()); | 1775 DCHECK_EQ(2, constant_elements->length()); |
1776 ElementsKind constant_elements_kind = | 1776 ElementsKind constant_elements_kind = |
1777 static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value()); | 1777 static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value()); |
1778 bool has_fast_elements = | 1778 bool has_fast_elements = |
1779 IsFastObjectElementsKind(constant_elements_kind); | 1779 IsFastObjectElementsKind(constant_elements_kind); |
1780 Handle<FixedArrayBase> constant_elements_values( | 1780 Handle<FixedArrayBase> constant_elements_values( |
1781 FixedArrayBase::cast(constant_elements->get(1))); | 1781 FixedArrayBase::cast(constant_elements->get(1))); |
1782 | 1782 |
1783 AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE; | 1783 AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE; |
1784 if (has_fast_elements && !FLAG_allocation_site_pretenuring) { | 1784 if (has_fast_elements && !FLAG_allocation_site_pretenuring) { |
1785 // If the only customer of allocation sites is transitioning, then | 1785 // If the only customer of allocation sites is transitioning, then |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1840 if (result_saved) { | 1840 if (result_saved) { |
1841 __ Pop(); // literal index | 1841 __ Pop(); // literal index |
1842 context()->PlugTOS(); | 1842 context()->PlugTOS(); |
1843 } else { | 1843 } else { |
1844 context()->Plug(v0); | 1844 context()->Plug(v0); |
1845 } | 1845 } |
1846 } | 1846 } |
1847 | 1847 |
1848 | 1848 |
1849 void FullCodeGenerator::VisitAssignment(Assignment* expr) { | 1849 void FullCodeGenerator::VisitAssignment(Assignment* expr) { |
1850 ASSERT(expr->target()->IsValidReferenceExpression()); | 1850 DCHECK(expr->target()->IsValidReferenceExpression()); |
1851 | 1851 |
1852 Comment cmnt(masm_, "[ Assignment"); | 1852 Comment cmnt(masm_, "[ Assignment"); |
1853 | 1853 |
1854 // Left-hand side can only be a property, a global or a (parameter or local) | 1854 // Left-hand side can only be a property, a global or a (parameter or local) |
1855 // slot. | 1855 // slot. |
1856 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 1856 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
1857 LhsKind assign_type = VARIABLE; | 1857 LhsKind assign_type = VARIABLE; |
1858 Property* property = expr->target()->AsProperty(); | 1858 Property* property = expr->target()->AsProperty(); |
1859 if (property != NULL) { | 1859 if (property != NULL) { |
1860 assign_type = (property->key()->IsPropertyName()) | 1860 assign_type = (property->key()->IsPropertyName()) |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1971 case Yield::INITIAL: { | 1971 case Yield::INITIAL: { |
1972 Label suspend, continuation, post_runtime, resume; | 1972 Label suspend, continuation, post_runtime, resume; |
1973 | 1973 |
1974 __ jmp(&suspend); | 1974 __ jmp(&suspend); |
1975 | 1975 |
1976 __ bind(&continuation); | 1976 __ bind(&continuation); |
1977 __ jmp(&resume); | 1977 __ jmp(&resume); |
1978 | 1978 |
1979 __ bind(&suspend); | 1979 __ bind(&suspend); |
1980 VisitForAccumulatorValue(expr->generator_object()); | 1980 VisitForAccumulatorValue(expr->generator_object()); |
1981 ASSERT(continuation.pos() > 0 && Smi::IsValid(continuation.pos())); | 1981 DCHECK(continuation.pos() > 0 && Smi::IsValid(continuation.pos())); |
1982 __ li(a1, Operand(Smi::FromInt(continuation.pos()))); | 1982 __ li(a1, Operand(Smi::FromInt(continuation.pos()))); |
1983 __ sd(a1, FieldMemOperand(v0, JSGeneratorObject::kContinuationOffset)); | 1983 __ sd(a1, FieldMemOperand(v0, JSGeneratorObject::kContinuationOffset)); |
1984 __ sd(cp, FieldMemOperand(v0, JSGeneratorObject::kContextOffset)); | 1984 __ sd(cp, FieldMemOperand(v0, JSGeneratorObject::kContextOffset)); |
1985 __ mov(a1, cp); | 1985 __ mov(a1, cp); |
1986 __ RecordWriteField(v0, JSGeneratorObject::kContextOffset, a1, a2, | 1986 __ RecordWriteField(v0, JSGeneratorObject::kContextOffset, a1, a2, |
1987 kRAHasBeenSaved, kDontSaveFPRegs); | 1987 kRAHasBeenSaved, kDontSaveFPRegs); |
1988 __ Daddu(a1, fp, Operand(StandardFrameConstants::kExpressionsOffset)); | 1988 __ Daddu(a1, fp, Operand(StandardFrameConstants::kExpressionsOffset)); |
1989 __ Branch(&post_runtime, eq, sp, Operand(a1)); | 1989 __ Branch(&post_runtime, eq, sp, Operand(a1)); |
1990 __ push(v0); // generator object | 1990 __ push(v0); // generator object |
1991 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); | 1991 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2044 const int handler_size = StackHandlerConstants::kSize; | 2044 const int handler_size = StackHandlerConstants::kSize; |
2045 __ push(a0); // result | 2045 __ push(a0); // result |
2046 __ jmp(&l_suspend); | 2046 __ jmp(&l_suspend); |
2047 __ bind(&l_continuation); | 2047 __ bind(&l_continuation); |
2048 __ mov(a0, v0); | 2048 __ mov(a0, v0); |
2049 __ jmp(&l_resume); | 2049 __ jmp(&l_resume); |
2050 __ bind(&l_suspend); | 2050 __ bind(&l_suspend); |
2051 const int generator_object_depth = kPointerSize + handler_size; | 2051 const int generator_object_depth = kPointerSize + handler_size; |
2052 __ ld(a0, MemOperand(sp, generator_object_depth)); | 2052 __ ld(a0, MemOperand(sp, generator_object_depth)); |
2053 __ push(a0); // g | 2053 __ push(a0); // g |
2054 ASSERT(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos())); | 2054 DCHECK(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos())); |
2055 __ li(a1, Operand(Smi::FromInt(l_continuation.pos()))); | 2055 __ li(a1, Operand(Smi::FromInt(l_continuation.pos()))); |
2056 __ sd(a1, FieldMemOperand(a0, JSGeneratorObject::kContinuationOffset)); | 2056 __ sd(a1, FieldMemOperand(a0, JSGeneratorObject::kContinuationOffset)); |
2057 __ sd(cp, FieldMemOperand(a0, JSGeneratorObject::kContextOffset)); | 2057 __ sd(cp, FieldMemOperand(a0, JSGeneratorObject::kContextOffset)); |
2058 __ mov(a1, cp); | 2058 __ mov(a1, cp); |
2059 __ RecordWriteField(a0, JSGeneratorObject::kContextOffset, a1, a2, | 2059 __ RecordWriteField(a0, JSGeneratorObject::kContextOffset, a1, a2, |
2060 kRAHasBeenSaved, kDontSaveFPRegs); | 2060 kRAHasBeenSaved, kDontSaveFPRegs); |
2061 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); | 2061 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); |
2062 __ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2062 __ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
2063 __ pop(v0); // result | 2063 __ pop(v0); // result |
2064 EmitReturnSequence(); | 2064 EmitReturnSequence(); |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2199 | 2199 |
2200 // Otherwise, we push holes for the operand stack and call the runtime to fix | 2200 // Otherwise, we push holes for the operand stack and call the runtime to fix |
2201 // up the stack and the handlers. | 2201 // up the stack and the handlers. |
2202 Label push_operand_holes, call_resume; | 2202 Label push_operand_holes, call_resume; |
2203 __ bind(&push_operand_holes); | 2203 __ bind(&push_operand_holes); |
2204 __ Dsubu(a3, a3, Operand(1)); | 2204 __ Dsubu(a3, a3, Operand(1)); |
2205 __ Branch(&call_resume, lt, a3, Operand(zero_reg)); | 2205 __ Branch(&call_resume, lt, a3, Operand(zero_reg)); |
2206 __ push(a2); | 2206 __ push(a2); |
2207 __ Branch(&push_operand_holes); | 2207 __ Branch(&push_operand_holes); |
2208 __ bind(&call_resume); | 2208 __ bind(&call_resume); |
2209 ASSERT(!result_register().is(a1)); | 2209 DCHECK(!result_register().is(a1)); |
2210 __ Push(a1, result_register()); | 2210 __ Push(a1, result_register()); |
2211 __ Push(Smi::FromInt(resume_mode)); | 2211 __ Push(Smi::FromInt(resume_mode)); |
2212 __ CallRuntime(Runtime::kResumeJSGeneratorObject, 3); | 2212 __ CallRuntime(Runtime::kResumeJSGeneratorObject, 3); |
2213 // Not reached: the runtime call returns elsewhere. | 2213 // Not reached: the runtime call returns elsewhere. |
2214 __ stop("not-reached"); | 2214 __ stop("not-reached"); |
2215 | 2215 |
2216 // Reach here when generator is closed. | 2216 // Reach here when generator is closed. |
2217 __ bind(&closed_state); | 2217 __ bind(&closed_state); |
2218 if (resume_mode == JSGeneratorObject::NEXT) { | 2218 if (resume_mode == JSGeneratorObject::NEXT) { |
2219 // Return completed iterator result when generator is closed. | 2219 // Return completed iterator result when generator is closed. |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2251 __ Push(Smi::FromInt(map->instance_size())); | 2251 __ Push(Smi::FromInt(map->instance_size())); |
2252 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); | 2252 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); |
2253 __ ld(context_register(), | 2253 __ ld(context_register(), |
2254 MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2254 MemOperand(fp, StandardFrameConstants::kContextOffset)); |
2255 | 2255 |
2256 __ bind(&allocated); | 2256 __ bind(&allocated); |
2257 __ li(a1, Operand(map)); | 2257 __ li(a1, Operand(map)); |
2258 __ pop(a2); | 2258 __ pop(a2); |
2259 __ li(a3, Operand(isolate()->factory()->ToBoolean(done))); | 2259 __ li(a3, Operand(isolate()->factory()->ToBoolean(done))); |
2260 __ li(a4, Operand(isolate()->factory()->empty_fixed_array())); | 2260 __ li(a4, Operand(isolate()->factory()->empty_fixed_array())); |
2261 ASSERT_EQ(map->instance_size(), 5 * kPointerSize); | 2261 DCHECK_EQ(map->instance_size(), 5 * kPointerSize); |
2262 __ sd(a1, FieldMemOperand(v0, HeapObject::kMapOffset)); | 2262 __ sd(a1, FieldMemOperand(v0, HeapObject::kMapOffset)); |
2263 __ sd(a4, FieldMemOperand(v0, JSObject::kPropertiesOffset)); | 2263 __ sd(a4, FieldMemOperand(v0, JSObject::kPropertiesOffset)); |
2264 __ sd(a4, FieldMemOperand(v0, JSObject::kElementsOffset)); | 2264 __ sd(a4, FieldMemOperand(v0, JSObject::kElementsOffset)); |
2265 __ sd(a2, | 2265 __ sd(a2, |
2266 FieldMemOperand(v0, JSGeneratorObject::kResultValuePropertyOffset)); | 2266 FieldMemOperand(v0, JSGeneratorObject::kResultValuePropertyOffset)); |
2267 __ sd(a3, | 2267 __ sd(a3, |
2268 FieldMemOperand(v0, JSGeneratorObject::kResultDonePropertyOffset)); | 2268 FieldMemOperand(v0, JSGeneratorObject::kResultDonePropertyOffset)); |
2269 | 2269 |
2270 // Only the value field needs a write barrier, as the other values are in the | 2270 // Only the value field needs a write barrier, as the other values are in the |
2271 // root set. | 2271 // root set. |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2365 break; | 2365 break; |
2366 case Token::MUL: { | 2366 case Token::MUL: { |
2367 __ Dmulh(v0, left, right); | 2367 __ Dmulh(v0, left, right); |
2368 __ dsra32(scratch2, v0, 0); | 2368 __ dsra32(scratch2, v0, 0); |
2369 __ sra(scratch1, v0, 31); | 2369 __ sra(scratch1, v0, 31); |
2370 __ Branch(USE_DELAY_SLOT, &stub_call, ne, scratch2, Operand(scratch1)); | 2370 __ Branch(USE_DELAY_SLOT, &stub_call, ne, scratch2, Operand(scratch1)); |
2371 __ SmiTag(v0); | 2371 __ SmiTag(v0); |
2372 __ Branch(USE_DELAY_SLOT, &done, ne, v0, Operand(zero_reg)); | 2372 __ Branch(USE_DELAY_SLOT, &done, ne, v0, Operand(zero_reg)); |
2373 __ Daddu(scratch2, right, left); | 2373 __ Daddu(scratch2, right, left); |
2374 __ Branch(&stub_call, lt, scratch2, Operand(zero_reg)); | 2374 __ Branch(&stub_call, lt, scratch2, Operand(zero_reg)); |
2375 ASSERT(Smi::FromInt(0) == 0); | 2375 DCHECK(Smi::FromInt(0) == 0); |
2376 __ mov(v0, zero_reg); | 2376 __ mov(v0, zero_reg); |
2377 break; | 2377 break; |
2378 } | 2378 } |
2379 case Token::BIT_OR: | 2379 case Token::BIT_OR: |
2380 __ Or(v0, left, Operand(right)); | 2380 __ Or(v0, left, Operand(right)); |
2381 break; | 2381 break; |
2382 case Token::BIT_AND: | 2382 case Token::BIT_AND: |
2383 __ And(v0, left, Operand(right)); | 2383 __ And(v0, left, Operand(right)); |
2384 break; | 2384 break; |
2385 case Token::BIT_XOR: | 2385 case Token::BIT_XOR: |
(...skipping 15 matching lines...) Expand all Loading... |
2401 __ pop(a1); | 2401 __ pop(a1); |
2402 BinaryOpICStub stub(isolate(), op, mode); | 2402 BinaryOpICStub stub(isolate(), op, mode); |
2403 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. | 2403 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. |
2404 CallIC(stub.GetCode(), expr->BinaryOperationFeedbackId()); | 2404 CallIC(stub.GetCode(), expr->BinaryOperationFeedbackId()); |
2405 patch_site.EmitPatchInfo(); | 2405 patch_site.EmitPatchInfo(); |
2406 context()->Plug(v0); | 2406 context()->Plug(v0); |
2407 } | 2407 } |
2408 | 2408 |
2409 | 2409 |
2410 void FullCodeGenerator::EmitAssignment(Expression* expr) { | 2410 void FullCodeGenerator::EmitAssignment(Expression* expr) { |
2411 ASSERT(expr->IsValidReferenceExpression()); | 2411 DCHECK(expr->IsValidReferenceExpression()); |
2412 | 2412 |
2413 // Left-hand side can only be a property, a global or a (parameter or local) | 2413 // Left-hand side can only be a property, a global or a (parameter or local) |
2414 // slot. | 2414 // slot. |
2415 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 2415 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
2416 LhsKind assign_type = VARIABLE; | 2416 LhsKind assign_type = VARIABLE; |
2417 Property* prop = expr->AsProperty(); | 2417 Property* prop = expr->AsProperty(); |
2418 if (prop != NULL) { | 2418 if (prop != NULL) { |
2419 assign_type = (prop->key()->IsPropertyName()) | 2419 assign_type = (prop->key()->IsPropertyName()) |
2420 ? NAMED_PROPERTY | 2420 ? NAMED_PROPERTY |
2421 : KEYED_PROPERTY; | 2421 : KEYED_PROPERTY; |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2470 | 2470 |
2471 void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op) { | 2471 void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op) { |
2472 if (var->IsUnallocated()) { | 2472 if (var->IsUnallocated()) { |
2473 // Global var, const, or let. | 2473 // Global var, const, or let. |
2474 __ mov(StoreIC::ValueRegister(), result_register()); | 2474 __ mov(StoreIC::ValueRegister(), result_register()); |
2475 __ li(StoreIC::NameRegister(), Operand(var->name())); | 2475 __ li(StoreIC::NameRegister(), Operand(var->name())); |
2476 __ ld(StoreIC::ReceiverRegister(), GlobalObjectOperand()); | 2476 __ ld(StoreIC::ReceiverRegister(), GlobalObjectOperand()); |
2477 CallStoreIC(); | 2477 CallStoreIC(); |
2478 } else if (op == Token::INIT_CONST_LEGACY) { | 2478 } else if (op == Token::INIT_CONST_LEGACY) { |
2479 // Const initializers need a write barrier. | 2479 // Const initializers need a write barrier. |
2480 ASSERT(!var->IsParameter()); // No const parameters. | 2480 DCHECK(!var->IsParameter()); // No const parameters. |
2481 if (var->IsLookupSlot()) { | 2481 if (var->IsLookupSlot()) { |
2482 __ li(a0, Operand(var->name())); | 2482 __ li(a0, Operand(var->name())); |
2483 __ Push(v0, cp, a0); // Context and name. | 2483 __ Push(v0, cp, a0); // Context and name. |
2484 __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot, 3); | 2484 __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot, 3); |
2485 } else { | 2485 } else { |
2486 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); | 2486 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
2487 Label skip; | 2487 Label skip; |
2488 MemOperand location = VarOperand(var, a1); | 2488 MemOperand location = VarOperand(var, a1); |
2489 __ ld(a2, location); | 2489 __ ld(a2, location); |
2490 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 2490 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
2491 __ Branch(&skip, ne, a2, Operand(at)); | 2491 __ Branch(&skip, ne, a2, Operand(at)); |
2492 EmitStoreToStackLocalOrContextSlot(var, location); | 2492 EmitStoreToStackLocalOrContextSlot(var, location); |
2493 __ bind(&skip); | 2493 __ bind(&skip); |
2494 } | 2494 } |
2495 | 2495 |
2496 } else if (var->mode() == LET && op != Token::INIT_LET) { | 2496 } else if (var->mode() == LET && op != Token::INIT_LET) { |
2497 // Non-initializing assignment to let variable needs a write barrier. | 2497 // Non-initializing assignment to let variable needs a write barrier. |
2498 ASSERT(!var->IsLookupSlot()); | 2498 DCHECK(!var->IsLookupSlot()); |
2499 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); | 2499 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
2500 Label assign; | 2500 Label assign; |
2501 MemOperand location = VarOperand(var, a1); | 2501 MemOperand location = VarOperand(var, a1); |
2502 __ ld(a3, location); | 2502 __ ld(a3, location); |
2503 __ LoadRoot(a4, Heap::kTheHoleValueRootIndex); | 2503 __ LoadRoot(a4, Heap::kTheHoleValueRootIndex); |
2504 __ Branch(&assign, ne, a3, Operand(a4)); | 2504 __ Branch(&assign, ne, a3, Operand(a4)); |
2505 __ li(a3, Operand(var->name())); | 2505 __ li(a3, Operand(var->name())); |
2506 __ push(a3); | 2506 __ push(a3); |
2507 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 2507 __ CallRuntime(Runtime::kThrowReferenceError, 1); |
2508 // Perform the assignment. | 2508 // Perform the assignment. |
2509 __ bind(&assign); | 2509 __ bind(&assign); |
2510 EmitStoreToStackLocalOrContextSlot(var, location); | 2510 EmitStoreToStackLocalOrContextSlot(var, location); |
2511 | 2511 |
2512 } else if (!var->is_const_mode() || op == Token::INIT_CONST) { | 2512 } else if (!var->is_const_mode() || op == Token::INIT_CONST) { |
2513 if (var->IsLookupSlot()) { | 2513 if (var->IsLookupSlot()) { |
2514 // Assignment to var. | 2514 // Assignment to var. |
2515 __ li(a4, Operand(var->name())); | 2515 __ li(a4, Operand(var->name())); |
2516 __ li(a3, Operand(Smi::FromInt(strict_mode()))); | 2516 __ li(a3, Operand(Smi::FromInt(strict_mode()))); |
2517 // jssp[0] : mode. | 2517 // jssp[0] : mode. |
2518 // jssp[8] : name. | 2518 // jssp[8] : name. |
2519 // jssp[16] : context. | 2519 // jssp[16] : context. |
2520 // jssp[24] : value. | 2520 // jssp[24] : value. |
2521 __ Push(v0, cp, a4, a3); | 2521 __ Push(v0, cp, a4, a3); |
2522 __ CallRuntime(Runtime::kStoreLookupSlot, 4); | 2522 __ CallRuntime(Runtime::kStoreLookupSlot, 4); |
2523 } else { | 2523 } else { |
2524 // Assignment to var or initializing assignment to let/const in harmony | 2524 // Assignment to var or initializing assignment to let/const in harmony |
2525 // mode. | 2525 // mode. |
2526 ASSERT((var->IsStackAllocated() || var->IsContextSlot())); | 2526 DCHECK((var->IsStackAllocated() || var->IsContextSlot())); |
2527 MemOperand location = VarOperand(var, a1); | 2527 MemOperand location = VarOperand(var, a1); |
2528 if (generate_debug_code_ && op == Token::INIT_LET) { | 2528 if (generate_debug_code_ && op == Token::INIT_LET) { |
2529 // Check for an uninitialized let binding. | 2529 // Check for an uninitialized let binding. |
2530 __ ld(a2, location); | 2530 __ ld(a2, location); |
2531 __ LoadRoot(a4, Heap::kTheHoleValueRootIndex); | 2531 __ LoadRoot(a4, Heap::kTheHoleValueRootIndex); |
2532 __ Check(eq, kLetBindingReInitialization, a2, Operand(a4)); | 2532 __ Check(eq, kLetBindingReInitialization, a2, Operand(a4)); |
2533 } | 2533 } |
2534 EmitStoreToStackLocalOrContextSlot(var, location); | 2534 EmitStoreToStackLocalOrContextSlot(var, location); |
2535 } | 2535 } |
2536 } | 2536 } |
2537 // Non-initializing assignments to consts are ignored. | 2537 // Non-initializing assignments to consts are ignored. |
2538 } | 2538 } |
2539 | 2539 |
2540 | 2540 |
2541 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 2541 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
2542 // Assignment to a property, using a named store IC. | 2542 // Assignment to a property, using a named store IC. |
2543 Property* prop = expr->target()->AsProperty(); | 2543 Property* prop = expr->target()->AsProperty(); |
2544 ASSERT(prop != NULL); | 2544 DCHECK(prop != NULL); |
2545 ASSERT(prop->key()->IsLiteral()); | 2545 DCHECK(prop->key()->IsLiteral()); |
2546 | 2546 |
2547 // Record source code position before IC call. | 2547 // Record source code position before IC call. |
2548 SetSourcePosition(expr->position()); | 2548 SetSourcePosition(expr->position()); |
2549 __ mov(StoreIC::ValueRegister(), result_register()); | 2549 __ mov(StoreIC::ValueRegister(), result_register()); |
2550 __ li(StoreIC::NameRegister(), Operand(prop->key()->AsLiteral()->value())); | 2550 __ li(StoreIC::NameRegister(), Operand(prop->key()->AsLiteral()->value())); |
2551 __ pop(StoreIC::ReceiverRegister()); | 2551 __ pop(StoreIC::ReceiverRegister()); |
2552 CallStoreIC(expr->AssignmentFeedbackId()); | 2552 CallStoreIC(expr->AssignmentFeedbackId()); |
2553 | 2553 |
2554 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 2554 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
2555 context()->Plug(v0); | 2555 context()->Plug(v0); |
2556 } | 2556 } |
2557 | 2557 |
2558 | 2558 |
2559 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 2559 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
2560 // Assignment to a property, using a keyed store IC. | 2560 // Assignment to a property, using a keyed store IC. |
2561 | 2561 |
2562 // Record source code position before IC call. | 2562 // Record source code position before IC call. |
2563 SetSourcePosition(expr->position()); | 2563 SetSourcePosition(expr->position()); |
2564 // Call keyed store IC. | 2564 // Call keyed store IC. |
2565 // The arguments are: | 2565 // The arguments are: |
2566 // - a0 is the value, | 2566 // - a0 is the value, |
2567 // - a1 is the key, | 2567 // - a1 is the key, |
2568 // - a2 is the receiver. | 2568 // - a2 is the receiver. |
2569 __ mov(KeyedStoreIC::ValueRegister(), result_register()); | 2569 __ mov(KeyedStoreIC::ValueRegister(), result_register()); |
2570 __ Pop(KeyedStoreIC::ReceiverRegister(), KeyedStoreIC::NameRegister()); | 2570 __ Pop(KeyedStoreIC::ReceiverRegister(), KeyedStoreIC::NameRegister()); |
2571 ASSERT(KeyedStoreIC::ValueRegister().is(a0)); | 2571 DCHECK(KeyedStoreIC::ValueRegister().is(a0)); |
2572 | 2572 |
2573 Handle<Code> ic = strict_mode() == SLOPPY | 2573 Handle<Code> ic = strict_mode() == SLOPPY |
2574 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 2574 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
2575 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 2575 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
2576 CallIC(ic, expr->AssignmentFeedbackId()); | 2576 CallIC(ic, expr->AssignmentFeedbackId()); |
2577 | 2577 |
2578 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 2578 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
2579 context()->Plug(v0); | 2579 context()->Plug(v0); |
2580 } | 2580 } |
2581 | 2581 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2620 if (call_type == CallIC::FUNCTION) { | 2620 if (call_type == CallIC::FUNCTION) { |
2621 { StackValueContext context(this); | 2621 { StackValueContext context(this); |
2622 EmitVariableLoad(callee->AsVariableProxy()); | 2622 EmitVariableLoad(callee->AsVariableProxy()); |
2623 PrepareForBailout(callee, NO_REGISTERS); | 2623 PrepareForBailout(callee, NO_REGISTERS); |
2624 } | 2624 } |
2625 // Push undefined as receiver. This is patched in the method prologue if it | 2625 // Push undefined as receiver. This is patched in the method prologue if it |
2626 // is a sloppy mode method. | 2626 // is a sloppy mode method. |
2627 __ Push(isolate()->factory()->undefined_value()); | 2627 __ Push(isolate()->factory()->undefined_value()); |
2628 } else { | 2628 } else { |
2629 // Load the function from the receiver. | 2629 // Load the function from the receiver. |
2630 ASSERT(callee->IsProperty()); | 2630 DCHECK(callee->IsProperty()); |
2631 __ ld(LoadIC::ReceiverRegister(), MemOperand(sp, 0)); | 2631 __ ld(LoadIC::ReceiverRegister(), MemOperand(sp, 0)); |
2632 EmitNamedPropertyLoad(callee->AsProperty()); | 2632 EmitNamedPropertyLoad(callee->AsProperty()); |
2633 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); | 2633 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); |
2634 // Push the target function under the receiver. | 2634 // Push the target function under the receiver. |
2635 __ ld(at, MemOperand(sp, 0)); | 2635 __ ld(at, MemOperand(sp, 0)); |
2636 __ push(at); | 2636 __ push(at); |
2637 __ sd(v0, MemOperand(sp, kPointerSize)); | 2637 __ sd(v0, MemOperand(sp, kPointerSize)); |
2638 } | 2638 } |
2639 | 2639 |
2640 EmitCall(expr, call_type); | 2640 EmitCall(expr, call_type); |
2641 } | 2641 } |
2642 | 2642 |
2643 | 2643 |
2644 // Code common for calls using the IC. | 2644 // Code common for calls using the IC. |
2645 void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr, | 2645 void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr, |
2646 Expression* key) { | 2646 Expression* key) { |
2647 // Load the key. | 2647 // Load the key. |
2648 VisitForAccumulatorValue(key); | 2648 VisitForAccumulatorValue(key); |
2649 | 2649 |
2650 Expression* callee = expr->expression(); | 2650 Expression* callee = expr->expression(); |
2651 | 2651 |
2652 // Load the function from the receiver. | 2652 // Load the function from the receiver. |
2653 ASSERT(callee->IsProperty()); | 2653 DCHECK(callee->IsProperty()); |
2654 __ ld(LoadIC::ReceiverRegister(), MemOperand(sp, 0)); | 2654 __ ld(LoadIC::ReceiverRegister(), MemOperand(sp, 0)); |
2655 __ Move(LoadIC::NameRegister(), v0); | 2655 __ Move(LoadIC::NameRegister(), v0); |
2656 EmitKeyedPropertyLoad(callee->AsProperty()); | 2656 EmitKeyedPropertyLoad(callee->AsProperty()); |
2657 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); | 2657 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); |
2658 | 2658 |
2659 // Push the target function under the receiver. | 2659 // Push the target function under the receiver. |
2660 __ ld(at, MemOperand(sp, 0)); | 2660 __ ld(at, MemOperand(sp, 0)); |
2661 __ push(at); | 2661 __ push(at); |
2662 __ sd(v0, MemOperand(sp, kPointerSize)); | 2662 __ sd(v0, MemOperand(sp, kPointerSize)); |
2663 | 2663 |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2773 | 2773 |
2774 { PreservePositionScope scope(masm()->positions_recorder()); | 2774 { PreservePositionScope scope(masm()->positions_recorder()); |
2775 // Generate code for loading from variables potentially shadowed | 2775 // Generate code for loading from variables potentially shadowed |
2776 // by eval-introduced variables. | 2776 // by eval-introduced variables. |
2777 EmitDynamicLookupFastCase(proxy, NOT_INSIDE_TYPEOF, &slow, &done); | 2777 EmitDynamicLookupFastCase(proxy, NOT_INSIDE_TYPEOF, &slow, &done); |
2778 } | 2778 } |
2779 | 2779 |
2780 __ bind(&slow); | 2780 __ bind(&slow); |
2781 // Call the runtime to find the function to call (returned in v0) | 2781 // Call the runtime to find the function to call (returned in v0) |
2782 // and the object holding it (returned in v1). | 2782 // and the object holding it (returned in v1). |
2783 ASSERT(!context_register().is(a2)); | 2783 DCHECK(!context_register().is(a2)); |
2784 __ li(a2, Operand(proxy->name())); | 2784 __ li(a2, Operand(proxy->name())); |
2785 __ Push(context_register(), a2); | 2785 __ Push(context_register(), a2); |
2786 __ CallRuntime(Runtime::kLoadLookupSlot, 2); | 2786 __ CallRuntime(Runtime::kLoadLookupSlot, 2); |
2787 __ Push(v0, v1); // Function, receiver. | 2787 __ Push(v0, v1); // Function, receiver. |
2788 | 2788 |
2789 // If fast case code has been generated, emit code to push the | 2789 // If fast case code has been generated, emit code to push the |
2790 // function and receiver and have the slow path jump around this | 2790 // function and receiver and have the slow path jump around this |
2791 // code. | 2791 // code. |
2792 if (done.is_linked()) { | 2792 if (done.is_linked()) { |
2793 Label call; | 2793 Label call; |
(...skipping 15 matching lines...) Expand all Loading... |
2809 Property* property = callee->AsProperty(); | 2809 Property* property = callee->AsProperty(); |
2810 { PreservePositionScope scope(masm()->positions_recorder()); | 2810 { PreservePositionScope scope(masm()->positions_recorder()); |
2811 VisitForStackValue(property->obj()); | 2811 VisitForStackValue(property->obj()); |
2812 } | 2812 } |
2813 if (property->key()->IsPropertyName()) { | 2813 if (property->key()->IsPropertyName()) { |
2814 EmitCallWithLoadIC(expr); | 2814 EmitCallWithLoadIC(expr); |
2815 } else { | 2815 } else { |
2816 EmitKeyedCallWithLoadIC(expr, property->key()); | 2816 EmitKeyedCallWithLoadIC(expr, property->key()); |
2817 } | 2817 } |
2818 } else { | 2818 } else { |
2819 ASSERT(call_type == Call::OTHER_CALL); | 2819 DCHECK(call_type == Call::OTHER_CALL); |
2820 // Call to an arbitrary expression not handled specially above. | 2820 // Call to an arbitrary expression not handled specially above. |
2821 { PreservePositionScope scope(masm()->positions_recorder()); | 2821 { PreservePositionScope scope(masm()->positions_recorder()); |
2822 VisitForStackValue(callee); | 2822 VisitForStackValue(callee); |
2823 } | 2823 } |
2824 __ LoadRoot(a1, Heap::kUndefinedValueRootIndex); | 2824 __ LoadRoot(a1, Heap::kUndefinedValueRootIndex); |
2825 __ push(a1); | 2825 __ push(a1); |
2826 // Emit function call. | 2826 // Emit function call. |
2827 EmitCall(expr); | 2827 EmitCall(expr); |
2828 } | 2828 } |
2829 | 2829 |
2830 #ifdef DEBUG | 2830 #ifdef DEBUG |
2831 // RecordJSReturnSite should have been called. | 2831 // RecordJSReturnSite should have been called. |
2832 ASSERT(expr->return_is_recorded_); | 2832 DCHECK(expr->return_is_recorded_); |
2833 #endif | 2833 #endif |
2834 } | 2834 } |
2835 | 2835 |
2836 | 2836 |
2837 void FullCodeGenerator::VisitCallNew(CallNew* expr) { | 2837 void FullCodeGenerator::VisitCallNew(CallNew* expr) { |
2838 Comment cmnt(masm_, "[ CallNew"); | 2838 Comment cmnt(masm_, "[ CallNew"); |
2839 // According to ECMA-262, section 11.2.2, page 44, the function | 2839 // According to ECMA-262, section 11.2.2, page 44, the function |
2840 // expression in new calls must be evaluated before the | 2840 // expression in new calls must be evaluated before the |
2841 // arguments. | 2841 // arguments. |
2842 | 2842 |
(...skipping 12 matching lines...) Expand all Loading... |
2855 // constructor invocation. | 2855 // constructor invocation. |
2856 SetSourcePosition(expr->position()); | 2856 SetSourcePosition(expr->position()); |
2857 | 2857 |
2858 // Load function and argument count into a1 and a0. | 2858 // Load function and argument count into a1 and a0. |
2859 __ li(a0, Operand(arg_count)); | 2859 __ li(a0, Operand(arg_count)); |
2860 __ ld(a1, MemOperand(sp, arg_count * kPointerSize)); | 2860 __ ld(a1, MemOperand(sp, arg_count * kPointerSize)); |
2861 | 2861 |
2862 // Record call targets in unoptimized code. | 2862 // Record call targets in unoptimized code. |
2863 if (FLAG_pretenuring_call_new) { | 2863 if (FLAG_pretenuring_call_new) { |
2864 EnsureSlotContainsAllocationSite(expr->AllocationSiteFeedbackSlot()); | 2864 EnsureSlotContainsAllocationSite(expr->AllocationSiteFeedbackSlot()); |
2865 ASSERT(expr->AllocationSiteFeedbackSlot() == | 2865 DCHECK(expr->AllocationSiteFeedbackSlot() == |
2866 expr->CallNewFeedbackSlot() + 1); | 2866 expr->CallNewFeedbackSlot() + 1); |
2867 } | 2867 } |
2868 | 2868 |
2869 __ li(a2, FeedbackVector()); | 2869 __ li(a2, FeedbackVector()); |
2870 __ li(a3, Operand(Smi::FromInt(expr->CallNewFeedbackSlot()))); | 2870 __ li(a3, Operand(Smi::FromInt(expr->CallNewFeedbackSlot()))); |
2871 | 2871 |
2872 CallConstructStub stub(isolate(), RECORD_CONSTRUCTOR_TARGET); | 2872 CallConstructStub stub(isolate(), RECORD_CONSTRUCTOR_TARGET); |
2873 __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL); | 2873 __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL); |
2874 PrepareForBailoutForId(expr->ReturnId(), TOS_REG); | 2874 PrepareForBailoutForId(expr->ReturnId(), TOS_REG); |
2875 context()->Plug(v0); | 2875 context()->Plug(v0); |
2876 } | 2876 } |
2877 | 2877 |
2878 | 2878 |
2879 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { | 2879 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { |
2880 ZoneList<Expression*>* args = expr->arguments(); | 2880 ZoneList<Expression*>* args = expr->arguments(); |
2881 ASSERT(args->length() == 1); | 2881 DCHECK(args->length() == 1); |
2882 | 2882 |
2883 VisitForAccumulatorValue(args->at(0)); | 2883 VisitForAccumulatorValue(args->at(0)); |
2884 | 2884 |
2885 Label materialize_true, materialize_false; | 2885 Label materialize_true, materialize_false; |
2886 Label* if_true = NULL; | 2886 Label* if_true = NULL; |
2887 Label* if_false = NULL; | 2887 Label* if_false = NULL; |
2888 Label* fall_through = NULL; | 2888 Label* fall_through = NULL; |
2889 context()->PrepareTest(&materialize_true, &materialize_false, | 2889 context()->PrepareTest(&materialize_true, &materialize_false, |
2890 &if_true, &if_false, &fall_through); | 2890 &if_true, &if_false, &fall_through); |
2891 | 2891 |
2892 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 2892 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
2893 __ SmiTst(v0, a4); | 2893 __ SmiTst(v0, a4); |
2894 Split(eq, a4, Operand(zero_reg), if_true, if_false, fall_through); | 2894 Split(eq, a4, Operand(zero_reg), if_true, if_false, fall_through); |
2895 | 2895 |
2896 context()->Plug(if_true, if_false); | 2896 context()->Plug(if_true, if_false); |
2897 } | 2897 } |
2898 | 2898 |
2899 | 2899 |
2900 void FullCodeGenerator::EmitIsNonNegativeSmi(CallRuntime* expr) { | 2900 void FullCodeGenerator::EmitIsNonNegativeSmi(CallRuntime* expr) { |
2901 ZoneList<Expression*>* args = expr->arguments(); | 2901 ZoneList<Expression*>* args = expr->arguments(); |
2902 ASSERT(args->length() == 1); | 2902 DCHECK(args->length() == 1); |
2903 | 2903 |
2904 VisitForAccumulatorValue(args->at(0)); | 2904 VisitForAccumulatorValue(args->at(0)); |
2905 | 2905 |
2906 Label materialize_true, materialize_false; | 2906 Label materialize_true, materialize_false; |
2907 Label* if_true = NULL; | 2907 Label* if_true = NULL; |
2908 Label* if_false = NULL; | 2908 Label* if_false = NULL; |
2909 Label* fall_through = NULL; | 2909 Label* fall_through = NULL; |
2910 context()->PrepareTest(&materialize_true, &materialize_false, | 2910 context()->PrepareTest(&materialize_true, &materialize_false, |
2911 &if_true, &if_false, &fall_through); | 2911 &if_true, &if_false, &fall_through); |
2912 | 2912 |
2913 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 2913 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
2914 __ NonNegativeSmiTst(v0, at); | 2914 __ NonNegativeSmiTst(v0, at); |
2915 Split(eq, at, Operand(zero_reg), if_true, if_false, fall_through); | 2915 Split(eq, at, Operand(zero_reg), if_true, if_false, fall_through); |
2916 | 2916 |
2917 context()->Plug(if_true, if_false); | 2917 context()->Plug(if_true, if_false); |
2918 } | 2918 } |
2919 | 2919 |
2920 | 2920 |
2921 void FullCodeGenerator::EmitIsObject(CallRuntime* expr) { | 2921 void FullCodeGenerator::EmitIsObject(CallRuntime* expr) { |
2922 ZoneList<Expression*>* args = expr->arguments(); | 2922 ZoneList<Expression*>* args = expr->arguments(); |
2923 ASSERT(args->length() == 1); | 2923 DCHECK(args->length() == 1); |
2924 | 2924 |
2925 VisitForAccumulatorValue(args->at(0)); | 2925 VisitForAccumulatorValue(args->at(0)); |
2926 | 2926 |
2927 Label materialize_true, materialize_false; | 2927 Label materialize_true, materialize_false; |
2928 Label* if_true = NULL; | 2928 Label* if_true = NULL; |
2929 Label* if_false = NULL; | 2929 Label* if_false = NULL; |
2930 Label* fall_through = NULL; | 2930 Label* fall_through = NULL; |
2931 context()->PrepareTest(&materialize_true, &materialize_false, | 2931 context()->PrepareTest(&materialize_true, &materialize_false, |
2932 &if_true, &if_false, &fall_through); | 2932 &if_true, &if_false, &fall_through); |
2933 | 2933 |
(...skipping 10 matching lines...) Expand all Loading... |
2944 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 2944 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
2945 Split(le, a1, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE), | 2945 Split(le, a1, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE), |
2946 if_true, if_false, fall_through); | 2946 if_true, if_false, fall_through); |
2947 | 2947 |
2948 context()->Plug(if_true, if_false); | 2948 context()->Plug(if_true, if_false); |
2949 } | 2949 } |
2950 | 2950 |
2951 | 2951 |
2952 void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) { | 2952 void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) { |
2953 ZoneList<Expression*>* args = expr->arguments(); | 2953 ZoneList<Expression*>* args = expr->arguments(); |
2954 ASSERT(args->length() == 1); | 2954 DCHECK(args->length() == 1); |
2955 | 2955 |
2956 VisitForAccumulatorValue(args->at(0)); | 2956 VisitForAccumulatorValue(args->at(0)); |
2957 | 2957 |
2958 Label materialize_true, materialize_false; | 2958 Label materialize_true, materialize_false; |
2959 Label* if_true = NULL; | 2959 Label* if_true = NULL; |
2960 Label* if_false = NULL; | 2960 Label* if_false = NULL; |
2961 Label* fall_through = NULL; | 2961 Label* fall_through = NULL; |
2962 context()->PrepareTest(&materialize_true, &materialize_false, | 2962 context()->PrepareTest(&materialize_true, &materialize_false, |
2963 &if_true, &if_false, &fall_through); | 2963 &if_true, &if_false, &fall_through); |
2964 | 2964 |
2965 __ JumpIfSmi(v0, if_false); | 2965 __ JumpIfSmi(v0, if_false); |
2966 __ GetObjectType(v0, a1, a1); | 2966 __ GetObjectType(v0, a1, a1); |
2967 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 2967 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
2968 Split(ge, a1, Operand(FIRST_SPEC_OBJECT_TYPE), | 2968 Split(ge, a1, Operand(FIRST_SPEC_OBJECT_TYPE), |
2969 if_true, if_false, fall_through); | 2969 if_true, if_false, fall_through); |
2970 | 2970 |
2971 context()->Plug(if_true, if_false); | 2971 context()->Plug(if_true, if_false); |
2972 } | 2972 } |
2973 | 2973 |
2974 | 2974 |
2975 void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) { | 2975 void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) { |
2976 ZoneList<Expression*>* args = expr->arguments(); | 2976 ZoneList<Expression*>* args = expr->arguments(); |
2977 ASSERT(args->length() == 1); | 2977 DCHECK(args->length() == 1); |
2978 | 2978 |
2979 VisitForAccumulatorValue(args->at(0)); | 2979 VisitForAccumulatorValue(args->at(0)); |
2980 | 2980 |
2981 Label materialize_true, materialize_false; | 2981 Label materialize_true, materialize_false; |
2982 Label* if_true = NULL; | 2982 Label* if_true = NULL; |
2983 Label* if_false = NULL; | 2983 Label* if_false = NULL; |
2984 Label* fall_through = NULL; | 2984 Label* fall_through = NULL; |
2985 context()->PrepareTest(&materialize_true, &materialize_false, | 2985 context()->PrepareTest(&materialize_true, &materialize_false, |
2986 &if_true, &if_false, &fall_through); | 2986 &if_true, &if_false, &fall_through); |
2987 | 2987 |
2988 __ JumpIfSmi(v0, if_false); | 2988 __ JumpIfSmi(v0, if_false); |
2989 __ ld(a1, FieldMemOperand(v0, HeapObject::kMapOffset)); | 2989 __ ld(a1, FieldMemOperand(v0, HeapObject::kMapOffset)); |
2990 __ lbu(a1, FieldMemOperand(a1, Map::kBitFieldOffset)); | 2990 __ lbu(a1, FieldMemOperand(a1, Map::kBitFieldOffset)); |
2991 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 2991 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
2992 __ And(at, a1, Operand(1 << Map::kIsUndetectable)); | 2992 __ And(at, a1, Operand(1 << Map::kIsUndetectable)); |
2993 Split(ne, at, Operand(zero_reg), if_true, if_false, fall_through); | 2993 Split(ne, at, Operand(zero_reg), if_true, if_false, fall_through); |
2994 | 2994 |
2995 context()->Plug(if_true, if_false); | 2995 context()->Plug(if_true, if_false); |
2996 } | 2996 } |
2997 | 2997 |
2998 | 2998 |
2999 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( | 2999 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( |
3000 CallRuntime* expr) { | 3000 CallRuntime* expr) { |
3001 ZoneList<Expression*>* args = expr->arguments(); | 3001 ZoneList<Expression*>* args = expr->arguments(); |
3002 ASSERT(args->length() == 1); | 3002 DCHECK(args->length() == 1); |
3003 | 3003 |
3004 VisitForAccumulatorValue(args->at(0)); | 3004 VisitForAccumulatorValue(args->at(0)); |
3005 | 3005 |
3006 Label materialize_true, materialize_false, skip_lookup; | 3006 Label materialize_true, materialize_false, skip_lookup; |
3007 Label* if_true = NULL; | 3007 Label* if_true = NULL; |
3008 Label* if_false = NULL; | 3008 Label* if_false = NULL; |
3009 Label* fall_through = NULL; | 3009 Label* fall_through = NULL; |
3010 context()->PrepareTest(&materialize_true, &materialize_false, | 3010 context()->PrepareTest(&materialize_true, &materialize_false, |
3011 &if_true, &if_false, &fall_through); | 3011 &if_true, &if_false, &fall_through); |
3012 | 3012 |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3080 __ ld(a3, ContextOperand(a3, Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX)); | 3080 __ ld(a3, ContextOperand(a3, Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX)); |
3081 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 3081 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
3082 Split(eq, a2, Operand(a3), if_true, if_false, fall_through); | 3082 Split(eq, a2, Operand(a3), if_true, if_false, fall_through); |
3083 | 3083 |
3084 context()->Plug(if_true, if_false); | 3084 context()->Plug(if_true, if_false); |
3085 } | 3085 } |
3086 | 3086 |
3087 | 3087 |
3088 void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) { | 3088 void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) { |
3089 ZoneList<Expression*>* args = expr->arguments(); | 3089 ZoneList<Expression*>* args = expr->arguments(); |
3090 ASSERT(args->length() == 1); | 3090 DCHECK(args->length() == 1); |
3091 | 3091 |
3092 VisitForAccumulatorValue(args->at(0)); | 3092 VisitForAccumulatorValue(args->at(0)); |
3093 | 3093 |
3094 Label materialize_true, materialize_false; | 3094 Label materialize_true, materialize_false; |
3095 Label* if_true = NULL; | 3095 Label* if_true = NULL; |
3096 Label* if_false = NULL; | 3096 Label* if_false = NULL; |
3097 Label* fall_through = NULL; | 3097 Label* fall_through = NULL; |
3098 context()->PrepareTest(&materialize_true, &materialize_false, | 3098 context()->PrepareTest(&materialize_true, &materialize_false, |
3099 &if_true, &if_false, &fall_through); | 3099 &if_true, &if_false, &fall_through); |
3100 | 3100 |
3101 __ JumpIfSmi(v0, if_false); | 3101 __ JumpIfSmi(v0, if_false); |
3102 __ GetObjectType(v0, a1, a2); | 3102 __ GetObjectType(v0, a1, a2); |
3103 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 3103 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
3104 __ Branch(if_true, eq, a2, Operand(JS_FUNCTION_TYPE)); | 3104 __ Branch(if_true, eq, a2, Operand(JS_FUNCTION_TYPE)); |
3105 __ Branch(if_false); | 3105 __ Branch(if_false); |
3106 | 3106 |
3107 context()->Plug(if_true, if_false); | 3107 context()->Plug(if_true, if_false); |
3108 } | 3108 } |
3109 | 3109 |
3110 | 3110 |
3111 void FullCodeGenerator::EmitIsMinusZero(CallRuntime* expr) { | 3111 void FullCodeGenerator::EmitIsMinusZero(CallRuntime* expr) { |
3112 ZoneList<Expression*>* args = expr->arguments(); | 3112 ZoneList<Expression*>* args = expr->arguments(); |
3113 ASSERT(args->length() == 1); | 3113 DCHECK(args->length() == 1); |
3114 | 3114 |
3115 VisitForAccumulatorValue(args->at(0)); | 3115 VisitForAccumulatorValue(args->at(0)); |
3116 | 3116 |
3117 Label materialize_true, materialize_false; | 3117 Label materialize_true, materialize_false; |
3118 Label* if_true = NULL; | 3118 Label* if_true = NULL; |
3119 Label* if_false = NULL; | 3119 Label* if_false = NULL; |
3120 Label* fall_through = NULL; | 3120 Label* fall_through = NULL; |
3121 context()->PrepareTest(&materialize_true, &materialize_false, | 3121 context()->PrepareTest(&materialize_true, &materialize_false, |
3122 &if_true, &if_false, &fall_through); | 3122 &if_true, &if_false, &fall_through); |
3123 | 3123 |
3124 __ CheckMap(v0, a1, Heap::kHeapNumberMapRootIndex, if_false, DO_SMI_CHECK); | 3124 __ CheckMap(v0, a1, Heap::kHeapNumberMapRootIndex, if_false, DO_SMI_CHECK); |
3125 __ lwu(a2, FieldMemOperand(v0, HeapNumber::kExponentOffset)); | 3125 __ lwu(a2, FieldMemOperand(v0, HeapNumber::kExponentOffset)); |
3126 __ lwu(a1, FieldMemOperand(v0, HeapNumber::kMantissaOffset)); | 3126 __ lwu(a1, FieldMemOperand(v0, HeapNumber::kMantissaOffset)); |
3127 __ li(a4, 0x80000000); | 3127 __ li(a4, 0x80000000); |
3128 Label not_nan; | 3128 Label not_nan; |
3129 __ Branch(¬_nan, ne, a2, Operand(a4)); | 3129 __ Branch(¬_nan, ne, a2, Operand(a4)); |
3130 __ mov(a4, zero_reg); | 3130 __ mov(a4, zero_reg); |
3131 __ mov(a2, a1); | 3131 __ mov(a2, a1); |
3132 __ bind(¬_nan); | 3132 __ bind(¬_nan); |
3133 | 3133 |
3134 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 3134 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
3135 Split(eq, a2, Operand(a4), if_true, if_false, fall_through); | 3135 Split(eq, a2, Operand(a4), if_true, if_false, fall_through); |
3136 | 3136 |
3137 context()->Plug(if_true, if_false); | 3137 context()->Plug(if_true, if_false); |
3138 } | 3138 } |
3139 | 3139 |
3140 | 3140 |
3141 void FullCodeGenerator::EmitIsArray(CallRuntime* expr) { | 3141 void FullCodeGenerator::EmitIsArray(CallRuntime* expr) { |
3142 ZoneList<Expression*>* args = expr->arguments(); | 3142 ZoneList<Expression*>* args = expr->arguments(); |
3143 ASSERT(args->length() == 1); | 3143 DCHECK(args->length() == 1); |
3144 | 3144 |
3145 VisitForAccumulatorValue(args->at(0)); | 3145 VisitForAccumulatorValue(args->at(0)); |
3146 | 3146 |
3147 Label materialize_true, materialize_false; | 3147 Label materialize_true, materialize_false; |
3148 Label* if_true = NULL; | 3148 Label* if_true = NULL; |
3149 Label* if_false = NULL; | 3149 Label* if_false = NULL; |
3150 Label* fall_through = NULL; | 3150 Label* fall_through = NULL; |
3151 context()->PrepareTest(&materialize_true, &materialize_false, | 3151 context()->PrepareTest(&materialize_true, &materialize_false, |
3152 &if_true, &if_false, &fall_through); | 3152 &if_true, &if_false, &fall_through); |
3153 | 3153 |
3154 __ JumpIfSmi(v0, if_false); | 3154 __ JumpIfSmi(v0, if_false); |
3155 __ GetObjectType(v0, a1, a1); | 3155 __ GetObjectType(v0, a1, a1); |
3156 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 3156 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
3157 Split(eq, a1, Operand(JS_ARRAY_TYPE), | 3157 Split(eq, a1, Operand(JS_ARRAY_TYPE), |
3158 if_true, if_false, fall_through); | 3158 if_true, if_false, fall_through); |
3159 | 3159 |
3160 context()->Plug(if_true, if_false); | 3160 context()->Plug(if_true, if_false); |
3161 } | 3161 } |
3162 | 3162 |
3163 | 3163 |
3164 void FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) { | 3164 void FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) { |
3165 ZoneList<Expression*>* args = expr->arguments(); | 3165 ZoneList<Expression*>* args = expr->arguments(); |
3166 ASSERT(args->length() == 1); | 3166 DCHECK(args->length() == 1); |
3167 | 3167 |
3168 VisitForAccumulatorValue(args->at(0)); | 3168 VisitForAccumulatorValue(args->at(0)); |
3169 | 3169 |
3170 Label materialize_true, materialize_false; | 3170 Label materialize_true, materialize_false; |
3171 Label* if_true = NULL; | 3171 Label* if_true = NULL; |
3172 Label* if_false = NULL; | 3172 Label* if_false = NULL; |
3173 Label* fall_through = NULL; | 3173 Label* fall_through = NULL; |
3174 context()->PrepareTest(&materialize_true, &materialize_false, | 3174 context()->PrepareTest(&materialize_true, &materialize_false, |
3175 &if_true, &if_false, &fall_through); | 3175 &if_true, &if_false, &fall_through); |
3176 | 3176 |
3177 __ JumpIfSmi(v0, if_false); | 3177 __ JumpIfSmi(v0, if_false); |
3178 __ GetObjectType(v0, a1, a1); | 3178 __ GetObjectType(v0, a1, a1); |
3179 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 3179 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
3180 Split(eq, a1, Operand(JS_REGEXP_TYPE), if_true, if_false, fall_through); | 3180 Split(eq, a1, Operand(JS_REGEXP_TYPE), if_true, if_false, fall_through); |
3181 | 3181 |
3182 context()->Plug(if_true, if_false); | 3182 context()->Plug(if_true, if_false); |
3183 } | 3183 } |
3184 | 3184 |
3185 | 3185 |
3186 void FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) { | 3186 void FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) { |
3187 ASSERT(expr->arguments()->length() == 0); | 3187 DCHECK(expr->arguments()->length() == 0); |
3188 | 3188 |
3189 Label materialize_true, materialize_false; | 3189 Label materialize_true, materialize_false; |
3190 Label* if_true = NULL; | 3190 Label* if_true = NULL; |
3191 Label* if_false = NULL; | 3191 Label* if_false = NULL; |
3192 Label* fall_through = NULL; | 3192 Label* fall_through = NULL; |
3193 context()->PrepareTest(&materialize_true, &materialize_false, | 3193 context()->PrepareTest(&materialize_true, &materialize_false, |
3194 &if_true, &if_false, &fall_through); | 3194 &if_true, &if_false, &fall_through); |
3195 | 3195 |
3196 // Get the frame pointer for the calling frame. | 3196 // Get the frame pointer for the calling frame. |
3197 __ ld(a2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | 3197 __ ld(a2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
(...skipping 11 matching lines...) Expand all Loading... |
3209 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 3209 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
3210 Split(eq, a1, Operand(Smi::FromInt(StackFrame::CONSTRUCT)), | 3210 Split(eq, a1, Operand(Smi::FromInt(StackFrame::CONSTRUCT)), |
3211 if_true, if_false, fall_through); | 3211 if_true, if_false, fall_through); |
3212 | 3212 |
3213 context()->Plug(if_true, if_false); | 3213 context()->Plug(if_true, if_false); |
3214 } | 3214 } |
3215 | 3215 |
3216 | 3216 |
3217 void FullCodeGenerator::EmitObjectEquals(CallRuntime* expr) { | 3217 void FullCodeGenerator::EmitObjectEquals(CallRuntime* expr) { |
3218 ZoneList<Expression*>* args = expr->arguments(); | 3218 ZoneList<Expression*>* args = expr->arguments(); |
3219 ASSERT(args->length() == 2); | 3219 DCHECK(args->length() == 2); |
3220 | 3220 |
3221 // Load the two objects into registers and perform the comparison. | 3221 // Load the two objects into registers and perform the comparison. |
3222 VisitForStackValue(args->at(0)); | 3222 VisitForStackValue(args->at(0)); |
3223 VisitForAccumulatorValue(args->at(1)); | 3223 VisitForAccumulatorValue(args->at(1)); |
3224 | 3224 |
3225 Label materialize_true, materialize_false; | 3225 Label materialize_true, materialize_false; |
3226 Label* if_true = NULL; | 3226 Label* if_true = NULL; |
3227 Label* if_false = NULL; | 3227 Label* if_false = NULL; |
3228 Label* fall_through = NULL; | 3228 Label* fall_through = NULL; |
3229 context()->PrepareTest(&materialize_true, &materialize_false, | 3229 context()->PrepareTest(&materialize_true, &materialize_false, |
3230 &if_true, &if_false, &fall_through); | 3230 &if_true, &if_false, &fall_through); |
3231 | 3231 |
3232 __ pop(a1); | 3232 __ pop(a1); |
3233 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 3233 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
3234 Split(eq, v0, Operand(a1), if_true, if_false, fall_through); | 3234 Split(eq, v0, Operand(a1), if_true, if_false, fall_through); |
3235 | 3235 |
3236 context()->Plug(if_true, if_false); | 3236 context()->Plug(if_true, if_false); |
3237 } | 3237 } |
3238 | 3238 |
3239 | 3239 |
3240 void FullCodeGenerator::EmitArguments(CallRuntime* expr) { | 3240 void FullCodeGenerator::EmitArguments(CallRuntime* expr) { |
3241 ZoneList<Expression*>* args = expr->arguments(); | 3241 ZoneList<Expression*>* args = expr->arguments(); |
3242 ASSERT(args->length() == 1); | 3242 DCHECK(args->length() == 1); |
3243 | 3243 |
3244 // ArgumentsAccessStub expects the key in a1 and the formal | 3244 // ArgumentsAccessStub expects the key in a1 and the formal |
3245 // parameter count in a0. | 3245 // parameter count in a0. |
3246 VisitForAccumulatorValue(args->at(0)); | 3246 VisitForAccumulatorValue(args->at(0)); |
3247 __ mov(a1, v0); | 3247 __ mov(a1, v0); |
3248 __ li(a0, Operand(Smi::FromInt(info_->scope()->num_parameters()))); | 3248 __ li(a0, Operand(Smi::FromInt(info_->scope()->num_parameters()))); |
3249 ArgumentsAccessStub stub(isolate(), ArgumentsAccessStub::READ_ELEMENT); | 3249 ArgumentsAccessStub stub(isolate(), ArgumentsAccessStub::READ_ELEMENT); |
3250 __ CallStub(&stub); | 3250 __ CallStub(&stub); |
3251 context()->Plug(v0); | 3251 context()->Plug(v0); |
3252 } | 3252 } |
3253 | 3253 |
3254 | 3254 |
3255 void FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) { | 3255 void FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) { |
3256 ASSERT(expr->arguments()->length() == 0); | 3256 DCHECK(expr->arguments()->length() == 0); |
3257 Label exit; | 3257 Label exit; |
3258 // Get the number of formal parameters. | 3258 // Get the number of formal parameters. |
3259 __ li(v0, Operand(Smi::FromInt(info_->scope()->num_parameters()))); | 3259 __ li(v0, Operand(Smi::FromInt(info_->scope()->num_parameters()))); |
3260 | 3260 |
3261 // Check if the calling frame is an arguments adaptor frame. | 3261 // Check if the calling frame is an arguments adaptor frame. |
3262 __ ld(a2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | 3262 __ ld(a2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
3263 __ ld(a3, MemOperand(a2, StandardFrameConstants::kContextOffset)); | 3263 __ ld(a3, MemOperand(a2, StandardFrameConstants::kContextOffset)); |
3264 __ Branch(&exit, ne, a3, | 3264 __ Branch(&exit, ne, a3, |
3265 Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 3265 Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
3266 | 3266 |
3267 // Arguments adaptor case: Read the arguments length from the | 3267 // Arguments adaptor case: Read the arguments length from the |
3268 // adaptor frame. | 3268 // adaptor frame. |
3269 __ ld(v0, MemOperand(a2, ArgumentsAdaptorFrameConstants::kLengthOffset)); | 3269 __ ld(v0, MemOperand(a2, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
3270 | 3270 |
3271 __ bind(&exit); | 3271 __ bind(&exit); |
3272 context()->Plug(v0); | 3272 context()->Plug(v0); |
3273 } | 3273 } |
3274 | 3274 |
3275 | 3275 |
3276 void FullCodeGenerator::EmitClassOf(CallRuntime* expr) { | 3276 void FullCodeGenerator::EmitClassOf(CallRuntime* expr) { |
3277 ZoneList<Expression*>* args = expr->arguments(); | 3277 ZoneList<Expression*>* args = expr->arguments(); |
3278 ASSERT(args->length() == 1); | 3278 DCHECK(args->length() == 1); |
3279 Label done, null, function, non_function_constructor; | 3279 Label done, null, function, non_function_constructor; |
3280 | 3280 |
3281 VisitForAccumulatorValue(args->at(0)); | 3281 VisitForAccumulatorValue(args->at(0)); |
3282 | 3282 |
3283 // If the object is a smi, we return null. | 3283 // If the object is a smi, we return null. |
3284 __ JumpIfSmi(v0, &null); | 3284 __ JumpIfSmi(v0, &null); |
3285 | 3285 |
3286 // Check that the object is a JS object but take special care of JS | 3286 // Check that the object is a JS object but take special care of JS |
3287 // functions to make sure they have 'Function' as their class. | 3287 // functions to make sure they have 'Function' as their class. |
3288 // Assume that there are only two callable types, and one of them is at | 3288 // Assume that there are only two callable types, and one of them is at |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3330 __ bind(&done); | 3330 __ bind(&done); |
3331 | 3331 |
3332 context()->Plug(v0); | 3332 context()->Plug(v0); |
3333 } | 3333 } |
3334 | 3334 |
3335 | 3335 |
3336 void FullCodeGenerator::EmitSubString(CallRuntime* expr) { | 3336 void FullCodeGenerator::EmitSubString(CallRuntime* expr) { |
3337 // Load the arguments on the stack and call the stub. | 3337 // Load the arguments on the stack and call the stub. |
3338 SubStringStub stub(isolate()); | 3338 SubStringStub stub(isolate()); |
3339 ZoneList<Expression*>* args = expr->arguments(); | 3339 ZoneList<Expression*>* args = expr->arguments(); |
3340 ASSERT(args->length() == 3); | 3340 DCHECK(args->length() == 3); |
3341 VisitForStackValue(args->at(0)); | 3341 VisitForStackValue(args->at(0)); |
3342 VisitForStackValue(args->at(1)); | 3342 VisitForStackValue(args->at(1)); |
3343 VisitForStackValue(args->at(2)); | 3343 VisitForStackValue(args->at(2)); |
3344 __ CallStub(&stub); | 3344 __ CallStub(&stub); |
3345 context()->Plug(v0); | 3345 context()->Plug(v0); |
3346 } | 3346 } |
3347 | 3347 |
3348 | 3348 |
3349 void FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) { | 3349 void FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) { |
3350 // Load the arguments on the stack and call the stub. | 3350 // Load the arguments on the stack and call the stub. |
3351 RegExpExecStub stub(isolate()); | 3351 RegExpExecStub stub(isolate()); |
3352 ZoneList<Expression*>* args = expr->arguments(); | 3352 ZoneList<Expression*>* args = expr->arguments(); |
3353 ASSERT(args->length() == 4); | 3353 DCHECK(args->length() == 4); |
3354 VisitForStackValue(args->at(0)); | 3354 VisitForStackValue(args->at(0)); |
3355 VisitForStackValue(args->at(1)); | 3355 VisitForStackValue(args->at(1)); |
3356 VisitForStackValue(args->at(2)); | 3356 VisitForStackValue(args->at(2)); |
3357 VisitForStackValue(args->at(3)); | 3357 VisitForStackValue(args->at(3)); |
3358 __ CallStub(&stub); | 3358 __ CallStub(&stub); |
3359 context()->Plug(v0); | 3359 context()->Plug(v0); |
3360 } | 3360 } |
3361 | 3361 |
3362 | 3362 |
3363 void FullCodeGenerator::EmitValueOf(CallRuntime* expr) { | 3363 void FullCodeGenerator::EmitValueOf(CallRuntime* expr) { |
3364 ZoneList<Expression*>* args = expr->arguments(); | 3364 ZoneList<Expression*>* args = expr->arguments(); |
3365 ASSERT(args->length() == 1); | 3365 DCHECK(args->length() == 1); |
3366 | 3366 |
3367 VisitForAccumulatorValue(args->at(0)); // Load the object. | 3367 VisitForAccumulatorValue(args->at(0)); // Load the object. |
3368 | 3368 |
3369 Label done; | 3369 Label done; |
3370 // If the object is a smi return the object. | 3370 // If the object is a smi return the object. |
3371 __ JumpIfSmi(v0, &done); | 3371 __ JumpIfSmi(v0, &done); |
3372 // If the object is not a value type, return the object. | 3372 // If the object is not a value type, return the object. |
3373 __ GetObjectType(v0, a1, a1); | 3373 __ GetObjectType(v0, a1, a1); |
3374 __ Branch(&done, ne, a1, Operand(JS_VALUE_TYPE)); | 3374 __ Branch(&done, ne, a1, Operand(JS_VALUE_TYPE)); |
3375 | 3375 |
3376 __ ld(v0, FieldMemOperand(v0, JSValue::kValueOffset)); | 3376 __ ld(v0, FieldMemOperand(v0, JSValue::kValueOffset)); |
3377 | 3377 |
3378 __ bind(&done); | 3378 __ bind(&done); |
3379 context()->Plug(v0); | 3379 context()->Plug(v0); |
3380 } | 3380 } |
3381 | 3381 |
3382 | 3382 |
3383 void FullCodeGenerator::EmitDateField(CallRuntime* expr) { | 3383 void FullCodeGenerator::EmitDateField(CallRuntime* expr) { |
3384 ZoneList<Expression*>* args = expr->arguments(); | 3384 ZoneList<Expression*>* args = expr->arguments(); |
3385 ASSERT(args->length() == 2); | 3385 DCHECK(args->length() == 2); |
3386 ASSERT_NE(NULL, args->at(1)->AsLiteral()); | 3386 DCHECK_NE(NULL, args->at(1)->AsLiteral()); |
3387 Smi* index = Smi::cast(*(args->at(1)->AsLiteral()->value())); | 3387 Smi* index = Smi::cast(*(args->at(1)->AsLiteral()->value())); |
3388 | 3388 |
3389 VisitForAccumulatorValue(args->at(0)); // Load the object. | 3389 VisitForAccumulatorValue(args->at(0)); // Load the object. |
3390 | 3390 |
3391 Label runtime, done, not_date_object; | 3391 Label runtime, done, not_date_object; |
3392 Register object = v0; | 3392 Register object = v0; |
3393 Register result = v0; | 3393 Register result = v0; |
3394 Register scratch0 = t1; | 3394 Register scratch0 = t1; |
3395 Register scratch1 = a1; | 3395 Register scratch1 = a1; |
3396 | 3396 |
(...skipping 25 matching lines...) Expand all Loading... |
3422 | 3422 |
3423 __ bind(¬_date_object); | 3423 __ bind(¬_date_object); |
3424 __ CallRuntime(Runtime::kThrowNotDateError, 0); | 3424 __ CallRuntime(Runtime::kThrowNotDateError, 0); |
3425 __ bind(&done); | 3425 __ bind(&done); |
3426 context()->Plug(v0); | 3426 context()->Plug(v0); |
3427 } | 3427 } |
3428 | 3428 |
3429 | 3429 |
3430 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) { | 3430 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) { |
3431 ZoneList<Expression*>* args = expr->arguments(); | 3431 ZoneList<Expression*>* args = expr->arguments(); |
3432 ASSERT_EQ(3, args->length()); | 3432 DCHECK_EQ(3, args->length()); |
3433 | 3433 |
3434 Register string = v0; | 3434 Register string = v0; |
3435 Register index = a1; | 3435 Register index = a1; |
3436 Register value = a2; | 3436 Register value = a2; |
3437 | 3437 |
3438 VisitForStackValue(args->at(1)); // index | 3438 VisitForStackValue(args->at(1)); // index |
3439 VisitForStackValue(args->at(2)); // value | 3439 VisitForStackValue(args->at(2)); // value |
3440 VisitForAccumulatorValue(args->at(0)); // string | 3440 VisitForAccumulatorValue(args->at(0)); // string |
3441 __ Pop(index, value); | 3441 __ Pop(index, value); |
3442 | 3442 |
(...skipping 16 matching lines...) Expand all Loading... |
3459 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); | 3459 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); |
3460 __ SmiUntag(index); | 3460 __ SmiUntag(index); |
3461 __ Daddu(at, at, index); | 3461 __ Daddu(at, at, index); |
3462 __ sb(value, MemOperand(at)); | 3462 __ sb(value, MemOperand(at)); |
3463 context()->Plug(string); | 3463 context()->Plug(string); |
3464 } | 3464 } |
3465 | 3465 |
3466 | 3466 |
3467 void FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) { | 3467 void FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) { |
3468 ZoneList<Expression*>* args = expr->arguments(); | 3468 ZoneList<Expression*>* args = expr->arguments(); |
3469 ASSERT_EQ(3, args->length()); | 3469 DCHECK_EQ(3, args->length()); |
3470 | 3470 |
3471 Register string = v0; | 3471 Register string = v0; |
3472 Register index = a1; | 3472 Register index = a1; |
3473 Register value = a2; | 3473 Register value = a2; |
3474 | 3474 |
3475 VisitForStackValue(args->at(1)); // index | 3475 VisitForStackValue(args->at(1)); // index |
3476 VisitForStackValue(args->at(2)); // value | 3476 VisitForStackValue(args->at(2)); // value |
3477 VisitForAccumulatorValue(args->at(0)); // string | 3477 VisitForAccumulatorValue(args->at(0)); // string |
3478 __ Pop(index, value); | 3478 __ Pop(index, value); |
3479 | 3479 |
(...skipping 18 matching lines...) Expand all Loading... |
3498 __ Daddu(at, at, index); | 3498 __ Daddu(at, at, index); |
3499 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); | 3499 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); |
3500 __ sh(value, MemOperand(at)); | 3500 __ sh(value, MemOperand(at)); |
3501 context()->Plug(string); | 3501 context()->Plug(string); |
3502 } | 3502 } |
3503 | 3503 |
3504 | 3504 |
3505 void FullCodeGenerator::EmitMathPow(CallRuntime* expr) { | 3505 void FullCodeGenerator::EmitMathPow(CallRuntime* expr) { |
3506 // Load the arguments on the stack and call the runtime function. | 3506 // Load the arguments on the stack and call the runtime function. |
3507 ZoneList<Expression*>* args = expr->arguments(); | 3507 ZoneList<Expression*>* args = expr->arguments(); |
3508 ASSERT(args->length() == 2); | 3508 DCHECK(args->length() == 2); |
3509 VisitForStackValue(args->at(0)); | 3509 VisitForStackValue(args->at(0)); |
3510 VisitForStackValue(args->at(1)); | 3510 VisitForStackValue(args->at(1)); |
3511 MathPowStub stub(isolate(), MathPowStub::ON_STACK); | 3511 MathPowStub stub(isolate(), MathPowStub::ON_STACK); |
3512 __ CallStub(&stub); | 3512 __ CallStub(&stub); |
3513 context()->Plug(v0); | 3513 context()->Plug(v0); |
3514 } | 3514 } |
3515 | 3515 |
3516 | 3516 |
3517 void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) { | 3517 void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) { |
3518 ZoneList<Expression*>* args = expr->arguments(); | 3518 ZoneList<Expression*>* args = expr->arguments(); |
3519 ASSERT(args->length() == 2); | 3519 DCHECK(args->length() == 2); |
3520 | 3520 |
3521 VisitForStackValue(args->at(0)); // Load the object. | 3521 VisitForStackValue(args->at(0)); // Load the object. |
3522 VisitForAccumulatorValue(args->at(1)); // Load the value. | 3522 VisitForAccumulatorValue(args->at(1)); // Load the value. |
3523 __ pop(a1); // v0 = value. a1 = object. | 3523 __ pop(a1); // v0 = value. a1 = object. |
3524 | 3524 |
3525 Label done; | 3525 Label done; |
3526 // If the object is a smi, return the value. | 3526 // If the object is a smi, return the value. |
3527 __ JumpIfSmi(a1, &done); | 3527 __ JumpIfSmi(a1, &done); |
3528 | 3528 |
3529 // If the object is not a value type, return the value. | 3529 // If the object is not a value type, return the value. |
3530 __ GetObjectType(a1, a2, a2); | 3530 __ GetObjectType(a1, a2, a2); |
3531 __ Branch(&done, ne, a2, Operand(JS_VALUE_TYPE)); | 3531 __ Branch(&done, ne, a2, Operand(JS_VALUE_TYPE)); |
3532 | 3532 |
3533 // Store the value. | 3533 // Store the value. |
3534 __ sd(v0, FieldMemOperand(a1, JSValue::kValueOffset)); | 3534 __ sd(v0, FieldMemOperand(a1, JSValue::kValueOffset)); |
3535 // Update the write barrier. Save the value as it will be | 3535 // Update the write barrier. Save the value as it will be |
3536 // overwritten by the write barrier code and is needed afterward. | 3536 // overwritten by the write barrier code and is needed afterward. |
3537 __ mov(a2, v0); | 3537 __ mov(a2, v0); |
3538 __ RecordWriteField( | 3538 __ RecordWriteField( |
3539 a1, JSValue::kValueOffset, a2, a3, kRAHasBeenSaved, kDontSaveFPRegs); | 3539 a1, JSValue::kValueOffset, a2, a3, kRAHasBeenSaved, kDontSaveFPRegs); |
3540 | 3540 |
3541 __ bind(&done); | 3541 __ bind(&done); |
3542 context()->Plug(v0); | 3542 context()->Plug(v0); |
3543 } | 3543 } |
3544 | 3544 |
3545 | 3545 |
3546 void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) { | 3546 void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) { |
3547 ZoneList<Expression*>* args = expr->arguments(); | 3547 ZoneList<Expression*>* args = expr->arguments(); |
3548 ASSERT_EQ(args->length(), 1); | 3548 DCHECK_EQ(args->length(), 1); |
3549 | 3549 |
3550 // Load the argument into a0 and call the stub. | 3550 // Load the argument into a0 and call the stub. |
3551 VisitForAccumulatorValue(args->at(0)); | 3551 VisitForAccumulatorValue(args->at(0)); |
3552 __ mov(a0, result_register()); | 3552 __ mov(a0, result_register()); |
3553 | 3553 |
3554 NumberToStringStub stub(isolate()); | 3554 NumberToStringStub stub(isolate()); |
3555 __ CallStub(&stub); | 3555 __ CallStub(&stub); |
3556 context()->Plug(v0); | 3556 context()->Plug(v0); |
3557 } | 3557 } |
3558 | 3558 |
3559 | 3559 |
3560 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) { | 3560 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) { |
3561 ZoneList<Expression*>* args = expr->arguments(); | 3561 ZoneList<Expression*>* args = expr->arguments(); |
3562 ASSERT(args->length() == 1); | 3562 DCHECK(args->length() == 1); |
3563 | 3563 |
3564 VisitForAccumulatorValue(args->at(0)); | 3564 VisitForAccumulatorValue(args->at(0)); |
3565 | 3565 |
3566 Label done; | 3566 Label done; |
3567 StringCharFromCodeGenerator generator(v0, a1); | 3567 StringCharFromCodeGenerator generator(v0, a1); |
3568 generator.GenerateFast(masm_); | 3568 generator.GenerateFast(masm_); |
3569 __ jmp(&done); | 3569 __ jmp(&done); |
3570 | 3570 |
3571 NopRuntimeCallHelper call_helper; | 3571 NopRuntimeCallHelper call_helper; |
3572 generator.GenerateSlow(masm_, call_helper); | 3572 generator.GenerateSlow(masm_, call_helper); |
3573 | 3573 |
3574 __ bind(&done); | 3574 __ bind(&done); |
3575 context()->Plug(a1); | 3575 context()->Plug(a1); |
3576 } | 3576 } |
3577 | 3577 |
3578 | 3578 |
3579 void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) { | 3579 void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) { |
3580 ZoneList<Expression*>* args = expr->arguments(); | 3580 ZoneList<Expression*>* args = expr->arguments(); |
3581 ASSERT(args->length() == 2); | 3581 DCHECK(args->length() == 2); |
3582 | 3582 |
3583 VisitForStackValue(args->at(0)); | 3583 VisitForStackValue(args->at(0)); |
3584 VisitForAccumulatorValue(args->at(1)); | 3584 VisitForAccumulatorValue(args->at(1)); |
3585 __ mov(a0, result_register()); | 3585 __ mov(a0, result_register()); |
3586 | 3586 |
3587 Register object = a1; | 3587 Register object = a1; |
3588 Register index = a0; | 3588 Register index = a0; |
3589 Register result = v0; | 3589 Register result = v0; |
3590 | 3590 |
3591 __ pop(object); | 3591 __ pop(object); |
(...skipping 26 matching lines...) Expand all Loading... |
3618 NopRuntimeCallHelper call_helper; | 3618 NopRuntimeCallHelper call_helper; |
3619 generator.GenerateSlow(masm_, call_helper); | 3619 generator.GenerateSlow(masm_, call_helper); |
3620 | 3620 |
3621 __ bind(&done); | 3621 __ bind(&done); |
3622 context()->Plug(result); | 3622 context()->Plug(result); |
3623 } | 3623 } |
3624 | 3624 |
3625 | 3625 |
3626 void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) { | 3626 void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) { |
3627 ZoneList<Expression*>* args = expr->arguments(); | 3627 ZoneList<Expression*>* args = expr->arguments(); |
3628 ASSERT(args->length() == 2); | 3628 DCHECK(args->length() == 2); |
3629 | 3629 |
3630 VisitForStackValue(args->at(0)); | 3630 VisitForStackValue(args->at(0)); |
3631 VisitForAccumulatorValue(args->at(1)); | 3631 VisitForAccumulatorValue(args->at(1)); |
3632 __ mov(a0, result_register()); | 3632 __ mov(a0, result_register()); |
3633 | 3633 |
3634 Register object = a1; | 3634 Register object = a1; |
3635 Register index = a0; | 3635 Register index = a0; |
3636 Register scratch = a3; | 3636 Register scratch = a3; |
3637 Register result = v0; | 3637 Register result = v0; |
3638 | 3638 |
(...skipping 28 matching lines...) Expand all Loading... |
3667 NopRuntimeCallHelper call_helper; | 3667 NopRuntimeCallHelper call_helper; |
3668 generator.GenerateSlow(masm_, call_helper); | 3668 generator.GenerateSlow(masm_, call_helper); |
3669 | 3669 |
3670 __ bind(&done); | 3670 __ bind(&done); |
3671 context()->Plug(result); | 3671 context()->Plug(result); |
3672 } | 3672 } |
3673 | 3673 |
3674 | 3674 |
3675 void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) { | 3675 void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) { |
3676 ZoneList<Expression*>* args = expr->arguments(); | 3676 ZoneList<Expression*>* args = expr->arguments(); |
3677 ASSERT_EQ(2, args->length()); | 3677 DCHECK_EQ(2, args->length()); |
3678 VisitForStackValue(args->at(0)); | 3678 VisitForStackValue(args->at(0)); |
3679 VisitForAccumulatorValue(args->at(1)); | 3679 VisitForAccumulatorValue(args->at(1)); |
3680 | 3680 |
3681 __ pop(a1); | 3681 __ pop(a1); |
3682 __ mov(a0, result_register()); // StringAddStub requires args in a0, a1. | 3682 __ mov(a0, result_register()); // StringAddStub requires args in a0, a1. |
3683 StringAddStub stub(isolate(), STRING_ADD_CHECK_BOTH, NOT_TENURED); | 3683 StringAddStub stub(isolate(), STRING_ADD_CHECK_BOTH, NOT_TENURED); |
3684 __ CallStub(&stub); | 3684 __ CallStub(&stub); |
3685 context()->Plug(v0); | 3685 context()->Plug(v0); |
3686 } | 3686 } |
3687 | 3687 |
3688 | 3688 |
3689 void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) { | 3689 void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) { |
3690 ZoneList<Expression*>* args = expr->arguments(); | 3690 ZoneList<Expression*>* args = expr->arguments(); |
3691 ASSERT_EQ(2, args->length()); | 3691 DCHECK_EQ(2, args->length()); |
3692 | 3692 |
3693 VisitForStackValue(args->at(0)); | 3693 VisitForStackValue(args->at(0)); |
3694 VisitForStackValue(args->at(1)); | 3694 VisitForStackValue(args->at(1)); |
3695 | 3695 |
3696 StringCompareStub stub(isolate()); | 3696 StringCompareStub stub(isolate()); |
3697 __ CallStub(&stub); | 3697 __ CallStub(&stub); |
3698 context()->Plug(v0); | 3698 context()->Plug(v0); |
3699 } | 3699 } |
3700 | 3700 |
3701 | 3701 |
3702 void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) { | 3702 void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) { |
3703 ZoneList<Expression*>* args = expr->arguments(); | 3703 ZoneList<Expression*>* args = expr->arguments(); |
3704 ASSERT(args->length() >= 2); | 3704 DCHECK(args->length() >= 2); |
3705 | 3705 |
3706 int arg_count = args->length() - 2; // 2 ~ receiver and function. | 3706 int arg_count = args->length() - 2; // 2 ~ receiver and function. |
3707 for (int i = 0; i < arg_count + 1; i++) { | 3707 for (int i = 0; i < arg_count + 1; i++) { |
3708 VisitForStackValue(args->at(i)); | 3708 VisitForStackValue(args->at(i)); |
3709 } | 3709 } |
3710 VisitForAccumulatorValue(args->last()); // Function. | 3710 VisitForAccumulatorValue(args->last()); // Function. |
3711 | 3711 |
3712 Label runtime, done; | 3712 Label runtime, done; |
3713 // Check for non-function argument (including proxy). | 3713 // Check for non-function argument (including proxy). |
3714 __ JumpIfSmi(v0, &runtime); | 3714 __ JumpIfSmi(v0, &runtime); |
(...skipping 12 matching lines...) Expand all Loading... |
3727 __ CallRuntime(Runtime::kCall, args->length()); | 3727 __ CallRuntime(Runtime::kCall, args->length()); |
3728 __ bind(&done); | 3728 __ bind(&done); |
3729 | 3729 |
3730 context()->Plug(v0); | 3730 context()->Plug(v0); |
3731 } | 3731 } |
3732 | 3732 |
3733 | 3733 |
3734 void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) { | 3734 void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) { |
3735 RegExpConstructResultStub stub(isolate()); | 3735 RegExpConstructResultStub stub(isolate()); |
3736 ZoneList<Expression*>* args = expr->arguments(); | 3736 ZoneList<Expression*>* args = expr->arguments(); |
3737 ASSERT(args->length() == 3); | 3737 DCHECK(args->length() == 3); |
3738 VisitForStackValue(args->at(0)); | 3738 VisitForStackValue(args->at(0)); |
3739 VisitForStackValue(args->at(1)); | 3739 VisitForStackValue(args->at(1)); |
3740 VisitForAccumulatorValue(args->at(2)); | 3740 VisitForAccumulatorValue(args->at(2)); |
3741 __ mov(a0, result_register()); | 3741 __ mov(a0, result_register()); |
3742 __ pop(a1); | 3742 __ pop(a1); |
3743 __ pop(a2); | 3743 __ pop(a2); |
3744 __ CallStub(&stub); | 3744 __ CallStub(&stub); |
3745 context()->Plug(v0); | 3745 context()->Plug(v0); |
3746 } | 3746 } |
3747 | 3747 |
3748 | 3748 |
3749 void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) { | 3749 void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) { |
3750 ZoneList<Expression*>* args = expr->arguments(); | 3750 ZoneList<Expression*>* args = expr->arguments(); |
3751 ASSERT_EQ(2, args->length()); | 3751 DCHECK_EQ(2, args->length()); |
3752 | 3752 |
3753 ASSERT_NE(NULL, args->at(0)->AsLiteral()); | 3753 DCHECK_NE(NULL, args->at(0)->AsLiteral()); |
3754 int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->value()))->value(); | 3754 int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->value()))->value(); |
3755 | 3755 |
3756 Handle<FixedArray> jsfunction_result_caches( | 3756 Handle<FixedArray> jsfunction_result_caches( |
3757 isolate()->native_context()->jsfunction_result_caches()); | 3757 isolate()->native_context()->jsfunction_result_caches()); |
3758 if (jsfunction_result_caches->length() <= cache_id) { | 3758 if (jsfunction_result_caches->length() <= cache_id) { |
3759 __ Abort(kAttemptToUseUndefinedCache); | 3759 __ Abort(kAttemptToUseUndefinedCache); |
3760 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex); | 3760 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex); |
3761 context()->Plug(v0); | 3761 context()->Plug(v0); |
3762 return; | 3762 return; |
3763 } | 3763 } |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3816 | 3816 |
3817 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 3817 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
3818 Split(eq, a0, Operand(zero_reg), if_true, if_false, fall_through); | 3818 Split(eq, a0, Operand(zero_reg), if_true, if_false, fall_through); |
3819 | 3819 |
3820 context()->Plug(if_true, if_false); | 3820 context()->Plug(if_true, if_false); |
3821 } | 3821 } |
3822 | 3822 |
3823 | 3823 |
3824 void FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) { | 3824 void FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) { |
3825 ZoneList<Expression*>* args = expr->arguments(); | 3825 ZoneList<Expression*>* args = expr->arguments(); |
3826 ASSERT(args->length() == 1); | 3826 DCHECK(args->length() == 1); |
3827 VisitForAccumulatorValue(args->at(0)); | 3827 VisitForAccumulatorValue(args->at(0)); |
3828 | 3828 |
3829 __ AssertString(v0); | 3829 __ AssertString(v0); |
3830 | 3830 |
3831 __ lwu(v0, FieldMemOperand(v0, String::kHashFieldOffset)); | 3831 __ lwu(v0, FieldMemOperand(v0, String::kHashFieldOffset)); |
3832 __ IndexFromHash(v0, v0); | 3832 __ IndexFromHash(v0, v0); |
3833 | 3833 |
3834 context()->Plug(v0); | 3834 context()->Plug(v0); |
3835 } | 3835 } |
3836 | 3836 |
3837 | 3837 |
3838 void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) { | 3838 void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) { |
3839 Label bailout, done, one_char_separator, long_separator, | 3839 Label bailout, done, one_char_separator, long_separator, |
3840 non_trivial_array, not_size_one_array, loop, | 3840 non_trivial_array, not_size_one_array, loop, |
3841 empty_separator_loop, one_char_separator_loop, | 3841 empty_separator_loop, one_char_separator_loop, |
3842 one_char_separator_loop_entry, long_separator_loop; | 3842 one_char_separator_loop_entry, long_separator_loop; |
3843 ZoneList<Expression*>* args = expr->arguments(); | 3843 ZoneList<Expression*>* args = expr->arguments(); |
3844 ASSERT(args->length() == 2); | 3844 DCHECK(args->length() == 2); |
3845 VisitForStackValue(args->at(1)); | 3845 VisitForStackValue(args->at(1)); |
3846 VisitForAccumulatorValue(args->at(0)); | 3846 VisitForAccumulatorValue(args->at(0)); |
3847 | 3847 |
3848 // All aliases of the same register have disjoint lifetimes. | 3848 // All aliases of the same register have disjoint lifetimes. |
3849 Register array = v0; | 3849 Register array = v0; |
3850 Register elements = no_reg; // Will be v0. | 3850 Register elements = no_reg; // Will be v0. |
3851 Register result = no_reg; // Will be v0. | 3851 Register result = no_reg; // Will be v0. |
3852 Register separator = a1; | 3852 Register separator = a1; |
3853 Register array_length = a2; | 3853 Register array_length = a2; |
3854 Register result_pos = no_reg; // Will be a2. | 3854 Register result_pos = no_reg; // Will be a2. |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3993 | 3993 |
3994 // Copy next array element to the result. | 3994 // Copy next array element to the result. |
3995 __ ld(string, MemOperand(element)); | 3995 __ ld(string, MemOperand(element)); |
3996 __ Daddu(element, element, kPointerSize); | 3996 __ Daddu(element, element, kPointerSize); |
3997 __ ld(string_length, FieldMemOperand(string, String::kLengthOffset)); | 3997 __ ld(string_length, FieldMemOperand(string, String::kLengthOffset)); |
3998 __ SmiUntag(string_length); | 3998 __ SmiUntag(string_length); |
3999 __ Daddu(string, string, SeqOneByteString::kHeaderSize - kHeapObjectTag); | 3999 __ Daddu(string, string, SeqOneByteString::kHeaderSize - kHeapObjectTag); |
4000 __ CopyBytes(string, result_pos, string_length, scratch1); | 4000 __ CopyBytes(string, result_pos, string_length, scratch1); |
4001 // End while (element < elements_end). | 4001 // End while (element < elements_end). |
4002 __ Branch(&empty_separator_loop, lt, element, Operand(elements_end)); | 4002 __ Branch(&empty_separator_loop, lt, element, Operand(elements_end)); |
4003 ASSERT(result.is(v0)); | 4003 DCHECK(result.is(v0)); |
4004 __ Branch(&done); | 4004 __ Branch(&done); |
4005 | 4005 |
4006 // One-character separator case. | 4006 // One-character separator case. |
4007 __ bind(&one_char_separator); | 4007 __ bind(&one_char_separator); |
4008 // Replace separator with its ASCII character value. | 4008 // Replace separator with its ASCII character value. |
4009 __ lbu(separator, FieldMemOperand(separator, SeqOneByteString::kHeaderSize)); | 4009 __ lbu(separator, FieldMemOperand(separator, SeqOneByteString::kHeaderSize)); |
4010 // Jump into the loop after the code that copies the separator, so the first | 4010 // Jump into the loop after the code that copies the separator, so the first |
4011 // element is not preceded by a separator. | 4011 // element is not preceded by a separator. |
4012 __ jmp(&one_char_separator_loop_entry); | 4012 __ jmp(&one_char_separator_loop_entry); |
4013 | 4013 |
(...skipping 11 matching lines...) Expand all Loading... |
4025 // Copy next array element to the result. | 4025 // Copy next array element to the result. |
4026 __ bind(&one_char_separator_loop_entry); | 4026 __ bind(&one_char_separator_loop_entry); |
4027 __ ld(string, MemOperand(element)); | 4027 __ ld(string, MemOperand(element)); |
4028 __ Daddu(element, element, kPointerSize); | 4028 __ Daddu(element, element, kPointerSize); |
4029 __ ld(string_length, FieldMemOperand(string, String::kLengthOffset)); | 4029 __ ld(string_length, FieldMemOperand(string, String::kLengthOffset)); |
4030 __ SmiUntag(string_length); | 4030 __ SmiUntag(string_length); |
4031 __ Daddu(string, string, SeqOneByteString::kHeaderSize - kHeapObjectTag); | 4031 __ Daddu(string, string, SeqOneByteString::kHeaderSize - kHeapObjectTag); |
4032 __ CopyBytes(string, result_pos, string_length, scratch1); | 4032 __ CopyBytes(string, result_pos, string_length, scratch1); |
4033 // End while (element < elements_end). | 4033 // End while (element < elements_end). |
4034 __ Branch(&one_char_separator_loop, lt, element, Operand(elements_end)); | 4034 __ Branch(&one_char_separator_loop, lt, element, Operand(elements_end)); |
4035 ASSERT(result.is(v0)); | 4035 DCHECK(result.is(v0)); |
4036 __ Branch(&done); | 4036 __ Branch(&done); |
4037 | 4037 |
4038 // Long separator case (separator is more than one character). Entry is at the | 4038 // Long separator case (separator is more than one character). Entry is at the |
4039 // label long_separator below. | 4039 // label long_separator below. |
4040 __ bind(&long_separator_loop); | 4040 __ bind(&long_separator_loop); |
4041 // Live values in registers: | 4041 // Live values in registers: |
4042 // result_pos: the position to which we are currently copying characters. | 4042 // result_pos: the position to which we are currently copying characters. |
4043 // element: Current array element. | 4043 // element: Current array element. |
4044 // elements_end: Array end. | 4044 // elements_end: Array end. |
4045 // separator: Separator string. | 4045 // separator: Separator string. |
4046 | 4046 |
4047 // Copy the separator to the result. | 4047 // Copy the separator to the result. |
4048 __ ld(string_length, FieldMemOperand(separator, String::kLengthOffset)); | 4048 __ ld(string_length, FieldMemOperand(separator, String::kLengthOffset)); |
4049 __ SmiUntag(string_length); | 4049 __ SmiUntag(string_length); |
4050 __ Daddu(string, | 4050 __ Daddu(string, |
4051 separator, | 4051 separator, |
4052 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); | 4052 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); |
4053 __ CopyBytes(string, result_pos, string_length, scratch1); | 4053 __ CopyBytes(string, result_pos, string_length, scratch1); |
4054 | 4054 |
4055 __ bind(&long_separator); | 4055 __ bind(&long_separator); |
4056 __ ld(string, MemOperand(element)); | 4056 __ ld(string, MemOperand(element)); |
4057 __ Daddu(element, element, kPointerSize); | 4057 __ Daddu(element, element, kPointerSize); |
4058 __ ld(string_length, FieldMemOperand(string, String::kLengthOffset)); | 4058 __ ld(string_length, FieldMemOperand(string, String::kLengthOffset)); |
4059 __ SmiUntag(string_length); | 4059 __ SmiUntag(string_length); |
4060 __ Daddu(string, string, SeqOneByteString::kHeaderSize - kHeapObjectTag); | 4060 __ Daddu(string, string, SeqOneByteString::kHeaderSize - kHeapObjectTag); |
4061 __ CopyBytes(string, result_pos, string_length, scratch1); | 4061 __ CopyBytes(string, result_pos, string_length, scratch1); |
4062 // End while (element < elements_end). | 4062 // End while (element < elements_end). |
4063 __ Branch(&long_separator_loop, lt, element, Operand(elements_end)); | 4063 __ Branch(&long_separator_loop, lt, element, Operand(elements_end)); |
4064 ASSERT(result.is(v0)); | 4064 DCHECK(result.is(v0)); |
4065 __ Branch(&done); | 4065 __ Branch(&done); |
4066 | 4066 |
4067 __ bind(&bailout); | 4067 __ bind(&bailout); |
4068 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex); | 4068 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex); |
4069 __ bind(&done); | 4069 __ bind(&done); |
4070 context()->Plug(v0); | 4070 context()->Plug(v0); |
4071 } | 4071 } |
4072 | 4072 |
4073 | 4073 |
4074 void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) { | 4074 void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) { |
4075 ASSERT(expr->arguments()->length() == 0); | 4075 DCHECK(expr->arguments()->length() == 0); |
4076 ExternalReference debug_is_active = | 4076 ExternalReference debug_is_active = |
4077 ExternalReference::debug_is_active_address(isolate()); | 4077 ExternalReference::debug_is_active_address(isolate()); |
4078 __ li(at, Operand(debug_is_active)); | 4078 __ li(at, Operand(debug_is_active)); |
4079 __ lbu(v0, MemOperand(at)); | 4079 __ lbu(v0, MemOperand(at)); |
4080 __ SmiTag(v0); | 4080 __ SmiTag(v0); |
4081 context()->Plug(v0); | 4081 context()->Plug(v0); |
4082 } | 4082 } |
4083 | 4083 |
4084 | 4084 |
4085 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { | 4085 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4156 VisitForStackValue(property->obj()); | 4156 VisitForStackValue(property->obj()); |
4157 VisitForStackValue(property->key()); | 4157 VisitForStackValue(property->key()); |
4158 __ li(a1, Operand(Smi::FromInt(strict_mode()))); | 4158 __ li(a1, Operand(Smi::FromInt(strict_mode()))); |
4159 __ push(a1); | 4159 __ push(a1); |
4160 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); | 4160 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); |
4161 context()->Plug(v0); | 4161 context()->Plug(v0); |
4162 } else if (proxy != NULL) { | 4162 } else if (proxy != NULL) { |
4163 Variable* var = proxy->var(); | 4163 Variable* var = proxy->var(); |
4164 // Delete of an unqualified identifier is disallowed in strict mode | 4164 // Delete of an unqualified identifier is disallowed in strict mode |
4165 // but "delete this" is allowed. | 4165 // but "delete this" is allowed. |
4166 ASSERT(strict_mode() == SLOPPY || var->is_this()); | 4166 DCHECK(strict_mode() == SLOPPY || var->is_this()); |
4167 if (var->IsUnallocated()) { | 4167 if (var->IsUnallocated()) { |
4168 __ ld(a2, GlobalObjectOperand()); | 4168 __ ld(a2, GlobalObjectOperand()); |
4169 __ li(a1, Operand(var->name())); | 4169 __ li(a1, Operand(var->name())); |
4170 __ li(a0, Operand(Smi::FromInt(SLOPPY))); | 4170 __ li(a0, Operand(Smi::FromInt(SLOPPY))); |
4171 __ Push(a2, a1, a0); | 4171 __ Push(a2, a1, a0); |
4172 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); | 4172 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); |
4173 context()->Plug(v0); | 4173 context()->Plug(v0); |
4174 } else if (var->IsStackAllocated() || var->IsContextSlot()) { | 4174 } else if (var->IsStackAllocated() || var->IsContextSlot()) { |
4175 // Result of deleting non-global, non-dynamic variables is false. | 4175 // Result of deleting non-global, non-dynamic variables is false. |
4176 // The subexpression does not have side effects. | 4176 // The subexpression does not have side effects. |
4177 context()->Plug(var->is_this()); | 4177 context()->Plug(var->is_this()); |
4178 } else { | 4178 } else { |
4179 // Non-global variable. Call the runtime to try to delete from the | 4179 // Non-global variable. Call the runtime to try to delete from the |
4180 // context where the variable was introduced. | 4180 // context where the variable was introduced. |
4181 ASSERT(!context_register().is(a2)); | 4181 DCHECK(!context_register().is(a2)); |
4182 __ li(a2, Operand(var->name())); | 4182 __ li(a2, Operand(var->name())); |
4183 __ Push(context_register(), a2); | 4183 __ Push(context_register(), a2); |
4184 __ CallRuntime(Runtime::kDeleteLookupSlot, 2); | 4184 __ CallRuntime(Runtime::kDeleteLookupSlot, 2); |
4185 context()->Plug(v0); | 4185 context()->Plug(v0); |
4186 } | 4186 } |
4187 } else { | 4187 } else { |
4188 // Result of deleting non-property, non-variable reference is true. | 4188 // Result of deleting non-property, non-variable reference is true. |
4189 // The subexpression may have side effects. | 4189 // The subexpression may have side effects. |
4190 VisitForEffect(expr->expression()); | 4190 VisitForEffect(expr->expression()); |
4191 context()->Plug(true); | 4191 context()->Plug(true); |
(...skipping 20 matching lines...) Expand all Loading... |
4212 VisitForControl(expr->expression(), | 4212 VisitForControl(expr->expression(), |
4213 test->false_label(), | 4213 test->false_label(), |
4214 test->true_label(), | 4214 test->true_label(), |
4215 test->fall_through()); | 4215 test->fall_through()); |
4216 context()->Plug(test->true_label(), test->false_label()); | 4216 context()->Plug(test->true_label(), test->false_label()); |
4217 } else { | 4217 } else { |
4218 // We handle value contexts explicitly rather than simply visiting | 4218 // We handle value contexts explicitly rather than simply visiting |
4219 // for control and plugging the control flow into the context, | 4219 // for control and plugging the control flow into the context, |
4220 // because we need to prepare a pair of extra administrative AST ids | 4220 // because we need to prepare a pair of extra administrative AST ids |
4221 // for the optimizing compiler. | 4221 // for the optimizing compiler. |
4222 ASSERT(context()->IsAccumulatorValue() || context()->IsStackValue()); | 4222 DCHECK(context()->IsAccumulatorValue() || context()->IsStackValue()); |
4223 Label materialize_true, materialize_false, done; | 4223 Label materialize_true, materialize_false, done; |
4224 VisitForControl(expr->expression(), | 4224 VisitForControl(expr->expression(), |
4225 &materialize_false, | 4225 &materialize_false, |
4226 &materialize_true, | 4226 &materialize_true, |
4227 &materialize_true); | 4227 &materialize_true); |
4228 __ bind(&materialize_true); | 4228 __ bind(&materialize_true); |
4229 PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS); | 4229 PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS); |
4230 __ LoadRoot(v0, Heap::kTrueValueRootIndex); | 4230 __ LoadRoot(v0, Heap::kTrueValueRootIndex); |
4231 if (context()->IsStackValue()) __ push(v0); | 4231 if (context()->IsStackValue()) __ push(v0); |
4232 __ jmp(&done); | 4232 __ jmp(&done); |
(...skipping 16 matching lines...) Expand all Loading... |
4249 break; | 4249 break; |
4250 } | 4250 } |
4251 | 4251 |
4252 default: | 4252 default: |
4253 UNREACHABLE(); | 4253 UNREACHABLE(); |
4254 } | 4254 } |
4255 } | 4255 } |
4256 | 4256 |
4257 | 4257 |
4258 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { | 4258 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { |
4259 ASSERT(expr->expression()->IsValidReferenceExpression()); | 4259 DCHECK(expr->expression()->IsValidReferenceExpression()); |
4260 | 4260 |
4261 Comment cmnt(masm_, "[ CountOperation"); | 4261 Comment cmnt(masm_, "[ CountOperation"); |
4262 SetSourcePosition(expr->position()); | 4262 SetSourcePosition(expr->position()); |
4263 | 4263 |
4264 // Expression can only be a property, a global or a (parameter or local) | 4264 // Expression can only be a property, a global or a (parameter or local) |
4265 // slot. | 4265 // slot. |
4266 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 4266 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
4267 LhsKind assign_type = VARIABLE; | 4267 LhsKind assign_type = VARIABLE; |
4268 Property* prop = expr->expression()->AsProperty(); | 4268 Property* prop = expr->expression()->AsProperty(); |
4269 // In case of a property we use the uninitialized expression context | 4269 // In case of a property we use the uninitialized expression context |
4270 // of the key to detect a named property. | 4270 // of the key to detect a named property. |
4271 if (prop != NULL) { | 4271 if (prop != NULL) { |
4272 assign_type = | 4272 assign_type = |
4273 (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; | 4273 (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; |
4274 } | 4274 } |
4275 | 4275 |
4276 // Evaluate expression and get value. | 4276 // Evaluate expression and get value. |
4277 if (assign_type == VARIABLE) { | 4277 if (assign_type == VARIABLE) { |
4278 ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); | 4278 DCHECK(expr->expression()->AsVariableProxy()->var() != NULL); |
4279 AccumulatorValueContext context(this); | 4279 AccumulatorValueContext context(this); |
4280 EmitVariableLoad(expr->expression()->AsVariableProxy()); | 4280 EmitVariableLoad(expr->expression()->AsVariableProxy()); |
4281 } else { | 4281 } else { |
4282 // Reserve space for result of postfix operation. | 4282 // Reserve space for result of postfix operation. |
4283 if (expr->is_postfix() && !context()->IsEffect()) { | 4283 if (expr->is_postfix() && !context()->IsEffect()) { |
4284 __ li(at, Operand(Smi::FromInt(0))); | 4284 __ li(at, Operand(Smi::FromInt(0))); |
4285 __ push(at); | 4285 __ push(at); |
4286 } | 4286 } |
4287 if (assign_type == NAMED_PROPERTY) { | 4287 if (assign_type == NAMED_PROPERTY) { |
4288 // Put the object both on the stack and in the register. | 4288 // Put the object both on the stack and in the register. |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4434 } else { | 4434 } else { |
4435 context()->Plug(v0); | 4435 context()->Plug(v0); |
4436 } | 4436 } |
4437 break; | 4437 break; |
4438 } | 4438 } |
4439 } | 4439 } |
4440 } | 4440 } |
4441 | 4441 |
4442 | 4442 |
4443 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { | 4443 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { |
4444 ASSERT(!context()->IsEffect()); | 4444 DCHECK(!context()->IsEffect()); |
4445 ASSERT(!context()->IsTest()); | 4445 DCHECK(!context()->IsTest()); |
4446 VariableProxy* proxy = expr->AsVariableProxy(); | 4446 VariableProxy* proxy = expr->AsVariableProxy(); |
4447 if (proxy != NULL && proxy->var()->IsUnallocated()) { | 4447 if (proxy != NULL && proxy->var()->IsUnallocated()) { |
4448 Comment cmnt(masm_, "[ Global variable"); | 4448 Comment cmnt(masm_, "[ Global variable"); |
4449 __ ld(LoadIC::ReceiverRegister(), GlobalObjectOperand()); | 4449 __ ld(LoadIC::ReceiverRegister(), GlobalObjectOperand()); |
4450 __ li(LoadIC::NameRegister(), Operand(proxy->name())); | 4450 __ li(LoadIC::NameRegister(), Operand(proxy->name())); |
4451 if (FLAG_vector_ics) { | 4451 if (FLAG_vector_ics) { |
4452 __ li(LoadIC::SlotRegister(), | 4452 __ li(LoadIC::SlotRegister(), |
4453 Operand(Smi::FromInt(proxy->VariableFeedbackSlot()))); | 4453 Operand(Smi::FromInt(proxy->VariableFeedbackSlot()))); |
4454 } | 4454 } |
4455 // Use a regular load, not a contextual load, to avoid a reference | 4455 // Use a regular load, not a contextual load, to avoid a reference |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4661 return v0; | 4661 return v0; |
4662 } | 4662 } |
4663 | 4663 |
4664 | 4664 |
4665 Register FullCodeGenerator::context_register() { | 4665 Register FullCodeGenerator::context_register() { |
4666 return cp; | 4666 return cp; |
4667 } | 4667 } |
4668 | 4668 |
4669 | 4669 |
4670 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { | 4670 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { |
4671 // ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset); | 4671 // DCHECK_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset); |
4672 ASSERT(IsAligned(frame_offset, kPointerSize)); | 4672 DCHECK(IsAligned(frame_offset, kPointerSize)); |
4673 // __ sw(value, MemOperand(fp, frame_offset)); | 4673 // __ sw(value, MemOperand(fp, frame_offset)); |
4674 __ sd(value, MemOperand(fp, frame_offset)); | 4674 __ sd(value, MemOperand(fp, frame_offset)); |
4675 } | 4675 } |
4676 | 4676 |
4677 | 4677 |
4678 void FullCodeGenerator::LoadContextField(Register dst, int context_index) { | 4678 void FullCodeGenerator::LoadContextField(Register dst, int context_index) { |
4679 __ ld(dst, ContextOperand(cp, context_index)); | 4679 __ ld(dst, ContextOperand(cp, context_index)); |
4680 } | 4680 } |
4681 | 4681 |
4682 | 4682 |
4683 void FullCodeGenerator::PushFunctionArgumentForContextAllocation() { | 4683 void FullCodeGenerator::PushFunctionArgumentForContextAllocation() { |
4684 Scope* declaration_scope = scope()->DeclarationScope(); | 4684 Scope* declaration_scope = scope()->DeclarationScope(); |
4685 if (declaration_scope->is_global_scope() || | 4685 if (declaration_scope->is_global_scope() || |
4686 declaration_scope->is_module_scope()) { | 4686 declaration_scope->is_module_scope()) { |
4687 // Contexts nested in the native context have a canonical empty function | 4687 // Contexts nested in the native context have a canonical empty function |
4688 // as their closure, not the anonymous closure containing the global | 4688 // as their closure, not the anonymous closure containing the global |
4689 // code. Pass a smi sentinel and let the runtime look up the empty | 4689 // code. Pass a smi sentinel and let the runtime look up the empty |
4690 // function. | 4690 // function. |
4691 __ li(at, Operand(Smi::FromInt(0))); | 4691 __ li(at, Operand(Smi::FromInt(0))); |
4692 } else if (declaration_scope->is_eval_scope()) { | 4692 } else if (declaration_scope->is_eval_scope()) { |
4693 // Contexts created by a call to eval have the same closure as the | 4693 // Contexts created by a call to eval have the same closure as the |
4694 // context calling eval, not the anonymous closure containing the eval | 4694 // context calling eval, not the anonymous closure containing the eval |
4695 // code. Fetch it from the context. | 4695 // code. Fetch it from the context. |
4696 __ ld(at, ContextOperand(cp, Context::CLOSURE_INDEX)); | 4696 __ ld(at, ContextOperand(cp, Context::CLOSURE_INDEX)); |
4697 } else { | 4697 } else { |
4698 ASSERT(declaration_scope->is_function_scope()); | 4698 DCHECK(declaration_scope->is_function_scope()); |
4699 __ ld(at, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 4699 __ ld(at, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
4700 } | 4700 } |
4701 __ push(at); | 4701 __ push(at); |
4702 } | 4702 } |
4703 | 4703 |
4704 | 4704 |
4705 // ---------------------------------------------------------------------------- | 4705 // ---------------------------------------------------------------------------- |
4706 // Non-local control flow support. | 4706 // Non-local control flow support. |
4707 | 4707 |
4708 void FullCodeGenerator::EnterFinallyBlock() { | 4708 void FullCodeGenerator::EnterFinallyBlock() { |
4709 ASSERT(!result_register().is(a1)); | 4709 DCHECK(!result_register().is(a1)); |
4710 // Store result register while executing finally block. | 4710 // Store result register while executing finally block. |
4711 __ push(result_register()); | 4711 __ push(result_register()); |
4712 // Cook return address in link register to stack (smi encoded Code* delta). | 4712 // Cook return address in link register to stack (smi encoded Code* delta). |
4713 __ Dsubu(a1, ra, Operand(masm_->CodeObject())); | 4713 __ Dsubu(a1, ra, Operand(masm_->CodeObject())); |
4714 __ SmiTag(a1); | 4714 __ SmiTag(a1); |
4715 | 4715 |
4716 // Store result register while executing finally block. | 4716 // Store result register while executing finally block. |
4717 __ push(a1); | 4717 __ push(a1); |
4718 | 4718 |
4719 // Store pending message while executing finally block. | 4719 // Store pending message while executing finally block. |
(...skipping 12 matching lines...) Expand all Loading... |
4732 | 4732 |
4733 ExternalReference pending_message_script = | 4733 ExternalReference pending_message_script = |
4734 ExternalReference::address_of_pending_message_script(isolate()); | 4734 ExternalReference::address_of_pending_message_script(isolate()); |
4735 __ li(at, Operand(pending_message_script)); | 4735 __ li(at, Operand(pending_message_script)); |
4736 __ ld(a1, MemOperand(at)); | 4736 __ ld(a1, MemOperand(at)); |
4737 __ push(a1); | 4737 __ push(a1); |
4738 } | 4738 } |
4739 | 4739 |
4740 | 4740 |
4741 void FullCodeGenerator::ExitFinallyBlock() { | 4741 void FullCodeGenerator::ExitFinallyBlock() { |
4742 ASSERT(!result_register().is(a1)); | 4742 DCHECK(!result_register().is(a1)); |
4743 // Restore pending message from stack. | 4743 // Restore pending message from stack. |
4744 __ pop(a1); | 4744 __ pop(a1); |
4745 ExternalReference pending_message_script = | 4745 ExternalReference pending_message_script = |
4746 ExternalReference::address_of_pending_message_script(isolate()); | 4746 ExternalReference::address_of_pending_message_script(isolate()); |
4747 __ li(at, Operand(pending_message_script)); | 4747 __ li(at, Operand(pending_message_script)); |
4748 __ sd(a1, MemOperand(at)); | 4748 __ sd(a1, MemOperand(at)); |
4749 | 4749 |
4750 __ pop(a1); | 4750 __ pop(a1); |
4751 __ SmiUntag(a1); | 4751 __ SmiUntag(a1); |
4752 ExternalReference has_pending_message = | 4752 ExternalReference has_pending_message = |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4850 | 4850 |
4851 | 4851 |
4852 BackEdgeTable::BackEdgeState BackEdgeTable::GetBackEdgeState( | 4852 BackEdgeTable::BackEdgeState BackEdgeTable::GetBackEdgeState( |
4853 Isolate* isolate, | 4853 Isolate* isolate, |
4854 Code* unoptimized_code, | 4854 Code* unoptimized_code, |
4855 Address pc) { | 4855 Address pc) { |
4856 static const int kInstrSize = Assembler::kInstrSize; | 4856 static const int kInstrSize = Assembler::kInstrSize; |
4857 Address branch_address = pc - 8 * kInstrSize; | 4857 Address branch_address = pc - 8 * kInstrSize; |
4858 Address pc_immediate_load_address = pc - 6 * kInstrSize; | 4858 Address pc_immediate_load_address = pc - 6 * kInstrSize; |
4859 | 4859 |
4860 ASSERT(Assembler::IsBeq(Assembler::instr_at(pc - 7 * kInstrSize))); | 4860 DCHECK(Assembler::IsBeq(Assembler::instr_at(pc - 7 * kInstrSize))); |
4861 if (!Assembler::IsAddImmediate(Assembler::instr_at(branch_address))) { | 4861 if (!Assembler::IsAddImmediate(Assembler::instr_at(branch_address))) { |
4862 ASSERT(reinterpret_cast<uint64_t>( | 4862 DCHECK(reinterpret_cast<uint64_t>( |
4863 Assembler::target_address_at(pc_immediate_load_address)) == | 4863 Assembler::target_address_at(pc_immediate_load_address)) == |
4864 reinterpret_cast<uint64_t>( | 4864 reinterpret_cast<uint64_t>( |
4865 isolate->builtins()->InterruptCheck()->entry())); | 4865 isolate->builtins()->InterruptCheck()->entry())); |
4866 return INTERRUPT; | 4866 return INTERRUPT; |
4867 } | 4867 } |
4868 | 4868 |
4869 ASSERT(Assembler::IsAddImmediate(Assembler::instr_at(branch_address))); | 4869 DCHECK(Assembler::IsAddImmediate(Assembler::instr_at(branch_address))); |
4870 | 4870 |
4871 if (reinterpret_cast<uint64_t>( | 4871 if (reinterpret_cast<uint64_t>( |
4872 Assembler::target_address_at(pc_immediate_load_address)) == | 4872 Assembler::target_address_at(pc_immediate_load_address)) == |
4873 reinterpret_cast<uint64_t>( | 4873 reinterpret_cast<uint64_t>( |
4874 isolate->builtins()->OnStackReplacement()->entry())) { | 4874 isolate->builtins()->OnStackReplacement()->entry())) { |
4875 return ON_STACK_REPLACEMENT; | 4875 return ON_STACK_REPLACEMENT; |
4876 } | 4876 } |
4877 | 4877 |
4878 ASSERT(reinterpret_cast<uint64_t>( | 4878 DCHECK(reinterpret_cast<uint64_t>( |
4879 Assembler::target_address_at(pc_immediate_load_address)) == | 4879 Assembler::target_address_at(pc_immediate_load_address)) == |
4880 reinterpret_cast<uint64_t>( | 4880 reinterpret_cast<uint64_t>( |
4881 isolate->builtins()->OsrAfterStackCheck()->entry())); | 4881 isolate->builtins()->OsrAfterStackCheck()->entry())); |
4882 return OSR_AFTER_STACK_CHECK; | 4882 return OSR_AFTER_STACK_CHECK; |
4883 } | 4883 } |
4884 | 4884 |
4885 | 4885 |
4886 } } // namespace v8::internal | 4886 } } // namespace v8::internal |
4887 | 4887 |
4888 #endif // V8_TARGET_ARCH_MIPS64 | 4888 #endif // V8_TARGET_ARCH_MIPS64 |
OLD | NEW |