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