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_ARM | 7 #if V8_TARGET_ARCH_ARM |
8 | 8 |
9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
(...skipping 22 matching lines...) Expand all Loading... |
33 // the patchable code. | 33 // the patchable code. |
34 class JumpPatchSite BASE_EMBEDDED { | 34 class JumpPatchSite BASE_EMBEDDED { |
35 public: | 35 public: |
36 explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm) { | 36 explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm) { |
37 #ifdef DEBUG | 37 #ifdef DEBUG |
38 info_emitted_ = false; | 38 info_emitted_ = false; |
39 #endif | 39 #endif |
40 } | 40 } |
41 | 41 |
42 ~JumpPatchSite() { | 42 ~JumpPatchSite() { |
43 ASSERT(patch_site_.is_bound() == info_emitted_); | 43 DCHECK(patch_site_.is_bound() == info_emitted_); |
44 } | 44 } |
45 | 45 |
46 // When initially emitting this ensure that a jump is always generated to skip | 46 // When initially emitting this ensure that a jump is always generated to skip |
47 // the inlined smi code. | 47 // the inlined smi code. |
48 void EmitJumpIfNotSmi(Register reg, Label* target) { | 48 void EmitJumpIfNotSmi(Register reg, Label* target) { |
49 ASSERT(!patch_site_.is_bound() && !info_emitted_); | 49 DCHECK(!patch_site_.is_bound() && !info_emitted_); |
50 Assembler::BlockConstPoolScope block_const_pool(masm_); | 50 Assembler::BlockConstPoolScope block_const_pool(masm_); |
51 __ bind(&patch_site_); | 51 __ bind(&patch_site_); |
52 __ cmp(reg, Operand(reg)); | 52 __ cmp(reg, Operand(reg)); |
53 __ b(eq, target); // Always taken before patched. | 53 __ b(eq, target); // Always taken before patched. |
54 } | 54 } |
55 | 55 |
56 // When initially emitting this ensure that a jump is never generated to skip | 56 // When initially emitting this ensure that a jump is never generated to skip |
57 // the inlined smi code. | 57 // the inlined smi code. |
58 void EmitJumpIfSmi(Register reg, Label* target) { | 58 void EmitJumpIfSmi(Register reg, Label* target) { |
59 ASSERT(!patch_site_.is_bound() && !info_emitted_); | 59 DCHECK(!patch_site_.is_bound() && !info_emitted_); |
60 Assembler::BlockConstPoolScope block_const_pool(masm_); | 60 Assembler::BlockConstPoolScope block_const_pool(masm_); |
61 __ bind(&patch_site_); | 61 __ bind(&patch_site_); |
62 __ cmp(reg, Operand(reg)); | 62 __ cmp(reg, Operand(reg)); |
63 __ b(ne, target); // Never taken before patched. | 63 __ b(ne, target); // Never taken before patched. |
64 } | 64 } |
65 | 65 |
66 void EmitPatchInfo() { | 66 void EmitPatchInfo() { |
67 // Block literal pool emission whilst recording patch site information. | 67 // Block literal pool emission whilst recording patch site information. |
68 Assembler::BlockConstPoolScope block_const_pool(masm_); | 68 Assembler::BlockConstPoolScope block_const_pool(masm_); |
69 if (patch_site_.is_bound()) { | 69 if (patch_site_.is_bound()) { |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
145 // the frame (that is done below). | 145 // the frame (that is done below). |
146 FrameScope frame_scope(masm_, StackFrame::MANUAL); | 146 FrameScope frame_scope(masm_, StackFrame::MANUAL); |
147 | 147 |
148 info->set_prologue_offset(masm_->pc_offset()); | 148 info->set_prologue_offset(masm_->pc_offset()); |
149 __ Prologue(info->IsCodePreAgingActive()); | 149 __ Prologue(info->IsCodePreAgingActive()); |
150 info->AddNoFrameRange(0, masm_->pc_offset()); | 150 info->AddNoFrameRange(0, masm_->pc_offset()); |
151 | 151 |
152 { Comment cmnt(masm_, "[ Allocate locals"); | 152 { Comment cmnt(masm_, "[ Allocate locals"); |
153 int locals_count = info->scope()->num_stack_slots(); | 153 int locals_count = info->scope()->num_stack_slots(); |
154 // Generators allocate locals, if any, in context slots. | 154 // Generators allocate locals, if any, in context slots. |
155 ASSERT(!info->function()->is_generator() || locals_count == 0); | 155 DCHECK(!info->function()->is_generator() || locals_count == 0); |
156 if (locals_count > 0) { | 156 if (locals_count > 0) { |
157 if (locals_count >= 128) { | 157 if (locals_count >= 128) { |
158 Label ok; | 158 Label ok; |
159 __ sub(r9, sp, Operand(locals_count * kPointerSize)); | 159 __ sub(r9, sp, Operand(locals_count * kPointerSize)); |
160 __ LoadRoot(r2, Heap::kRealStackLimitRootIndex); | 160 __ LoadRoot(r2, Heap::kRealStackLimitRootIndex); |
161 __ cmp(r9, Operand(r2)); | 161 __ cmp(r9, Operand(r2)); |
162 __ b(hs, &ok); | 162 __ b(hs, &ok); |
163 __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION); | 163 __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION); |
164 __ bind(&ok); | 164 __ bind(&ok); |
165 } | 165 } |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
285 Comment cmnt(masm_, "[ Declarations"); | 285 Comment cmnt(masm_, "[ Declarations"); |
286 scope()->VisitIllegalRedeclaration(this); | 286 scope()->VisitIllegalRedeclaration(this); |
287 | 287 |
288 } else { | 288 } else { |
289 PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS); | 289 PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS); |
290 { Comment cmnt(masm_, "[ Declarations"); | 290 { Comment cmnt(masm_, "[ Declarations"); |
291 // For named function expressions, declare the function name as a | 291 // For named function expressions, declare the function name as a |
292 // constant. | 292 // constant. |
293 if (scope()->is_function_scope() && scope()->function() != NULL) { | 293 if (scope()->is_function_scope() && scope()->function() != NULL) { |
294 VariableDeclaration* function = scope()->function(); | 294 VariableDeclaration* function = scope()->function(); |
295 ASSERT(function->proxy()->var()->mode() == CONST || | 295 DCHECK(function->proxy()->var()->mode() == CONST || |
296 function->proxy()->var()->mode() == CONST_LEGACY); | 296 function->proxy()->var()->mode() == CONST_LEGACY); |
297 ASSERT(function->proxy()->var()->location() != Variable::UNALLOCATED); | 297 DCHECK(function->proxy()->var()->location() != Variable::UNALLOCATED); |
298 VisitVariableDeclaration(function); | 298 VisitVariableDeclaration(function); |
299 } | 299 } |
300 VisitDeclarations(scope()->declarations()); | 300 VisitDeclarations(scope()->declarations()); |
301 } | 301 } |
302 | 302 |
303 { Comment cmnt(masm_, "[ Stack check"); | 303 { Comment cmnt(masm_, "[ Stack check"); |
304 PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS); | 304 PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS); |
305 Label ok; | 305 Label ok; |
306 __ LoadRoot(ip, Heap::kStackLimitRootIndex); | 306 __ LoadRoot(ip, Heap::kStackLimitRootIndex); |
307 __ cmp(sp, Operand(ip)); | 307 __ cmp(sp, Operand(ip)); |
308 __ b(hs, &ok); | 308 __ b(hs, &ok); |
309 Handle<Code> stack_check = isolate()->builtins()->StackCheck(); | 309 Handle<Code> stack_check = isolate()->builtins()->StackCheck(); |
310 PredictableCodeSizeScope predictable(masm_, | 310 PredictableCodeSizeScope predictable(masm_, |
311 masm_->CallSize(stack_check, RelocInfo::CODE_TARGET)); | 311 masm_->CallSize(stack_check, RelocInfo::CODE_TARGET)); |
312 __ Call(stack_check, RelocInfo::CODE_TARGET); | 312 __ Call(stack_check, RelocInfo::CODE_TARGET); |
313 __ bind(&ok); | 313 __ bind(&ok); |
314 } | 314 } |
315 | 315 |
316 { Comment cmnt(masm_, "[ Body"); | 316 { Comment cmnt(masm_, "[ Body"); |
317 ASSERT(loop_depth() == 0); | 317 DCHECK(loop_depth() == 0); |
318 VisitStatements(function()->body()); | 318 VisitStatements(function()->body()); |
319 ASSERT(loop_depth() == 0); | 319 DCHECK(loop_depth() == 0); |
320 } | 320 } |
321 } | 321 } |
322 | 322 |
323 // Always emit a 'return undefined' in case control fell off the end of | 323 // Always emit a 'return undefined' in case control fell off the end of |
324 // the body. | 324 // the body. |
325 { Comment cmnt(masm_, "[ return <undefined>;"); | 325 { Comment cmnt(masm_, "[ return <undefined>;"); |
326 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); | 326 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); |
327 } | 327 } |
328 EmitReturnSequence(); | 328 EmitReturnSequence(); |
329 | 329 |
(...skipping 26 matching lines...) Expand all Loading... |
356 Label start; | 356 Label start; |
357 __ bind(&start); | 357 __ bind(&start); |
358 int reset_value = FLAG_interrupt_budget; | 358 int reset_value = FLAG_interrupt_budget; |
359 if (info_->is_debug()) { | 359 if (info_->is_debug()) { |
360 // Detect debug break requests as soon as possible. | 360 // Detect debug break requests as soon as possible. |
361 reset_value = FLAG_interrupt_budget >> 4; | 361 reset_value = FLAG_interrupt_budget >> 4; |
362 } | 362 } |
363 __ mov(r2, Operand(profiling_counter_)); | 363 __ mov(r2, Operand(profiling_counter_)); |
364 // The mov instruction above can be either 1, 2 or 3 instructions depending | 364 // The mov instruction above can be either 1, 2 or 3 instructions depending |
365 // upon whether it is an extended constant pool - insert nop to compensate. | 365 // upon whether it is an extended constant pool - insert nop to compensate. |
366 ASSERT(masm_->InstructionsGeneratedSince(&start) <= 3); | 366 DCHECK(masm_->InstructionsGeneratedSince(&start) <= 3); |
367 while (masm_->InstructionsGeneratedSince(&start) != 3) { | 367 while (masm_->InstructionsGeneratedSince(&start) != 3) { |
368 __ nop(); | 368 __ nop(); |
369 } | 369 } |
370 __ mov(r3, Operand(Smi::FromInt(reset_value))); | 370 __ mov(r3, Operand(Smi::FromInt(reset_value))); |
371 __ str(r3, FieldMemOperand(r2, Cell::kValueOffset)); | 371 __ str(r3, FieldMemOperand(r2, Cell::kValueOffset)); |
372 } | 372 } |
373 | 373 |
374 | 374 |
375 void FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt, | 375 void FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt, |
376 Label* back_edge_target) { | 376 Label* back_edge_target) { |
377 Comment cmnt(masm_, "[ Back edge bookkeeping"); | 377 Comment cmnt(masm_, "[ Back edge bookkeeping"); |
378 // Block literal pools whilst emitting back edge code. | 378 // Block literal pools whilst emitting back edge code. |
379 Assembler::BlockConstPoolScope block_const_pool(masm_); | 379 Assembler::BlockConstPoolScope block_const_pool(masm_); |
380 Label ok; | 380 Label ok; |
381 | 381 |
382 ASSERT(back_edge_target->is_bound()); | 382 DCHECK(back_edge_target->is_bound()); |
383 int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target); | 383 int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target); |
384 int weight = Min(kMaxBackEdgeWeight, | 384 int weight = Min(kMaxBackEdgeWeight, |
385 Max(1, distance / kCodeSizeMultiplier)); | 385 Max(1, distance / kCodeSizeMultiplier)); |
386 EmitProfilingCounterDecrement(weight); | 386 EmitProfilingCounterDecrement(weight); |
387 __ b(pl, &ok); | 387 __ b(pl, &ok); |
388 __ Call(isolate()->builtins()->InterruptCheck(), RelocInfo::CODE_TARGET); | 388 __ Call(isolate()->builtins()->InterruptCheck(), RelocInfo::CODE_TARGET); |
389 | 389 |
390 // Record a mapping of this PC offset to the OSR id. This is used to find | 390 // Record a mapping of this PC offset to the OSR id. This is used to find |
391 // the AST id from the unoptimized code in order to use it as a key into | 391 // the AST id from the unoptimized code in order to use it as a key into |
392 // the deoptimization input data found in the optimized code. | 392 // the deoptimization input data found in the optimized code. |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
449 __ RecordJSReturn(); | 449 __ RecordJSReturn(); |
450 int no_frame_start = __ LeaveFrame(StackFrame::JAVA_SCRIPT); | 450 int no_frame_start = __ LeaveFrame(StackFrame::JAVA_SCRIPT); |
451 __ add(sp, sp, Operand(sp_delta)); | 451 __ add(sp, sp, Operand(sp_delta)); |
452 __ Jump(lr); | 452 __ Jump(lr); |
453 info_->AddNoFrameRange(no_frame_start, masm_->pc_offset()); | 453 info_->AddNoFrameRange(no_frame_start, masm_->pc_offset()); |
454 } | 454 } |
455 | 455 |
456 #ifdef DEBUG | 456 #ifdef DEBUG |
457 // Check that the size of the code used for returning is large enough | 457 // Check that the size of the code used for returning is large enough |
458 // for the debugger's requirements. | 458 // for the debugger's requirements. |
459 ASSERT(Assembler::kJSReturnSequenceInstructions <= | 459 DCHECK(Assembler::kJSReturnSequenceInstructions <= |
460 masm_->InstructionsGeneratedSince(&check_exit_codesize)); | 460 masm_->InstructionsGeneratedSince(&check_exit_codesize)); |
461 #endif | 461 #endif |
462 } | 462 } |
463 } | 463 } |
464 | 464 |
465 | 465 |
466 void FullCodeGenerator::EffectContext::Plug(Variable* var) const { | 466 void FullCodeGenerator::EffectContext::Plug(Variable* var) const { |
467 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); | 467 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
468 } | 468 } |
469 | 469 |
470 | 470 |
471 void FullCodeGenerator::AccumulatorValueContext::Plug(Variable* var) const { | 471 void FullCodeGenerator::AccumulatorValueContext::Plug(Variable* var) const { |
472 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); | 472 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
473 codegen()->GetVar(result_register(), var); | 473 codegen()->GetVar(result_register(), var); |
474 } | 474 } |
475 | 475 |
476 | 476 |
477 void FullCodeGenerator::StackValueContext::Plug(Variable* var) const { | 477 void FullCodeGenerator::StackValueContext::Plug(Variable* var) const { |
478 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); | 478 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
479 codegen()->GetVar(result_register(), var); | 479 codegen()->GetVar(result_register(), var); |
480 __ push(result_register()); | 480 __ push(result_register()); |
481 } | 481 } |
482 | 482 |
483 | 483 |
484 void FullCodeGenerator::TestContext::Plug(Variable* var) const { | 484 void FullCodeGenerator::TestContext::Plug(Variable* var) const { |
485 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); | 485 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
486 // For simplicity we always test the accumulator register. | 486 // For simplicity we always test the accumulator register. |
487 codegen()->GetVar(result_register(), var); | 487 codegen()->GetVar(result_register(), var); |
488 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); | 488 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); |
489 codegen()->DoTest(this); | 489 codegen()->DoTest(this); |
490 } | 490 } |
491 | 491 |
492 | 492 |
493 void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const { | 493 void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const { |
494 } | 494 } |
495 | 495 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
540 __ mov(result_register(), Operand(lit)); | 540 __ mov(result_register(), Operand(lit)); |
541 __ push(result_register()); | 541 __ push(result_register()); |
542 } | 542 } |
543 | 543 |
544 | 544 |
545 void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const { | 545 void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const { |
546 codegen()->PrepareForBailoutBeforeSplit(condition(), | 546 codegen()->PrepareForBailoutBeforeSplit(condition(), |
547 true, | 547 true, |
548 true_label_, | 548 true_label_, |
549 false_label_); | 549 false_label_); |
550 ASSERT(!lit->IsUndetectableObject()); // There are no undetectable literals. | 550 DCHECK(!lit->IsUndetectableObject()); // There are no undetectable literals. |
551 if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) { | 551 if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) { |
552 if (false_label_ != fall_through_) __ b(false_label_); | 552 if (false_label_ != fall_through_) __ b(false_label_); |
553 } else if (lit->IsTrue() || lit->IsJSObject()) { | 553 } else if (lit->IsTrue() || lit->IsJSObject()) { |
554 if (true_label_ != fall_through_) __ b(true_label_); | 554 if (true_label_ != fall_through_) __ b(true_label_); |
555 } else if (lit->IsString()) { | 555 } else if (lit->IsString()) { |
556 if (String::cast(*lit)->length() == 0) { | 556 if (String::cast(*lit)->length() == 0) { |
557 if (false_label_ != fall_through_) __ b(false_label_); | 557 if (false_label_ != fall_through_) __ b(false_label_); |
558 } else { | 558 } else { |
559 if (true_label_ != fall_through_) __ b(true_label_); | 559 if (true_label_ != fall_through_) __ b(true_label_); |
560 } | 560 } |
561 } else if (lit->IsSmi()) { | 561 } else if (lit->IsSmi()) { |
562 if (Smi::cast(*lit)->value() == 0) { | 562 if (Smi::cast(*lit)->value() == 0) { |
563 if (false_label_ != fall_through_) __ b(false_label_); | 563 if (false_label_ != fall_through_) __ b(false_label_); |
564 } else { | 564 } else { |
565 if (true_label_ != fall_through_) __ b(true_label_); | 565 if (true_label_ != fall_through_) __ b(true_label_); |
566 } | 566 } |
567 } else { | 567 } else { |
568 // For simplicity we always test the accumulator register. | 568 // For simplicity we always test the accumulator register. |
569 __ mov(result_register(), Operand(lit)); | 569 __ mov(result_register(), Operand(lit)); |
570 codegen()->DoTest(this); | 570 codegen()->DoTest(this); |
571 } | 571 } |
572 } | 572 } |
573 | 573 |
574 | 574 |
575 void FullCodeGenerator::EffectContext::DropAndPlug(int count, | 575 void FullCodeGenerator::EffectContext::DropAndPlug(int count, |
576 Register reg) const { | 576 Register reg) const { |
577 ASSERT(count > 0); | 577 DCHECK(count > 0); |
578 __ Drop(count); | 578 __ Drop(count); |
579 } | 579 } |
580 | 580 |
581 | 581 |
582 void FullCodeGenerator::AccumulatorValueContext::DropAndPlug( | 582 void FullCodeGenerator::AccumulatorValueContext::DropAndPlug( |
583 int count, | 583 int count, |
584 Register reg) const { | 584 Register reg) const { |
585 ASSERT(count > 0); | 585 DCHECK(count > 0); |
586 __ Drop(count); | 586 __ Drop(count); |
587 __ Move(result_register(), reg); | 587 __ Move(result_register(), reg); |
588 } | 588 } |
589 | 589 |
590 | 590 |
591 void FullCodeGenerator::StackValueContext::DropAndPlug(int count, | 591 void FullCodeGenerator::StackValueContext::DropAndPlug(int count, |
592 Register reg) const { | 592 Register reg) const { |
593 ASSERT(count > 0); | 593 DCHECK(count > 0); |
594 if (count > 1) __ Drop(count - 1); | 594 if (count > 1) __ Drop(count - 1); |
595 __ str(reg, MemOperand(sp, 0)); | 595 __ str(reg, MemOperand(sp, 0)); |
596 } | 596 } |
597 | 597 |
598 | 598 |
599 void FullCodeGenerator::TestContext::DropAndPlug(int count, | 599 void FullCodeGenerator::TestContext::DropAndPlug(int count, |
600 Register reg) const { | 600 Register reg) const { |
601 ASSERT(count > 0); | 601 DCHECK(count > 0); |
602 // For simplicity we always test the accumulator register. | 602 // For simplicity we always test the accumulator register. |
603 __ Drop(count); | 603 __ Drop(count); |
604 __ Move(result_register(), reg); | 604 __ Move(result_register(), reg); |
605 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); | 605 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); |
606 codegen()->DoTest(this); | 606 codegen()->DoTest(this); |
607 } | 607 } |
608 | 608 |
609 | 609 |
610 void FullCodeGenerator::EffectContext::Plug(Label* materialize_true, | 610 void FullCodeGenerator::EffectContext::Plug(Label* materialize_true, |
611 Label* materialize_false) const { | 611 Label* materialize_false) const { |
612 ASSERT(materialize_true == materialize_false); | 612 DCHECK(materialize_true == materialize_false); |
613 __ bind(materialize_true); | 613 __ bind(materialize_true); |
614 } | 614 } |
615 | 615 |
616 | 616 |
617 void FullCodeGenerator::AccumulatorValueContext::Plug( | 617 void FullCodeGenerator::AccumulatorValueContext::Plug( |
618 Label* materialize_true, | 618 Label* materialize_true, |
619 Label* materialize_false) const { | 619 Label* materialize_false) const { |
620 Label done; | 620 Label done; |
621 __ bind(materialize_true); | 621 __ bind(materialize_true); |
622 __ LoadRoot(result_register(), Heap::kTrueValueRootIndex); | 622 __ LoadRoot(result_register(), Heap::kTrueValueRootIndex); |
(...skipping 13 matching lines...) Expand all Loading... |
636 __ jmp(&done); | 636 __ jmp(&done); |
637 __ bind(materialize_false); | 637 __ bind(materialize_false); |
638 __ LoadRoot(ip, Heap::kFalseValueRootIndex); | 638 __ LoadRoot(ip, Heap::kFalseValueRootIndex); |
639 __ bind(&done); | 639 __ bind(&done); |
640 __ push(ip); | 640 __ push(ip); |
641 } | 641 } |
642 | 642 |
643 | 643 |
644 void FullCodeGenerator::TestContext::Plug(Label* materialize_true, | 644 void FullCodeGenerator::TestContext::Plug(Label* materialize_true, |
645 Label* materialize_false) const { | 645 Label* materialize_false) const { |
646 ASSERT(materialize_true == true_label_); | 646 DCHECK(materialize_true == true_label_); |
647 ASSERT(materialize_false == false_label_); | 647 DCHECK(materialize_false == false_label_); |
648 } | 648 } |
649 | 649 |
650 | 650 |
651 void FullCodeGenerator::EffectContext::Plug(bool flag) const { | 651 void FullCodeGenerator::EffectContext::Plug(bool flag) const { |
652 } | 652 } |
653 | 653 |
654 | 654 |
655 void FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const { | 655 void FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const { |
656 Heap::RootListIndex value_root_index = | 656 Heap::RootListIndex value_root_index = |
657 flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; | 657 flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; |
(...skipping 42 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 __ b(NegateCondition(cond), if_false); | 701 __ b(NegateCondition(cond), if_false); |
702 } else { | 702 } else { |
703 __ b(cond, if_true); | 703 __ b(cond, if_true); |
704 __ b(if_false); | 704 __ b(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 __ ldr(dest, location); | 738 __ ldr(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 __ str(src, location); | 751 __ str(src, location); |
752 | 752 |
753 // Emit the write barrier code if the location is in the heap. | 753 // Emit the write barrier code if the location is in the heap. |
754 if (var->IsContextSlot()) { | 754 if (var->IsContextSlot()) { |
755 __ RecordWriteContextSlot(scratch0, | 755 __ RecordWriteContextSlot(scratch0, |
756 location.offset(), | 756 location.offset(), |
757 src, | 757 src, |
758 scratch1, | 758 scratch1, |
759 kLRHasBeenSaved, | 759 kLRHasBeenSaved, |
(...skipping 19 matching lines...) Expand all Loading... |
779 __ cmp(r0, ip); | 779 __ cmp(r0, ip); |
780 Split(eq, if_true, if_false, NULL); | 780 Split(eq, if_true, if_false, NULL); |
781 __ bind(&skip); | 781 __ bind(&skip); |
782 } | 782 } |
783 } | 783 } |
784 | 784 |
785 | 785 |
786 void FullCodeGenerator::EmitDebugCheckDeclarationContext(Variable* variable) { | 786 void FullCodeGenerator::EmitDebugCheckDeclarationContext(Variable* variable) { |
787 // The variable in the declaration always resides in the current function | 787 // The variable in the declaration always resides in the current function |
788 // context. | 788 // context. |
789 ASSERT_EQ(0, scope()->ContextChainLength(variable->scope())); | 789 DCHECK_EQ(0, scope()->ContextChainLength(variable->scope())); |
790 if (generate_debug_code_) { | 790 if (generate_debug_code_) { |
791 // Check that we're not inside a with or catch context. | 791 // Check that we're not inside a with or catch context. |
792 __ ldr(r1, FieldMemOperand(cp, HeapObject::kMapOffset)); | 792 __ ldr(r1, FieldMemOperand(cp, HeapObject::kMapOffset)); |
793 __ CompareRoot(r1, Heap::kWithContextMapRootIndex); | 793 __ CompareRoot(r1, Heap::kWithContextMapRootIndex); |
794 __ Check(ne, kDeclarationInWithContext); | 794 __ Check(ne, kDeclarationInWithContext); |
795 __ CompareRoot(r1, Heap::kCatchContextMapRootIndex); | 795 __ CompareRoot(r1, Heap::kCatchContextMapRootIndex); |
796 __ Check(ne, kDeclarationInCatchContext); | 796 __ Check(ne, kDeclarationInCatchContext); |
797 } | 797 } |
798 } | 798 } |
799 | 799 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
833 __ str(ip, ContextOperand(cp, variable->index())); | 833 __ str(ip, 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 __ mov(r2, Operand(variable->name())); | 841 __ mov(r2, 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 __ mov(r1, Operand(Smi::FromInt(attr))); | 846 __ mov(r1, 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(r0, Heap::kTheHoleValueRootIndex); | 852 __ LoadRoot(r0, Heap::kTheHoleValueRootIndex); |
853 __ Push(cp, r2, r1, r0); | 853 __ Push(cp, r2, r1, r0); |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
913 VisitForStackValue(declaration->fun()); | 913 VisitForStackValue(declaration->fun()); |
914 __ CallRuntime(Runtime::kDeclareLookupSlot, 4); | 914 __ CallRuntime(Runtime::kDeclareLookupSlot, 4); |
915 break; | 915 break; |
916 } | 916 } |
917 } | 917 } |
918 } | 918 } |
919 | 919 |
920 | 920 |
921 void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) { | 921 void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) { |
922 Variable* variable = declaration->proxy()->var(); | 922 Variable* variable = declaration->proxy()->var(); |
923 ASSERT(variable->location() == Variable::CONTEXT); | 923 DCHECK(variable->location() == Variable::CONTEXT); |
924 ASSERT(variable->interface()->IsFrozen()); | 924 DCHECK(variable->interface()->IsFrozen()); |
925 | 925 |
926 Comment cmnt(masm_, "[ ModuleDeclaration"); | 926 Comment cmnt(masm_, "[ ModuleDeclaration"); |
927 EmitDebugCheckDeclarationContext(variable); | 927 EmitDebugCheckDeclarationContext(variable); |
928 | 928 |
929 // Load instance object. | 929 // Load instance object. |
930 __ LoadContext(r1, scope_->ContextChainLength(scope_->GlobalScope())); | 930 __ LoadContext(r1, scope_->ContextChainLength(scope_->GlobalScope())); |
931 __ ldr(r1, ContextOperand(r1, variable->interface()->Index())); | 931 __ ldr(r1, ContextOperand(r1, variable->interface()->Index())); |
932 __ ldr(r1, ContextOperand(r1, Context::EXTENSION_INDEX)); | 932 __ ldr(r1, ContextOperand(r1, Context::EXTENSION_INDEX)); |
933 | 933 |
934 // Assign it. | 934 // Assign it. |
(...skipping 468 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1403 | 1403 |
1404 ContextualMode mode = (typeof_state == INSIDE_TYPEOF) | 1404 ContextualMode mode = (typeof_state == INSIDE_TYPEOF) |
1405 ? NOT_CONTEXTUAL | 1405 ? NOT_CONTEXTUAL |
1406 : CONTEXTUAL; | 1406 : CONTEXTUAL; |
1407 CallLoadIC(mode); | 1407 CallLoadIC(mode); |
1408 } | 1408 } |
1409 | 1409 |
1410 | 1410 |
1411 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, | 1411 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, |
1412 Label* slow) { | 1412 Label* slow) { |
1413 ASSERT(var->IsContextSlot()); | 1413 DCHECK(var->IsContextSlot()); |
1414 Register context = cp; | 1414 Register context = cp; |
1415 Register next = r3; | 1415 Register next = r3; |
1416 Register temp = r4; | 1416 Register temp = r4; |
1417 | 1417 |
1418 for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { | 1418 for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { |
1419 if (s->num_heap_slots() > 0) { | 1419 if (s->num_heap_slots() > 0) { |
1420 if (s->calls_sloppy_eval()) { | 1420 if (s->calls_sloppy_eval()) { |
1421 // Check that extension is NULL. | 1421 // Check that extension is NULL. |
1422 __ ldr(temp, ContextOperand(context, Context::EXTENSION_INDEX)); | 1422 __ ldr(temp, ContextOperand(context, Context::EXTENSION_INDEX)); |
1423 __ tst(temp, temp); | 1423 __ tst(temp, temp); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1498 case Variable::LOCAL: | 1498 case Variable::LOCAL: |
1499 case Variable::CONTEXT: { | 1499 case Variable::CONTEXT: { |
1500 Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable" | 1500 Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable" |
1501 : "[ Stack variable"); | 1501 : "[ Stack variable"); |
1502 if (var->binding_needs_init()) { | 1502 if (var->binding_needs_init()) { |
1503 // var->scope() may be NULL when the proxy is located in eval code and | 1503 // var->scope() may be NULL when the proxy is located in eval code and |
1504 // refers to a potential outside binding. Currently those bindings are | 1504 // refers to a potential outside binding. Currently those bindings are |
1505 // always looked up dynamically, i.e. in that case | 1505 // always looked up dynamically, i.e. in that case |
1506 // var->location() == LOOKUP. | 1506 // var->location() == LOOKUP. |
1507 // always holds. | 1507 // always holds. |
1508 ASSERT(var->scope() != NULL); | 1508 DCHECK(var->scope() != NULL); |
1509 | 1509 |
1510 // Check if the binding really needs an initialization check. The check | 1510 // Check if the binding really needs an initialization check. The check |
1511 // can be skipped in the following situation: we have a LET or CONST | 1511 // can be skipped in the following situation: we have a LET or CONST |
1512 // binding in harmony mode, both the Variable and the VariableProxy have | 1512 // binding in harmony mode, both the Variable and the VariableProxy have |
1513 // the same declaration scope (i.e. they are both in global code, in the | 1513 // the same declaration scope (i.e. they are both in global code, in the |
1514 // same function or in the same eval code) and the VariableProxy is in | 1514 // same function or in the same eval code) and the VariableProxy is in |
1515 // the source physically located after the initializer of the variable. | 1515 // the source physically located after the initializer of the variable. |
1516 // | 1516 // |
1517 // We cannot skip any initialization checks for CONST in non-harmony | 1517 // We cannot skip any initialization checks for CONST in non-harmony |
1518 // mode because const variables may be declared but never initialized: | 1518 // mode because const variables may be declared but never initialized: |
1519 // if (false) { const x; }; var y = x; | 1519 // if (false) { const x; }; var y = x; |
1520 // | 1520 // |
1521 // The condition on the declaration scopes is a conservative check for | 1521 // The condition on the declaration scopes is a conservative check for |
1522 // nested functions that access a binding and are called before the | 1522 // nested functions that access a binding and are called before the |
1523 // binding is initialized: | 1523 // binding is initialized: |
1524 // function() { f(); let x = 1; function f() { x = 2; } } | 1524 // function() { f(); let x = 1; function f() { x = 2; } } |
1525 // | 1525 // |
1526 bool skip_init_check; | 1526 bool skip_init_check; |
1527 if (var->scope()->DeclarationScope() != scope()->DeclarationScope()) { | 1527 if (var->scope()->DeclarationScope() != scope()->DeclarationScope()) { |
1528 skip_init_check = false; | 1528 skip_init_check = false; |
1529 } else { | 1529 } else { |
1530 // Check that we always have valid source position. | 1530 // Check that we always have valid source position. |
1531 ASSERT(var->initializer_position() != RelocInfo::kNoPosition); | 1531 DCHECK(var->initializer_position() != RelocInfo::kNoPosition); |
1532 ASSERT(proxy->position() != RelocInfo::kNoPosition); | 1532 DCHECK(proxy->position() != RelocInfo::kNoPosition); |
1533 skip_init_check = var->mode() != CONST_LEGACY && | 1533 skip_init_check = var->mode() != CONST_LEGACY && |
1534 var->initializer_position() < proxy->position(); | 1534 var->initializer_position() < proxy->position(); |
1535 } | 1535 } |
1536 | 1536 |
1537 if (!skip_init_check) { | 1537 if (!skip_init_check) { |
1538 // Let and const need a read barrier. | 1538 // Let and const need a read barrier. |
1539 GetVar(r0, var); | 1539 GetVar(r0, var); |
1540 __ CompareRoot(r0, Heap::kTheHoleValueRootIndex); | 1540 __ CompareRoot(r0, Heap::kTheHoleValueRootIndex); |
1541 if (var->mode() == LET || var->mode() == CONST) { | 1541 if (var->mode() == LET || var->mode() == CONST) { |
1542 // Throw a reference error when using an uninitialized let/const | 1542 // Throw a reference error when using an uninitialized let/const |
1543 // binding in harmony mode. | 1543 // binding in harmony mode. |
1544 Label done; | 1544 Label done; |
1545 __ b(ne, &done); | 1545 __ b(ne, &done); |
1546 __ mov(r0, Operand(var->name())); | 1546 __ mov(r0, Operand(var->name())); |
1547 __ push(r0); | 1547 __ push(r0); |
1548 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 1548 __ CallRuntime(Runtime::kThrowReferenceError, 1); |
1549 __ bind(&done); | 1549 __ bind(&done); |
1550 } else { | 1550 } else { |
1551 // Uninitalized const bindings outside of harmony mode are unholed. | 1551 // Uninitalized const bindings outside of harmony mode are unholed. |
1552 ASSERT(var->mode() == CONST_LEGACY); | 1552 DCHECK(var->mode() == CONST_LEGACY); |
1553 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq); | 1553 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq); |
1554 } | 1554 } |
1555 context()->Plug(r0); | 1555 context()->Plug(r0); |
1556 break; | 1556 break; |
1557 } | 1557 } |
1558 } | 1558 } |
1559 context()->Plug(var); | 1559 context()->Plug(var); |
1560 break; | 1560 break; |
1561 } | 1561 } |
1562 | 1562 |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1681 Literal* key = property->key(); | 1681 Literal* key = property->key(); |
1682 Expression* value = property->value(); | 1682 Expression* value = property->value(); |
1683 if (!result_saved) { | 1683 if (!result_saved) { |
1684 __ push(r0); // Save result on stack | 1684 __ push(r0); // Save result on stack |
1685 result_saved = true; | 1685 result_saved = true; |
1686 } | 1686 } |
1687 switch (property->kind()) { | 1687 switch (property->kind()) { |
1688 case ObjectLiteral::Property::CONSTANT: | 1688 case ObjectLiteral::Property::CONSTANT: |
1689 UNREACHABLE(); | 1689 UNREACHABLE(); |
1690 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 1690 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
1691 ASSERT(!CompileTimeValue::IsCompileTimeValue(property->value())); | 1691 DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value())); |
1692 // Fall through. | 1692 // Fall through. |
1693 case ObjectLiteral::Property::COMPUTED: | 1693 case ObjectLiteral::Property::COMPUTED: |
1694 if (key->value()->IsInternalizedString()) { | 1694 if (key->value()->IsInternalizedString()) { |
1695 if (property->emit_store()) { | 1695 if (property->emit_store()) { |
1696 VisitForAccumulatorValue(value); | 1696 VisitForAccumulatorValue(value); |
1697 ASSERT(StoreIC::ValueRegister().is(r0)); | 1697 DCHECK(StoreIC::ValueRegister().is(r0)); |
1698 __ mov(StoreIC::NameRegister(), Operand(key->value())); | 1698 __ mov(StoreIC::NameRegister(), Operand(key->value())); |
1699 __ ldr(StoreIC::ReceiverRegister(), MemOperand(sp)); | 1699 __ ldr(StoreIC::ReceiverRegister(), MemOperand(sp)); |
1700 CallStoreIC(key->LiteralFeedbackId()); | 1700 CallStoreIC(key->LiteralFeedbackId()); |
1701 PrepareForBailoutForId(key->id(), NO_REGISTERS); | 1701 PrepareForBailoutForId(key->id(), NO_REGISTERS); |
1702 } else { | 1702 } else { |
1703 VisitForEffect(value); | 1703 VisitForEffect(value); |
1704 } | 1704 } |
1705 break; | 1705 break; |
1706 } | 1706 } |
1707 // Duplicate receiver on stack. | 1707 // Duplicate receiver on stack. |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1747 __ push(r0); | 1747 __ push(r0); |
1748 VisitForStackValue(it->first); | 1748 VisitForStackValue(it->first); |
1749 EmitAccessor(it->second->getter); | 1749 EmitAccessor(it->second->getter); |
1750 EmitAccessor(it->second->setter); | 1750 EmitAccessor(it->second->setter); |
1751 __ mov(r0, Operand(Smi::FromInt(NONE))); | 1751 __ mov(r0, Operand(Smi::FromInt(NONE))); |
1752 __ push(r0); | 1752 __ push(r0); |
1753 __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5); | 1753 __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5); |
1754 } | 1754 } |
1755 | 1755 |
1756 if (expr->has_function()) { | 1756 if (expr->has_function()) { |
1757 ASSERT(result_saved); | 1757 DCHECK(result_saved); |
1758 __ ldr(r0, MemOperand(sp)); | 1758 __ ldr(r0, MemOperand(sp)); |
1759 __ push(r0); | 1759 __ push(r0); |
1760 __ CallRuntime(Runtime::kToFastProperties, 1); | 1760 __ CallRuntime(Runtime::kToFastProperties, 1); |
1761 } | 1761 } |
1762 | 1762 |
1763 if (result_saved) { | 1763 if (result_saved) { |
1764 context()->PlugTOS(); | 1764 context()->PlugTOS(); |
1765 } else { | 1765 } else { |
1766 context()->Plug(r0); | 1766 context()->Plug(r0); |
1767 } | 1767 } |
1768 } | 1768 } |
1769 | 1769 |
1770 | 1770 |
1771 void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { | 1771 void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { |
1772 Comment cmnt(masm_, "[ ArrayLiteral"); | 1772 Comment cmnt(masm_, "[ ArrayLiteral"); |
1773 | 1773 |
1774 expr->BuildConstantElements(isolate()); | 1774 expr->BuildConstantElements(isolate()); |
1775 int flags = expr->depth() == 1 | 1775 int flags = expr->depth() == 1 |
1776 ? ArrayLiteral::kShallowElements | 1776 ? ArrayLiteral::kShallowElements |
1777 : ArrayLiteral::kNoFlags; | 1777 : ArrayLiteral::kNoFlags; |
1778 | 1778 |
1779 ZoneList<Expression*>* subexprs = expr->values(); | 1779 ZoneList<Expression*>* subexprs = expr->values(); |
1780 int length = subexprs->length(); | 1780 int length = subexprs->length(); |
1781 Handle<FixedArray> constant_elements = expr->constant_elements(); | 1781 Handle<FixedArray> constant_elements = expr->constant_elements(); |
1782 ASSERT_EQ(2, constant_elements->length()); | 1782 DCHECK_EQ(2, constant_elements->length()); |
1783 ElementsKind constant_elements_kind = | 1783 ElementsKind constant_elements_kind = |
1784 static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value()); | 1784 static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value()); |
1785 bool has_fast_elements = IsFastObjectElementsKind(constant_elements_kind); | 1785 bool has_fast_elements = IsFastObjectElementsKind(constant_elements_kind); |
1786 Handle<FixedArrayBase> constant_elements_values( | 1786 Handle<FixedArrayBase> constant_elements_values( |
1787 FixedArrayBase::cast(constant_elements->get(1))); | 1787 FixedArrayBase::cast(constant_elements->get(1))); |
1788 | 1788 |
1789 AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE; | 1789 AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE; |
1790 if (has_fast_elements && !FLAG_allocation_site_pretenuring) { | 1790 if (has_fast_elements && !FLAG_allocation_site_pretenuring) { |
1791 // If the only customer of allocation sites is transitioning, then | 1791 // If the only customer of allocation sites is transitioning, then |
1792 // we can turn it off if we don't have anywhere else to transition to. | 1792 // we can turn it off if we don't have anywhere else to transition to. |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1844 if (result_saved) { | 1844 if (result_saved) { |
1845 __ pop(); // literal index | 1845 __ pop(); // literal index |
1846 context()->PlugTOS(); | 1846 context()->PlugTOS(); |
1847 } else { | 1847 } else { |
1848 context()->Plug(r0); | 1848 context()->Plug(r0); |
1849 } | 1849 } |
1850 } | 1850 } |
1851 | 1851 |
1852 | 1852 |
1853 void FullCodeGenerator::VisitAssignment(Assignment* expr) { | 1853 void FullCodeGenerator::VisitAssignment(Assignment* expr) { |
1854 ASSERT(expr->target()->IsValidReferenceExpression()); | 1854 DCHECK(expr->target()->IsValidReferenceExpression()); |
1855 | 1855 |
1856 Comment cmnt(masm_, "[ Assignment"); | 1856 Comment cmnt(masm_, "[ Assignment"); |
1857 | 1857 |
1858 // Left-hand side can only be a property, a global or a (parameter or local) | 1858 // Left-hand side can only be a property, a global or a (parameter or local) |
1859 // slot. | 1859 // slot. |
1860 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 1860 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
1861 LhsKind assign_type = VARIABLE; | 1861 LhsKind assign_type = VARIABLE; |
1862 Property* property = expr->target()->AsProperty(); | 1862 Property* property = expr->target()->AsProperty(); |
1863 if (property != NULL) { | 1863 if (property != NULL) { |
1864 assign_type = (property->key()->IsPropertyName()) | 1864 assign_type = (property->key()->IsPropertyName()) |
(...skipping 109 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 __ mov(r1, Operand(Smi::FromInt(continuation.pos()))); | 1985 __ mov(r1, Operand(Smi::FromInt(continuation.pos()))); |
1986 __ str(r1, FieldMemOperand(r0, JSGeneratorObject::kContinuationOffset)); | 1986 __ str(r1, FieldMemOperand(r0, JSGeneratorObject::kContinuationOffset)); |
1987 __ str(cp, FieldMemOperand(r0, JSGeneratorObject::kContextOffset)); | 1987 __ str(cp, FieldMemOperand(r0, JSGeneratorObject::kContextOffset)); |
1988 __ mov(r1, cp); | 1988 __ mov(r1, cp); |
1989 __ RecordWriteField(r0, JSGeneratorObject::kContextOffset, r1, r2, | 1989 __ RecordWriteField(r0, JSGeneratorObject::kContextOffset, r1, r2, |
1990 kLRHasBeenSaved, kDontSaveFPRegs); | 1990 kLRHasBeenSaved, kDontSaveFPRegs); |
1991 __ add(r1, fp, Operand(StandardFrameConstants::kExpressionsOffset)); | 1991 __ add(r1, fp, Operand(StandardFrameConstants::kExpressionsOffset)); |
1992 __ cmp(sp, r1); | 1992 __ cmp(sp, r1); |
1993 __ b(eq, &post_runtime); | 1993 __ b(eq, &post_runtime); |
1994 __ push(r0); // generator object | 1994 __ push(r0); // generator object |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2047 __ PushTryHandler(StackHandler::CATCH, expr->index()); | 2047 __ PushTryHandler(StackHandler::CATCH, expr->index()); |
2048 const int handler_size = StackHandlerConstants::kSize; | 2048 const int handler_size = StackHandlerConstants::kSize; |
2049 __ push(r0); // result | 2049 __ push(r0); // result |
2050 __ jmp(&l_suspend); | 2050 __ jmp(&l_suspend); |
2051 __ bind(&l_continuation); | 2051 __ bind(&l_continuation); |
2052 __ jmp(&l_resume); | 2052 __ jmp(&l_resume); |
2053 __ bind(&l_suspend); | 2053 __ bind(&l_suspend); |
2054 const int generator_object_depth = kPointerSize + handler_size; | 2054 const int generator_object_depth = kPointerSize + handler_size; |
2055 __ ldr(r0, MemOperand(sp, generator_object_depth)); | 2055 __ ldr(r0, MemOperand(sp, generator_object_depth)); |
2056 __ push(r0); // g | 2056 __ push(r0); // g |
2057 ASSERT(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos())); | 2057 DCHECK(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos())); |
2058 __ mov(r1, Operand(Smi::FromInt(l_continuation.pos()))); | 2058 __ mov(r1, Operand(Smi::FromInt(l_continuation.pos()))); |
2059 __ str(r1, FieldMemOperand(r0, JSGeneratorObject::kContinuationOffset)); | 2059 __ str(r1, FieldMemOperand(r0, JSGeneratorObject::kContinuationOffset)); |
2060 __ str(cp, FieldMemOperand(r0, JSGeneratorObject::kContextOffset)); | 2060 __ str(cp, FieldMemOperand(r0, JSGeneratorObject::kContextOffset)); |
2061 __ mov(r1, cp); | 2061 __ mov(r1, cp); |
2062 __ RecordWriteField(r0, JSGeneratorObject::kContextOffset, r1, r2, | 2062 __ RecordWriteField(r0, JSGeneratorObject::kContextOffset, r1, r2, |
2063 kLRHasBeenSaved, kDontSaveFPRegs); | 2063 kLRHasBeenSaved, kDontSaveFPRegs); |
2064 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); | 2064 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); |
2065 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2065 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
2066 __ pop(r0); // result | 2066 __ pop(r0); // result |
2067 EmitReturnSequence(); | 2067 EmitReturnSequence(); |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2212 | 2212 |
2213 // Otherwise, we push holes for the operand stack and call the runtime to fix | 2213 // Otherwise, we push holes for the operand stack and call the runtime to fix |
2214 // up the stack and the handlers. | 2214 // up the stack and the handlers. |
2215 Label push_operand_holes, call_resume; | 2215 Label push_operand_holes, call_resume; |
2216 __ bind(&push_operand_holes); | 2216 __ bind(&push_operand_holes); |
2217 __ sub(r3, r3, Operand(1), SetCC); | 2217 __ sub(r3, r3, Operand(1), SetCC); |
2218 __ b(mi, &call_resume); | 2218 __ b(mi, &call_resume); |
2219 __ push(r2); | 2219 __ push(r2); |
2220 __ b(&push_operand_holes); | 2220 __ b(&push_operand_holes); |
2221 __ bind(&call_resume); | 2221 __ bind(&call_resume); |
2222 ASSERT(!result_register().is(r1)); | 2222 DCHECK(!result_register().is(r1)); |
2223 __ Push(r1, result_register()); | 2223 __ Push(r1, result_register()); |
2224 __ Push(Smi::FromInt(resume_mode)); | 2224 __ Push(Smi::FromInt(resume_mode)); |
2225 __ CallRuntime(Runtime::kResumeJSGeneratorObject, 3); | 2225 __ CallRuntime(Runtime::kResumeJSGeneratorObject, 3); |
2226 // Not reached: the runtime call returns elsewhere. | 2226 // Not reached: the runtime call returns elsewhere. |
2227 __ stop("not-reached"); | 2227 __ stop("not-reached"); |
2228 | 2228 |
2229 // Reach here when generator is closed. | 2229 // Reach here when generator is closed. |
2230 __ bind(&closed_state); | 2230 __ bind(&closed_state); |
2231 if (resume_mode == JSGeneratorObject::NEXT) { | 2231 if (resume_mode == JSGeneratorObject::NEXT) { |
2232 // Return completed iterator result when generator is closed. | 2232 // Return completed iterator result when generator is closed. |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2264 __ Push(Smi::FromInt(map->instance_size())); | 2264 __ Push(Smi::FromInt(map->instance_size())); |
2265 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); | 2265 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); |
2266 __ ldr(context_register(), | 2266 __ ldr(context_register(), |
2267 MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2267 MemOperand(fp, StandardFrameConstants::kContextOffset)); |
2268 | 2268 |
2269 __ bind(&allocated); | 2269 __ bind(&allocated); |
2270 __ mov(r1, Operand(map)); | 2270 __ mov(r1, Operand(map)); |
2271 __ pop(r2); | 2271 __ pop(r2); |
2272 __ mov(r3, Operand(isolate()->factory()->ToBoolean(done))); | 2272 __ mov(r3, Operand(isolate()->factory()->ToBoolean(done))); |
2273 __ mov(r4, Operand(isolate()->factory()->empty_fixed_array())); | 2273 __ mov(r4, Operand(isolate()->factory()->empty_fixed_array())); |
2274 ASSERT_EQ(map->instance_size(), 5 * kPointerSize); | 2274 DCHECK_EQ(map->instance_size(), 5 * kPointerSize); |
2275 __ str(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); | 2275 __ str(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); |
2276 __ str(r4, FieldMemOperand(r0, JSObject::kPropertiesOffset)); | 2276 __ str(r4, FieldMemOperand(r0, JSObject::kPropertiesOffset)); |
2277 __ str(r4, FieldMemOperand(r0, JSObject::kElementsOffset)); | 2277 __ str(r4, FieldMemOperand(r0, JSObject::kElementsOffset)); |
2278 __ str(r2, | 2278 __ str(r2, |
2279 FieldMemOperand(r0, JSGeneratorObject::kResultValuePropertyOffset)); | 2279 FieldMemOperand(r0, JSGeneratorObject::kResultValuePropertyOffset)); |
2280 __ str(r3, | 2280 __ str(r3, |
2281 FieldMemOperand(r0, JSGeneratorObject::kResultDonePropertyOffset)); | 2281 FieldMemOperand(r0, JSGeneratorObject::kResultDonePropertyOffset)); |
2282 | 2282 |
2283 // Only the value field needs a write barrier, as the other values are in the | 2283 // Only the value field needs a write barrier, as the other values are in the |
2284 // root set. | 2284 // root set. |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2414 __ pop(r1); | 2414 __ pop(r1); |
2415 BinaryOpICStub stub(isolate(), op, mode); | 2415 BinaryOpICStub stub(isolate(), op, mode); |
2416 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. | 2416 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. |
2417 CallIC(stub.GetCode(), expr->BinaryOperationFeedbackId()); | 2417 CallIC(stub.GetCode(), expr->BinaryOperationFeedbackId()); |
2418 patch_site.EmitPatchInfo(); | 2418 patch_site.EmitPatchInfo(); |
2419 context()->Plug(r0); | 2419 context()->Plug(r0); |
2420 } | 2420 } |
2421 | 2421 |
2422 | 2422 |
2423 void FullCodeGenerator::EmitAssignment(Expression* expr) { | 2423 void FullCodeGenerator::EmitAssignment(Expression* expr) { |
2424 ASSERT(expr->IsValidReferenceExpression()); | 2424 DCHECK(expr->IsValidReferenceExpression()); |
2425 | 2425 |
2426 // Left-hand side can only be a property, a global or a (parameter or local) | 2426 // Left-hand side can only be a property, a global or a (parameter or local) |
2427 // slot. | 2427 // slot. |
2428 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 2428 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
2429 LhsKind assign_type = VARIABLE; | 2429 LhsKind assign_type = VARIABLE; |
2430 Property* prop = expr->AsProperty(); | 2430 Property* prop = expr->AsProperty(); |
2431 if (prop != NULL) { | 2431 if (prop != NULL) { |
2432 assign_type = (prop->key()->IsPropertyName()) | 2432 assign_type = (prop->key()->IsPropertyName()) |
2433 ? NAMED_PROPERTY | 2433 ? NAMED_PROPERTY |
2434 : KEYED_PROPERTY; | 2434 : KEYED_PROPERTY; |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2483 | 2483 |
2484 void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op) { | 2484 void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op) { |
2485 if (var->IsUnallocated()) { | 2485 if (var->IsUnallocated()) { |
2486 // Global var, const, or let. | 2486 // Global var, const, or let. |
2487 __ mov(StoreIC::NameRegister(), Operand(var->name())); | 2487 __ mov(StoreIC::NameRegister(), Operand(var->name())); |
2488 __ ldr(StoreIC::ReceiverRegister(), GlobalObjectOperand()); | 2488 __ ldr(StoreIC::ReceiverRegister(), GlobalObjectOperand()); |
2489 CallStoreIC(); | 2489 CallStoreIC(); |
2490 | 2490 |
2491 } else if (op == Token::INIT_CONST_LEGACY) { | 2491 } else if (op == Token::INIT_CONST_LEGACY) { |
2492 // Const initializers need a write barrier. | 2492 // Const initializers need a write barrier. |
2493 ASSERT(!var->IsParameter()); // No const parameters. | 2493 DCHECK(!var->IsParameter()); // No const parameters. |
2494 if (var->IsLookupSlot()) { | 2494 if (var->IsLookupSlot()) { |
2495 __ push(r0); | 2495 __ push(r0); |
2496 __ mov(r0, Operand(var->name())); | 2496 __ mov(r0, Operand(var->name())); |
2497 __ Push(cp, r0); // Context and name. | 2497 __ Push(cp, r0); // Context and name. |
2498 __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot, 3); | 2498 __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot, 3); |
2499 } else { | 2499 } else { |
2500 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); | 2500 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
2501 Label skip; | 2501 Label skip; |
2502 MemOperand location = VarOperand(var, r1); | 2502 MemOperand location = VarOperand(var, r1); |
2503 __ ldr(r2, location); | 2503 __ ldr(r2, location); |
2504 __ CompareRoot(r2, Heap::kTheHoleValueRootIndex); | 2504 __ CompareRoot(r2, Heap::kTheHoleValueRootIndex); |
2505 __ b(ne, &skip); | 2505 __ b(ne, &skip); |
2506 EmitStoreToStackLocalOrContextSlot(var, location); | 2506 EmitStoreToStackLocalOrContextSlot(var, location); |
2507 __ bind(&skip); | 2507 __ bind(&skip); |
2508 } | 2508 } |
2509 | 2509 |
2510 } else if (var->mode() == LET && op != Token::INIT_LET) { | 2510 } else if (var->mode() == LET && op != Token::INIT_LET) { |
2511 // Non-initializing assignment to let variable needs a write barrier. | 2511 // Non-initializing assignment to let variable needs a write barrier. |
2512 ASSERT(!var->IsLookupSlot()); | 2512 DCHECK(!var->IsLookupSlot()); |
2513 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); | 2513 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
2514 Label assign; | 2514 Label assign; |
2515 MemOperand location = VarOperand(var, r1); | 2515 MemOperand location = VarOperand(var, r1); |
2516 __ ldr(r3, location); | 2516 __ ldr(r3, location); |
2517 __ CompareRoot(r3, Heap::kTheHoleValueRootIndex); | 2517 __ CompareRoot(r3, Heap::kTheHoleValueRootIndex); |
2518 __ b(ne, &assign); | 2518 __ b(ne, &assign); |
2519 __ mov(r3, Operand(var->name())); | 2519 __ mov(r3, Operand(var->name())); |
2520 __ push(r3); | 2520 __ push(r3); |
2521 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 2521 __ CallRuntime(Runtime::kThrowReferenceError, 1); |
2522 // Perform the assignment. | 2522 // Perform the assignment. |
2523 __ bind(&assign); | 2523 __ bind(&assign); |
2524 EmitStoreToStackLocalOrContextSlot(var, location); | 2524 EmitStoreToStackLocalOrContextSlot(var, location); |
2525 | 2525 |
2526 } else if (!var->is_const_mode() || op == Token::INIT_CONST) { | 2526 } else if (!var->is_const_mode() || op == Token::INIT_CONST) { |
2527 if (var->IsLookupSlot()) { | 2527 if (var->IsLookupSlot()) { |
2528 // Assignment to var. | 2528 // Assignment to var. |
2529 __ push(r0); // Value. | 2529 __ push(r0); // Value. |
2530 __ mov(r1, Operand(var->name())); | 2530 __ mov(r1, Operand(var->name())); |
2531 __ mov(r0, Operand(Smi::FromInt(strict_mode()))); | 2531 __ mov(r0, Operand(Smi::FromInt(strict_mode()))); |
2532 __ Push(cp, r1, r0); // Context, name, strict mode. | 2532 __ Push(cp, r1, r0); // Context, name, strict mode. |
2533 __ CallRuntime(Runtime::kStoreLookupSlot, 4); | 2533 __ CallRuntime(Runtime::kStoreLookupSlot, 4); |
2534 } else { | 2534 } else { |
2535 // Assignment to var or initializing assignment to let/const in harmony | 2535 // Assignment to var or initializing assignment to let/const in harmony |
2536 // mode. | 2536 // mode. |
2537 ASSERT((var->IsStackAllocated() || var->IsContextSlot())); | 2537 DCHECK((var->IsStackAllocated() || var->IsContextSlot())); |
2538 MemOperand location = VarOperand(var, r1); | 2538 MemOperand location = VarOperand(var, r1); |
2539 if (generate_debug_code_ && op == Token::INIT_LET) { | 2539 if (generate_debug_code_ && op == Token::INIT_LET) { |
2540 // Check for an uninitialized let binding. | 2540 // Check for an uninitialized let binding. |
2541 __ ldr(r2, location); | 2541 __ ldr(r2, location); |
2542 __ CompareRoot(r2, Heap::kTheHoleValueRootIndex); | 2542 __ CompareRoot(r2, Heap::kTheHoleValueRootIndex); |
2543 __ Check(eq, kLetBindingReInitialization); | 2543 __ Check(eq, kLetBindingReInitialization); |
2544 } | 2544 } |
2545 EmitStoreToStackLocalOrContextSlot(var, location); | 2545 EmitStoreToStackLocalOrContextSlot(var, location); |
2546 } | 2546 } |
2547 } | 2547 } |
2548 // Non-initializing assignments to consts are ignored. | 2548 // Non-initializing assignments to consts are ignored. |
2549 } | 2549 } |
2550 | 2550 |
2551 | 2551 |
2552 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 2552 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
2553 // Assignment to a property, using a named store IC. | 2553 // Assignment to a property, using a named store IC. |
2554 Property* prop = expr->target()->AsProperty(); | 2554 Property* prop = expr->target()->AsProperty(); |
2555 ASSERT(prop != NULL); | 2555 DCHECK(prop != NULL); |
2556 ASSERT(prop->key()->IsLiteral()); | 2556 DCHECK(prop->key()->IsLiteral()); |
2557 | 2557 |
2558 // Record source code position before IC call. | 2558 // Record source code position before IC call. |
2559 SetSourcePosition(expr->position()); | 2559 SetSourcePosition(expr->position()); |
2560 __ mov(StoreIC::NameRegister(), Operand(prop->key()->AsLiteral()->value())); | 2560 __ mov(StoreIC::NameRegister(), Operand(prop->key()->AsLiteral()->value())); |
2561 __ pop(StoreIC::ReceiverRegister()); | 2561 __ pop(StoreIC::ReceiverRegister()); |
2562 CallStoreIC(expr->AssignmentFeedbackId()); | 2562 CallStoreIC(expr->AssignmentFeedbackId()); |
2563 | 2563 |
2564 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 2564 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
2565 context()->Plug(r0); | 2565 context()->Plug(r0); |
2566 } | 2566 } |
2567 | 2567 |
2568 | 2568 |
2569 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 2569 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
2570 // Assignment to a property, using a keyed store IC. | 2570 // Assignment to a property, using a keyed store IC. |
2571 | 2571 |
2572 // Record source code position before IC call. | 2572 // Record source code position before IC call. |
2573 SetSourcePosition(expr->position()); | 2573 SetSourcePosition(expr->position()); |
2574 __ Pop(KeyedStoreIC::ReceiverRegister(), KeyedStoreIC::NameRegister()); | 2574 __ Pop(KeyedStoreIC::ReceiverRegister(), KeyedStoreIC::NameRegister()); |
2575 ASSERT(KeyedStoreIC::ValueRegister().is(r0)); | 2575 DCHECK(KeyedStoreIC::ValueRegister().is(r0)); |
2576 | 2576 |
2577 Handle<Code> ic = strict_mode() == SLOPPY | 2577 Handle<Code> ic = strict_mode() == SLOPPY |
2578 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 2578 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
2579 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 2579 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
2580 CallIC(ic, expr->AssignmentFeedbackId()); | 2580 CallIC(ic, expr->AssignmentFeedbackId()); |
2581 | 2581 |
2582 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 2582 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
2583 context()->Plug(r0); | 2583 context()->Plug(r0); |
2584 } | 2584 } |
2585 | 2585 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2627 if (call_type == CallIC::FUNCTION) { | 2627 if (call_type == CallIC::FUNCTION) { |
2628 { StackValueContext context(this); | 2628 { StackValueContext context(this); |
2629 EmitVariableLoad(callee->AsVariableProxy()); | 2629 EmitVariableLoad(callee->AsVariableProxy()); |
2630 PrepareForBailout(callee, NO_REGISTERS); | 2630 PrepareForBailout(callee, NO_REGISTERS); |
2631 } | 2631 } |
2632 // Push undefined as receiver. This is patched in the method prologue if it | 2632 // Push undefined as receiver. This is patched in the method prologue if it |
2633 // is a sloppy mode method. | 2633 // is a sloppy mode method. |
2634 __ Push(isolate()->factory()->undefined_value()); | 2634 __ Push(isolate()->factory()->undefined_value()); |
2635 } else { | 2635 } else { |
2636 // Load the function from the receiver. | 2636 // Load the function from the receiver. |
2637 ASSERT(callee->IsProperty()); | 2637 DCHECK(callee->IsProperty()); |
2638 __ ldr(LoadIC::ReceiverRegister(), MemOperand(sp, 0)); | 2638 __ ldr(LoadIC::ReceiverRegister(), MemOperand(sp, 0)); |
2639 EmitNamedPropertyLoad(callee->AsProperty()); | 2639 EmitNamedPropertyLoad(callee->AsProperty()); |
2640 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); | 2640 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); |
2641 // Push the target function under the receiver. | 2641 // Push the target function under the receiver. |
2642 __ ldr(ip, MemOperand(sp, 0)); | 2642 __ ldr(ip, MemOperand(sp, 0)); |
2643 __ push(ip); | 2643 __ push(ip); |
2644 __ str(r0, MemOperand(sp, kPointerSize)); | 2644 __ str(r0, MemOperand(sp, kPointerSize)); |
2645 } | 2645 } |
2646 | 2646 |
2647 EmitCall(expr, call_type); | 2647 EmitCall(expr, call_type); |
2648 } | 2648 } |
2649 | 2649 |
2650 | 2650 |
2651 // Code common for calls using the IC. | 2651 // Code common for calls using the IC. |
2652 void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr, | 2652 void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr, |
2653 Expression* key) { | 2653 Expression* key) { |
2654 // Load the key. | 2654 // Load the key. |
2655 VisitForAccumulatorValue(key); | 2655 VisitForAccumulatorValue(key); |
2656 | 2656 |
2657 Expression* callee = expr->expression(); | 2657 Expression* callee = expr->expression(); |
2658 | 2658 |
2659 // Load the function from the receiver. | 2659 // Load the function from the receiver. |
2660 ASSERT(callee->IsProperty()); | 2660 DCHECK(callee->IsProperty()); |
2661 __ ldr(LoadIC::ReceiverRegister(), MemOperand(sp, 0)); | 2661 __ ldr(LoadIC::ReceiverRegister(), MemOperand(sp, 0)); |
2662 __ Move(LoadIC::NameRegister(), r0); | 2662 __ Move(LoadIC::NameRegister(), r0); |
2663 EmitKeyedPropertyLoad(callee->AsProperty()); | 2663 EmitKeyedPropertyLoad(callee->AsProperty()); |
2664 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); | 2664 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); |
2665 | 2665 |
2666 // Push the target function under the receiver. | 2666 // Push the target function under the receiver. |
2667 __ ldr(ip, MemOperand(sp, 0)); | 2667 __ ldr(ip, MemOperand(sp, 0)); |
2668 __ push(ip); | 2668 __ push(ip); |
2669 __ str(r0, MemOperand(sp, kPointerSize)); | 2669 __ str(r0, MemOperand(sp, kPointerSize)); |
2670 | 2670 |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2783 | 2783 |
2784 { PreservePositionScope scope(masm()->positions_recorder()); | 2784 { PreservePositionScope scope(masm()->positions_recorder()); |
2785 // Generate code for loading from variables potentially shadowed | 2785 // Generate code for loading from variables potentially shadowed |
2786 // by eval-introduced variables. | 2786 // by eval-introduced variables. |
2787 EmitDynamicLookupFastCase(proxy, NOT_INSIDE_TYPEOF, &slow, &done); | 2787 EmitDynamicLookupFastCase(proxy, NOT_INSIDE_TYPEOF, &slow, &done); |
2788 } | 2788 } |
2789 | 2789 |
2790 __ bind(&slow); | 2790 __ bind(&slow); |
2791 // Call the runtime to find the function to call (returned in r0) | 2791 // Call the runtime to find the function to call (returned in r0) |
2792 // and the object holding it (returned in edx). | 2792 // and the object holding it (returned in edx). |
2793 ASSERT(!context_register().is(r2)); | 2793 DCHECK(!context_register().is(r2)); |
2794 __ mov(r2, Operand(proxy->name())); | 2794 __ mov(r2, Operand(proxy->name())); |
2795 __ Push(context_register(), r2); | 2795 __ Push(context_register(), r2); |
2796 __ CallRuntime(Runtime::kLoadLookupSlot, 2); | 2796 __ CallRuntime(Runtime::kLoadLookupSlot, 2); |
2797 __ Push(r0, r1); // Function, receiver. | 2797 __ Push(r0, r1); // Function, receiver. |
2798 | 2798 |
2799 // If fast case code has been generated, emit code to push the | 2799 // If fast case code has been generated, emit code to push the |
2800 // function and receiver and have the slow path jump around this | 2800 // function and receiver and have the slow path jump around this |
2801 // code. | 2801 // code. |
2802 if (done.is_linked()) { | 2802 if (done.is_linked()) { |
2803 Label call; | 2803 Label call; |
(...skipping 15 matching lines...) Expand all Loading... |
2819 Property* property = callee->AsProperty(); | 2819 Property* property = callee->AsProperty(); |
2820 { PreservePositionScope scope(masm()->positions_recorder()); | 2820 { PreservePositionScope scope(masm()->positions_recorder()); |
2821 VisitForStackValue(property->obj()); | 2821 VisitForStackValue(property->obj()); |
2822 } | 2822 } |
2823 if (property->key()->IsPropertyName()) { | 2823 if (property->key()->IsPropertyName()) { |
2824 EmitCallWithLoadIC(expr); | 2824 EmitCallWithLoadIC(expr); |
2825 } else { | 2825 } else { |
2826 EmitKeyedCallWithLoadIC(expr, property->key()); | 2826 EmitKeyedCallWithLoadIC(expr, property->key()); |
2827 } | 2827 } |
2828 } else { | 2828 } else { |
2829 ASSERT(call_type == Call::OTHER_CALL); | 2829 DCHECK(call_type == Call::OTHER_CALL); |
2830 // Call to an arbitrary expression not handled specially above. | 2830 // Call to an arbitrary expression not handled specially above. |
2831 { PreservePositionScope scope(masm()->positions_recorder()); | 2831 { PreservePositionScope scope(masm()->positions_recorder()); |
2832 VisitForStackValue(callee); | 2832 VisitForStackValue(callee); |
2833 } | 2833 } |
2834 __ LoadRoot(r1, Heap::kUndefinedValueRootIndex); | 2834 __ LoadRoot(r1, Heap::kUndefinedValueRootIndex); |
2835 __ push(r1); | 2835 __ push(r1); |
2836 // Emit function call. | 2836 // Emit function call. |
2837 EmitCall(expr); | 2837 EmitCall(expr); |
2838 } | 2838 } |
2839 | 2839 |
2840 #ifdef DEBUG | 2840 #ifdef DEBUG |
2841 // RecordJSReturnSite should have been called. | 2841 // RecordJSReturnSite should have been called. |
2842 ASSERT(expr->return_is_recorded_); | 2842 DCHECK(expr->return_is_recorded_); |
2843 #endif | 2843 #endif |
2844 } | 2844 } |
2845 | 2845 |
2846 | 2846 |
2847 void FullCodeGenerator::VisitCallNew(CallNew* expr) { | 2847 void FullCodeGenerator::VisitCallNew(CallNew* expr) { |
2848 Comment cmnt(masm_, "[ CallNew"); | 2848 Comment cmnt(masm_, "[ CallNew"); |
2849 // According to ECMA-262, section 11.2.2, page 44, the function | 2849 // According to ECMA-262, section 11.2.2, page 44, the function |
2850 // expression in new calls must be evaluated before the | 2850 // expression in new calls must be evaluated before the |
2851 // arguments. | 2851 // arguments. |
2852 | 2852 |
(...skipping 13 matching lines...) Expand all Loading... |
2866 // constructor invocation. | 2866 // constructor invocation. |
2867 SetSourcePosition(expr->position()); | 2867 SetSourcePosition(expr->position()); |
2868 | 2868 |
2869 // Load function and argument count into r1 and r0. | 2869 // Load function and argument count into r1 and r0. |
2870 __ mov(r0, Operand(arg_count)); | 2870 __ mov(r0, Operand(arg_count)); |
2871 __ ldr(r1, MemOperand(sp, arg_count * kPointerSize)); | 2871 __ ldr(r1, MemOperand(sp, arg_count * kPointerSize)); |
2872 | 2872 |
2873 // Record call targets in unoptimized code. | 2873 // Record call targets in unoptimized code. |
2874 if (FLAG_pretenuring_call_new) { | 2874 if (FLAG_pretenuring_call_new) { |
2875 EnsureSlotContainsAllocationSite(expr->AllocationSiteFeedbackSlot()); | 2875 EnsureSlotContainsAllocationSite(expr->AllocationSiteFeedbackSlot()); |
2876 ASSERT(expr->AllocationSiteFeedbackSlot() == | 2876 DCHECK(expr->AllocationSiteFeedbackSlot() == |
2877 expr->CallNewFeedbackSlot() + 1); | 2877 expr->CallNewFeedbackSlot() + 1); |
2878 } | 2878 } |
2879 | 2879 |
2880 __ Move(r2, FeedbackVector()); | 2880 __ Move(r2, FeedbackVector()); |
2881 __ mov(r3, Operand(Smi::FromInt(expr->CallNewFeedbackSlot()))); | 2881 __ mov(r3, Operand(Smi::FromInt(expr->CallNewFeedbackSlot()))); |
2882 | 2882 |
2883 CallConstructStub stub(isolate(), RECORD_CONSTRUCTOR_TARGET); | 2883 CallConstructStub stub(isolate(), RECORD_CONSTRUCTOR_TARGET); |
2884 __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL); | 2884 __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL); |
2885 PrepareForBailoutForId(expr->ReturnId(), TOS_REG); | 2885 PrepareForBailoutForId(expr->ReturnId(), TOS_REG); |
2886 context()->Plug(r0); | 2886 context()->Plug(r0); |
2887 } | 2887 } |
2888 | 2888 |
2889 | 2889 |
2890 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { | 2890 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { |
2891 ZoneList<Expression*>* args = expr->arguments(); | 2891 ZoneList<Expression*>* args = expr->arguments(); |
2892 ASSERT(args->length() == 1); | 2892 DCHECK(args->length() == 1); |
2893 | 2893 |
2894 VisitForAccumulatorValue(args->at(0)); | 2894 VisitForAccumulatorValue(args->at(0)); |
2895 | 2895 |
2896 Label materialize_true, materialize_false; | 2896 Label materialize_true, materialize_false; |
2897 Label* if_true = NULL; | 2897 Label* if_true = NULL; |
2898 Label* if_false = NULL; | 2898 Label* if_false = NULL; |
2899 Label* fall_through = NULL; | 2899 Label* fall_through = NULL; |
2900 context()->PrepareTest(&materialize_true, &materialize_false, | 2900 context()->PrepareTest(&materialize_true, &materialize_false, |
2901 &if_true, &if_false, &fall_through); | 2901 &if_true, &if_false, &fall_through); |
2902 | 2902 |
2903 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 2903 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
2904 __ SmiTst(r0); | 2904 __ SmiTst(r0); |
2905 Split(eq, if_true, if_false, fall_through); | 2905 Split(eq, if_true, if_false, fall_through); |
2906 | 2906 |
2907 context()->Plug(if_true, if_false); | 2907 context()->Plug(if_true, if_false); |
2908 } | 2908 } |
2909 | 2909 |
2910 | 2910 |
2911 void FullCodeGenerator::EmitIsNonNegativeSmi(CallRuntime* expr) { | 2911 void FullCodeGenerator::EmitIsNonNegativeSmi(CallRuntime* expr) { |
2912 ZoneList<Expression*>* args = expr->arguments(); | 2912 ZoneList<Expression*>* args = expr->arguments(); |
2913 ASSERT(args->length() == 1); | 2913 DCHECK(args->length() == 1); |
2914 | 2914 |
2915 VisitForAccumulatorValue(args->at(0)); | 2915 VisitForAccumulatorValue(args->at(0)); |
2916 | 2916 |
2917 Label materialize_true, materialize_false; | 2917 Label materialize_true, materialize_false; |
2918 Label* if_true = NULL; | 2918 Label* if_true = NULL; |
2919 Label* if_false = NULL; | 2919 Label* if_false = NULL; |
2920 Label* fall_through = NULL; | 2920 Label* fall_through = NULL; |
2921 context()->PrepareTest(&materialize_true, &materialize_false, | 2921 context()->PrepareTest(&materialize_true, &materialize_false, |
2922 &if_true, &if_false, &fall_through); | 2922 &if_true, &if_false, &fall_through); |
2923 | 2923 |
2924 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 2924 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
2925 __ NonNegativeSmiTst(r0); | 2925 __ NonNegativeSmiTst(r0); |
2926 Split(eq, if_true, if_false, fall_through); | 2926 Split(eq, if_true, if_false, fall_through); |
2927 | 2927 |
2928 context()->Plug(if_true, if_false); | 2928 context()->Plug(if_true, if_false); |
2929 } | 2929 } |
2930 | 2930 |
2931 | 2931 |
2932 void FullCodeGenerator::EmitIsObject(CallRuntime* expr) { | 2932 void FullCodeGenerator::EmitIsObject(CallRuntime* expr) { |
2933 ZoneList<Expression*>* args = expr->arguments(); | 2933 ZoneList<Expression*>* args = expr->arguments(); |
2934 ASSERT(args->length() == 1); | 2934 DCHECK(args->length() == 1); |
2935 | 2935 |
2936 VisitForAccumulatorValue(args->at(0)); | 2936 VisitForAccumulatorValue(args->at(0)); |
2937 | 2937 |
2938 Label materialize_true, materialize_false; | 2938 Label materialize_true, materialize_false; |
2939 Label* if_true = NULL; | 2939 Label* if_true = NULL; |
2940 Label* if_false = NULL; | 2940 Label* if_false = NULL; |
2941 Label* fall_through = NULL; | 2941 Label* fall_through = NULL; |
2942 context()->PrepareTest(&materialize_true, &materialize_false, | 2942 context()->PrepareTest(&materialize_true, &materialize_false, |
2943 &if_true, &if_false, &fall_through); | 2943 &if_true, &if_false, &fall_through); |
2944 | 2944 |
(...skipping 12 matching lines...) Expand all Loading... |
2957 __ cmp(r1, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); | 2957 __ cmp(r1, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); |
2958 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 2958 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
2959 Split(le, if_true, if_false, fall_through); | 2959 Split(le, if_true, if_false, fall_through); |
2960 | 2960 |
2961 context()->Plug(if_true, if_false); | 2961 context()->Plug(if_true, if_false); |
2962 } | 2962 } |
2963 | 2963 |
2964 | 2964 |
2965 void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) { | 2965 void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) { |
2966 ZoneList<Expression*>* args = expr->arguments(); | 2966 ZoneList<Expression*>* args = expr->arguments(); |
2967 ASSERT(args->length() == 1); | 2967 DCHECK(args->length() == 1); |
2968 | 2968 |
2969 VisitForAccumulatorValue(args->at(0)); | 2969 VisitForAccumulatorValue(args->at(0)); |
2970 | 2970 |
2971 Label materialize_true, materialize_false; | 2971 Label materialize_true, materialize_false; |
2972 Label* if_true = NULL; | 2972 Label* if_true = NULL; |
2973 Label* if_false = NULL; | 2973 Label* if_false = NULL; |
2974 Label* fall_through = NULL; | 2974 Label* fall_through = NULL; |
2975 context()->PrepareTest(&materialize_true, &materialize_false, | 2975 context()->PrepareTest(&materialize_true, &materialize_false, |
2976 &if_true, &if_false, &fall_through); | 2976 &if_true, &if_false, &fall_through); |
2977 | 2977 |
2978 __ JumpIfSmi(r0, if_false); | 2978 __ JumpIfSmi(r0, if_false); |
2979 __ CompareObjectType(r0, r1, r1, FIRST_SPEC_OBJECT_TYPE); | 2979 __ CompareObjectType(r0, r1, r1, FIRST_SPEC_OBJECT_TYPE); |
2980 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 2980 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
2981 Split(ge, if_true, if_false, fall_through); | 2981 Split(ge, if_true, if_false, fall_through); |
2982 | 2982 |
2983 context()->Plug(if_true, if_false); | 2983 context()->Plug(if_true, if_false); |
2984 } | 2984 } |
2985 | 2985 |
2986 | 2986 |
2987 void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) { | 2987 void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) { |
2988 ZoneList<Expression*>* args = expr->arguments(); | 2988 ZoneList<Expression*>* args = expr->arguments(); |
2989 ASSERT(args->length() == 1); | 2989 DCHECK(args->length() == 1); |
2990 | 2990 |
2991 VisitForAccumulatorValue(args->at(0)); | 2991 VisitForAccumulatorValue(args->at(0)); |
2992 | 2992 |
2993 Label materialize_true, materialize_false; | 2993 Label materialize_true, materialize_false; |
2994 Label* if_true = NULL; | 2994 Label* if_true = NULL; |
2995 Label* if_false = NULL; | 2995 Label* if_false = NULL; |
2996 Label* fall_through = NULL; | 2996 Label* fall_through = NULL; |
2997 context()->PrepareTest(&materialize_true, &materialize_false, | 2997 context()->PrepareTest(&materialize_true, &materialize_false, |
2998 &if_true, &if_false, &fall_through); | 2998 &if_true, &if_false, &fall_through); |
2999 | 2999 |
3000 __ JumpIfSmi(r0, if_false); | 3000 __ JumpIfSmi(r0, if_false); |
3001 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); | 3001 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); |
3002 __ ldrb(r1, FieldMemOperand(r1, Map::kBitFieldOffset)); | 3002 __ ldrb(r1, FieldMemOperand(r1, Map::kBitFieldOffset)); |
3003 __ tst(r1, Operand(1 << Map::kIsUndetectable)); | 3003 __ tst(r1, Operand(1 << Map::kIsUndetectable)); |
3004 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 3004 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
3005 Split(ne, if_true, if_false, fall_through); | 3005 Split(ne, if_true, if_false, fall_through); |
3006 | 3006 |
3007 context()->Plug(if_true, if_false); | 3007 context()->Plug(if_true, if_false); |
3008 } | 3008 } |
3009 | 3009 |
3010 | 3010 |
3011 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( | 3011 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( |
3012 CallRuntime* expr) { | 3012 CallRuntime* expr) { |
3013 ZoneList<Expression*>* args = expr->arguments(); | 3013 ZoneList<Expression*>* args = expr->arguments(); |
3014 ASSERT(args->length() == 1); | 3014 DCHECK(args->length() == 1); |
3015 | 3015 |
3016 VisitForAccumulatorValue(args->at(0)); | 3016 VisitForAccumulatorValue(args->at(0)); |
3017 | 3017 |
3018 Label materialize_true, materialize_false, skip_lookup; | 3018 Label materialize_true, materialize_false, skip_lookup; |
3019 Label* if_true = NULL; | 3019 Label* if_true = NULL; |
3020 Label* if_false = NULL; | 3020 Label* if_false = NULL; |
3021 Label* fall_through = NULL; | 3021 Label* fall_through = NULL; |
3022 context()->PrepareTest(&materialize_true, &materialize_false, | 3022 context()->PrepareTest(&materialize_true, &materialize_false, |
3023 &if_true, &if_false, &fall_through); | 3023 &if_true, &if_false, &fall_through); |
3024 | 3024 |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3092 __ cmp(r2, r3); | 3092 __ cmp(r2, r3); |
3093 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 3093 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
3094 Split(eq, if_true, if_false, fall_through); | 3094 Split(eq, if_true, if_false, fall_through); |
3095 | 3095 |
3096 context()->Plug(if_true, if_false); | 3096 context()->Plug(if_true, if_false); |
3097 } | 3097 } |
3098 | 3098 |
3099 | 3099 |
3100 void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) { | 3100 void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) { |
3101 ZoneList<Expression*>* args = expr->arguments(); | 3101 ZoneList<Expression*>* args = expr->arguments(); |
3102 ASSERT(args->length() == 1); | 3102 DCHECK(args->length() == 1); |
3103 | 3103 |
3104 VisitForAccumulatorValue(args->at(0)); | 3104 VisitForAccumulatorValue(args->at(0)); |
3105 | 3105 |
3106 Label materialize_true, materialize_false; | 3106 Label materialize_true, materialize_false; |
3107 Label* if_true = NULL; | 3107 Label* if_true = NULL; |
3108 Label* if_false = NULL; | 3108 Label* if_false = NULL; |
3109 Label* fall_through = NULL; | 3109 Label* fall_through = NULL; |
3110 context()->PrepareTest(&materialize_true, &materialize_false, | 3110 context()->PrepareTest(&materialize_true, &materialize_false, |
3111 &if_true, &if_false, &fall_through); | 3111 &if_true, &if_false, &fall_through); |
3112 | 3112 |
3113 __ JumpIfSmi(r0, if_false); | 3113 __ JumpIfSmi(r0, if_false); |
3114 __ CompareObjectType(r0, r1, r2, JS_FUNCTION_TYPE); | 3114 __ CompareObjectType(r0, r1, r2, JS_FUNCTION_TYPE); |
3115 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 3115 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
3116 Split(eq, if_true, if_false, fall_through); | 3116 Split(eq, if_true, if_false, fall_through); |
3117 | 3117 |
3118 context()->Plug(if_true, if_false); | 3118 context()->Plug(if_true, if_false); |
3119 } | 3119 } |
3120 | 3120 |
3121 | 3121 |
3122 void FullCodeGenerator::EmitIsMinusZero(CallRuntime* expr) { | 3122 void FullCodeGenerator::EmitIsMinusZero(CallRuntime* expr) { |
3123 ZoneList<Expression*>* args = expr->arguments(); | 3123 ZoneList<Expression*>* args = expr->arguments(); |
3124 ASSERT(args->length() == 1); | 3124 DCHECK(args->length() == 1); |
3125 | 3125 |
3126 VisitForAccumulatorValue(args->at(0)); | 3126 VisitForAccumulatorValue(args->at(0)); |
3127 | 3127 |
3128 Label materialize_true, materialize_false; | 3128 Label materialize_true, materialize_false; |
3129 Label* if_true = NULL; | 3129 Label* if_true = NULL; |
3130 Label* if_false = NULL; | 3130 Label* if_false = NULL; |
3131 Label* fall_through = NULL; | 3131 Label* fall_through = NULL; |
3132 context()->PrepareTest(&materialize_true, &materialize_false, | 3132 context()->PrepareTest(&materialize_true, &materialize_false, |
3133 &if_true, &if_false, &fall_through); | 3133 &if_true, &if_false, &fall_through); |
3134 | 3134 |
3135 __ CheckMap(r0, r1, Heap::kHeapNumberMapRootIndex, if_false, DO_SMI_CHECK); | 3135 __ CheckMap(r0, r1, Heap::kHeapNumberMapRootIndex, if_false, DO_SMI_CHECK); |
3136 __ ldr(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset)); | 3136 __ ldr(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset)); |
3137 __ ldr(r1, FieldMemOperand(r0, HeapNumber::kMantissaOffset)); | 3137 __ ldr(r1, FieldMemOperand(r0, HeapNumber::kMantissaOffset)); |
3138 __ cmp(r2, Operand(0x80000000)); | 3138 __ cmp(r2, Operand(0x80000000)); |
3139 __ cmp(r1, Operand(0x00000000), eq); | 3139 __ cmp(r1, Operand(0x00000000), eq); |
3140 | 3140 |
3141 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 3141 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
3142 Split(eq, if_true, if_false, fall_through); | 3142 Split(eq, if_true, if_false, fall_through); |
3143 | 3143 |
3144 context()->Plug(if_true, if_false); | 3144 context()->Plug(if_true, if_false); |
3145 } | 3145 } |
3146 | 3146 |
3147 | 3147 |
3148 void FullCodeGenerator::EmitIsArray(CallRuntime* expr) { | 3148 void FullCodeGenerator::EmitIsArray(CallRuntime* expr) { |
3149 ZoneList<Expression*>* args = expr->arguments(); | 3149 ZoneList<Expression*>* args = expr->arguments(); |
3150 ASSERT(args->length() == 1); | 3150 DCHECK(args->length() == 1); |
3151 | 3151 |
3152 VisitForAccumulatorValue(args->at(0)); | 3152 VisitForAccumulatorValue(args->at(0)); |
3153 | 3153 |
3154 Label materialize_true, materialize_false; | 3154 Label materialize_true, materialize_false; |
3155 Label* if_true = NULL; | 3155 Label* if_true = NULL; |
3156 Label* if_false = NULL; | 3156 Label* if_false = NULL; |
3157 Label* fall_through = NULL; | 3157 Label* fall_through = NULL; |
3158 context()->PrepareTest(&materialize_true, &materialize_false, | 3158 context()->PrepareTest(&materialize_true, &materialize_false, |
3159 &if_true, &if_false, &fall_through); | 3159 &if_true, &if_false, &fall_through); |
3160 | 3160 |
3161 __ JumpIfSmi(r0, if_false); | 3161 __ JumpIfSmi(r0, if_false); |
3162 __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE); | 3162 __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE); |
3163 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 3163 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
3164 Split(eq, if_true, if_false, fall_through); | 3164 Split(eq, if_true, if_false, fall_through); |
3165 | 3165 |
3166 context()->Plug(if_true, if_false); | 3166 context()->Plug(if_true, if_false); |
3167 } | 3167 } |
3168 | 3168 |
3169 | 3169 |
3170 void FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) { | 3170 void FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) { |
3171 ZoneList<Expression*>* args = expr->arguments(); | 3171 ZoneList<Expression*>* args = expr->arguments(); |
3172 ASSERT(args->length() == 1); | 3172 DCHECK(args->length() == 1); |
3173 | 3173 |
3174 VisitForAccumulatorValue(args->at(0)); | 3174 VisitForAccumulatorValue(args->at(0)); |
3175 | 3175 |
3176 Label materialize_true, materialize_false; | 3176 Label materialize_true, materialize_false; |
3177 Label* if_true = NULL; | 3177 Label* if_true = NULL; |
3178 Label* if_false = NULL; | 3178 Label* if_false = NULL; |
3179 Label* fall_through = NULL; | 3179 Label* fall_through = NULL; |
3180 context()->PrepareTest(&materialize_true, &materialize_false, | 3180 context()->PrepareTest(&materialize_true, &materialize_false, |
3181 &if_true, &if_false, &fall_through); | 3181 &if_true, &if_false, &fall_through); |
3182 | 3182 |
3183 __ JumpIfSmi(r0, if_false); | 3183 __ JumpIfSmi(r0, if_false); |
3184 __ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE); | 3184 __ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE); |
3185 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 3185 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
3186 Split(eq, if_true, if_false, fall_through); | 3186 Split(eq, if_true, if_false, fall_through); |
3187 | 3187 |
3188 context()->Plug(if_true, if_false); | 3188 context()->Plug(if_true, if_false); |
3189 } | 3189 } |
3190 | 3190 |
3191 | 3191 |
3192 | 3192 |
3193 void FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) { | 3193 void FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) { |
3194 ASSERT(expr->arguments()->length() == 0); | 3194 DCHECK(expr->arguments()->length() == 0); |
3195 | 3195 |
3196 Label materialize_true, materialize_false; | 3196 Label materialize_true, materialize_false; |
3197 Label* if_true = NULL; | 3197 Label* if_true = NULL; |
3198 Label* if_false = NULL; | 3198 Label* if_false = NULL; |
3199 Label* fall_through = NULL; | 3199 Label* fall_through = NULL; |
3200 context()->PrepareTest(&materialize_true, &materialize_false, | 3200 context()->PrepareTest(&materialize_true, &materialize_false, |
3201 &if_true, &if_false, &fall_through); | 3201 &if_true, &if_false, &fall_through); |
3202 | 3202 |
3203 // Get the frame pointer for the calling frame. | 3203 // Get the frame pointer for the calling frame. |
3204 __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | 3204 __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
3205 | 3205 |
3206 // Skip the arguments adaptor frame if it exists. | 3206 // Skip the arguments adaptor frame if it exists. |
3207 __ ldr(r1, MemOperand(r2, StandardFrameConstants::kContextOffset)); | 3207 __ ldr(r1, MemOperand(r2, StandardFrameConstants::kContextOffset)); |
3208 __ cmp(r1, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 3208 __ cmp(r1, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
3209 __ ldr(r2, MemOperand(r2, StandardFrameConstants::kCallerFPOffset), eq); | 3209 __ ldr(r2, MemOperand(r2, StandardFrameConstants::kCallerFPOffset), eq); |
3210 | 3210 |
3211 // Check the marker in the calling frame. | 3211 // Check the marker in the calling frame. |
3212 __ ldr(r1, MemOperand(r2, StandardFrameConstants::kMarkerOffset)); | 3212 __ ldr(r1, MemOperand(r2, StandardFrameConstants::kMarkerOffset)); |
3213 __ cmp(r1, Operand(Smi::FromInt(StackFrame::CONSTRUCT))); | 3213 __ cmp(r1, Operand(Smi::FromInt(StackFrame::CONSTRUCT))); |
3214 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 3214 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
3215 Split(eq, if_true, if_false, fall_through); | 3215 Split(eq, 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(r1); | 3236 __ pop(r1); |
3237 __ cmp(r0, r1); | 3237 __ cmp(r0, r1); |
3238 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 3238 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
3239 Split(eq, if_true, if_false, fall_through); | 3239 Split(eq, if_true, if_false, fall_through); |
3240 | 3240 |
3241 context()->Plug(if_true, if_false); | 3241 context()->Plug(if_true, if_false); |
3242 } | 3242 } |
3243 | 3243 |
3244 | 3244 |
3245 void FullCodeGenerator::EmitArguments(CallRuntime* expr) { | 3245 void FullCodeGenerator::EmitArguments(CallRuntime* expr) { |
3246 ZoneList<Expression*>* args = expr->arguments(); | 3246 ZoneList<Expression*>* args = expr->arguments(); |
3247 ASSERT(args->length() == 1); | 3247 DCHECK(args->length() == 1); |
3248 | 3248 |
3249 // ArgumentsAccessStub expects the key in edx and the formal | 3249 // ArgumentsAccessStub expects the key in edx and the formal |
3250 // parameter count in r0. | 3250 // parameter count in r0. |
3251 VisitForAccumulatorValue(args->at(0)); | 3251 VisitForAccumulatorValue(args->at(0)); |
3252 __ mov(r1, r0); | 3252 __ mov(r1, r0); |
3253 __ mov(r0, Operand(Smi::FromInt(info_->scope()->num_parameters()))); | 3253 __ mov(r0, Operand(Smi::FromInt(info_->scope()->num_parameters()))); |
3254 ArgumentsAccessStub stub(isolate(), ArgumentsAccessStub::READ_ELEMENT); | 3254 ArgumentsAccessStub stub(isolate(), ArgumentsAccessStub::READ_ELEMENT); |
3255 __ CallStub(&stub); | 3255 __ CallStub(&stub); |
3256 context()->Plug(r0); | 3256 context()->Plug(r0); |
3257 } | 3257 } |
3258 | 3258 |
3259 | 3259 |
3260 void FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) { | 3260 void FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) { |
3261 ASSERT(expr->arguments()->length() == 0); | 3261 DCHECK(expr->arguments()->length() == 0); |
3262 | 3262 |
3263 // Get the number of formal parameters. | 3263 // Get the number of formal parameters. |
3264 __ mov(r0, Operand(Smi::FromInt(info_->scope()->num_parameters()))); | 3264 __ mov(r0, Operand(Smi::FromInt(info_->scope()->num_parameters()))); |
3265 | 3265 |
3266 // Check if the calling frame is an arguments adaptor frame. | 3266 // Check if the calling frame is an arguments adaptor frame. |
3267 __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | 3267 __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
3268 __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset)); | 3268 __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset)); |
3269 __ cmp(r3, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 3269 __ cmp(r3, 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 __ ldr(r0, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset), eq); | 3273 __ ldr(r0, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset), eq); |
3274 | 3274 |
3275 context()->Plug(r0); | 3275 context()->Plug(r0); |
3276 } | 3276 } |
3277 | 3277 |
3278 | 3278 |
3279 void FullCodeGenerator::EmitClassOf(CallRuntime* expr) { | 3279 void FullCodeGenerator::EmitClassOf(CallRuntime* expr) { |
3280 ZoneList<Expression*>* args = expr->arguments(); | 3280 ZoneList<Expression*>* args = expr->arguments(); |
3281 ASSERT(args->length() == 1); | 3281 DCHECK(args->length() == 1); |
3282 Label done, null, function, non_function_constructor; | 3282 Label done, null, function, non_function_constructor; |
3283 | 3283 |
3284 VisitForAccumulatorValue(args->at(0)); | 3284 VisitForAccumulatorValue(args->at(0)); |
3285 | 3285 |
3286 // If the object is a smi, we return null. | 3286 // If the object is a smi, we return null. |
3287 __ JumpIfSmi(r0, &null); | 3287 __ JumpIfSmi(r0, &null); |
3288 | 3288 |
3289 // Check that the object is a JS object but take special care of JS | 3289 // Check that the object is a JS object but take special care of JS |
3290 // functions to make sure they have 'Function' as their class. | 3290 // functions to make sure they have 'Function' as their class. |
3291 // Assume that there are only two callable types, and one of them is at | 3291 // Assume that there are only two callable types, and one of them is at |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3334 __ bind(&done); | 3334 __ bind(&done); |
3335 | 3335 |
3336 context()->Plug(r0); | 3336 context()->Plug(r0); |
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(r0); | 3349 context()->Plug(r0); |
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(r0); | 3363 context()->Plug(r0); |
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 VisitForAccumulatorValue(args->at(0)); // Load the object. | 3370 VisitForAccumulatorValue(args->at(0)); // Load the object. |
3371 | 3371 |
3372 Label done; | 3372 Label done; |
3373 // If the object is a smi return the object. | 3373 // If the object is a smi return the object. |
3374 __ JumpIfSmi(r0, &done); | 3374 __ JumpIfSmi(r0, &done); |
3375 // If the object is not a value type, return the object. | 3375 // If the object is not a value type, return the object. |
3376 __ CompareObjectType(r0, r1, r1, JS_VALUE_TYPE); | 3376 __ CompareObjectType(r0, r1, r1, JS_VALUE_TYPE); |
3377 __ ldr(r0, FieldMemOperand(r0, JSValue::kValueOffset), eq); | 3377 __ ldr(r0, FieldMemOperand(r0, JSValue::kValueOffset), eq); |
3378 | 3378 |
3379 __ bind(&done); | 3379 __ bind(&done); |
3380 context()->Plug(r0); | 3380 context()->Plug(r0); |
3381 } | 3381 } |
3382 | 3382 |
3383 | 3383 |
3384 void FullCodeGenerator::EmitDateField(CallRuntime* expr) { | 3384 void FullCodeGenerator::EmitDateField(CallRuntime* expr) { |
3385 ZoneList<Expression*>* args = expr->arguments(); | 3385 ZoneList<Expression*>* args = expr->arguments(); |
3386 ASSERT(args->length() == 2); | 3386 DCHECK(args->length() == 2); |
3387 ASSERT_NE(NULL, args->at(1)->AsLiteral()); | 3387 DCHECK_NE(NULL, args->at(1)->AsLiteral()); |
3388 Smi* index = Smi::cast(*(args->at(1)->AsLiteral()->value())); | 3388 Smi* index = Smi::cast(*(args->at(1)->AsLiteral()->value())); |
3389 | 3389 |
3390 VisitForAccumulatorValue(args->at(0)); // Load the object. | 3390 VisitForAccumulatorValue(args->at(0)); // Load the object. |
3391 | 3391 |
3392 Label runtime, done, not_date_object; | 3392 Label runtime, done, not_date_object; |
3393 Register object = r0; | 3393 Register object = r0; |
3394 Register result = r0; | 3394 Register result = r0; |
3395 Register scratch0 = r9; | 3395 Register scratch0 = r9; |
3396 Register scratch1 = r1; | 3396 Register scratch1 = r1; |
3397 | 3397 |
(...skipping 25 matching lines...) Expand all Loading... |
3423 | 3423 |
3424 __ bind(¬_date_object); | 3424 __ bind(¬_date_object); |
3425 __ CallRuntime(Runtime::kThrowNotDateError, 0); | 3425 __ CallRuntime(Runtime::kThrowNotDateError, 0); |
3426 __ bind(&done); | 3426 __ bind(&done); |
3427 context()->Plug(r0); | 3427 context()->Plug(r0); |
3428 } | 3428 } |
3429 | 3429 |
3430 | 3430 |
3431 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) { | 3431 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) { |
3432 ZoneList<Expression*>* args = expr->arguments(); | 3432 ZoneList<Expression*>* args = expr->arguments(); |
3433 ASSERT_EQ(3, args->length()); | 3433 DCHECK_EQ(3, args->length()); |
3434 | 3434 |
3435 Register string = r0; | 3435 Register string = r0; |
3436 Register index = r1; | 3436 Register index = r1; |
3437 Register value = r2; | 3437 Register value = r2; |
3438 | 3438 |
3439 VisitForStackValue(args->at(1)); // index | 3439 VisitForStackValue(args->at(1)); // index |
3440 VisitForStackValue(args->at(2)); // value | 3440 VisitForStackValue(args->at(2)); // value |
3441 VisitForAccumulatorValue(args->at(0)); // string | 3441 VisitForAccumulatorValue(args->at(0)); // string |
3442 __ Pop(index, value); | 3442 __ Pop(index, value); |
3443 | 3443 |
(...skipping 12 matching lines...) Expand all Loading... |
3456 __ add(ip, | 3456 __ add(ip, |
3457 string, | 3457 string, |
3458 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); | 3458 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); |
3459 __ strb(value, MemOperand(ip, index, LSR, kSmiTagSize)); | 3459 __ strb(value, MemOperand(ip, index, LSR, kSmiTagSize)); |
3460 context()->Plug(string); | 3460 context()->Plug(string); |
3461 } | 3461 } |
3462 | 3462 |
3463 | 3463 |
3464 void FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) { | 3464 void FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) { |
3465 ZoneList<Expression*>* args = expr->arguments(); | 3465 ZoneList<Expression*>* args = expr->arguments(); |
3466 ASSERT_EQ(3, args->length()); | 3466 DCHECK_EQ(3, args->length()); |
3467 | 3467 |
3468 Register string = r0; | 3468 Register string = r0; |
3469 Register index = r1; | 3469 Register index = r1; |
3470 Register value = r2; | 3470 Register value = r2; |
3471 | 3471 |
3472 VisitForStackValue(args->at(1)); // index | 3472 VisitForStackValue(args->at(1)); // index |
3473 VisitForStackValue(args->at(2)); // value | 3473 VisitForStackValue(args->at(2)); // value |
3474 VisitForAccumulatorValue(args->at(0)); // string | 3474 VisitForAccumulatorValue(args->at(0)); // string |
3475 __ Pop(index, value); | 3475 __ Pop(index, value); |
3476 | 3476 |
(...skipping 15 matching lines...) Expand all Loading... |
3492 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); | 3492 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); |
3493 __ strh(value, MemOperand(ip, index)); | 3493 __ strh(value, MemOperand(ip, index)); |
3494 context()->Plug(string); | 3494 context()->Plug(string); |
3495 } | 3495 } |
3496 | 3496 |
3497 | 3497 |
3498 | 3498 |
3499 void FullCodeGenerator::EmitMathPow(CallRuntime* expr) { | 3499 void FullCodeGenerator::EmitMathPow(CallRuntime* expr) { |
3500 // Load the arguments on the stack and call the runtime function. | 3500 // Load the arguments on the stack and call the runtime function. |
3501 ZoneList<Expression*>* args = expr->arguments(); | 3501 ZoneList<Expression*>* args = expr->arguments(); |
3502 ASSERT(args->length() == 2); | 3502 DCHECK(args->length() == 2); |
3503 VisitForStackValue(args->at(0)); | 3503 VisitForStackValue(args->at(0)); |
3504 VisitForStackValue(args->at(1)); | 3504 VisitForStackValue(args->at(1)); |
3505 MathPowStub stub(isolate(), MathPowStub::ON_STACK); | 3505 MathPowStub stub(isolate(), MathPowStub::ON_STACK); |
3506 __ CallStub(&stub); | 3506 __ CallStub(&stub); |
3507 context()->Plug(r0); | 3507 context()->Plug(r0); |
3508 } | 3508 } |
3509 | 3509 |
3510 | 3510 |
3511 void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) { | 3511 void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) { |
3512 ZoneList<Expression*>* args = expr->arguments(); | 3512 ZoneList<Expression*>* args = expr->arguments(); |
3513 ASSERT(args->length() == 2); | 3513 DCHECK(args->length() == 2); |
3514 VisitForStackValue(args->at(0)); // Load the object. | 3514 VisitForStackValue(args->at(0)); // Load the object. |
3515 VisitForAccumulatorValue(args->at(1)); // Load the value. | 3515 VisitForAccumulatorValue(args->at(1)); // Load the value. |
3516 __ pop(r1); // r0 = value. r1 = object. | 3516 __ pop(r1); // r0 = value. r1 = object. |
3517 | 3517 |
3518 Label done; | 3518 Label done; |
3519 // If the object is a smi, return the value. | 3519 // If the object is a smi, return the value. |
3520 __ JumpIfSmi(r1, &done); | 3520 __ JumpIfSmi(r1, &done); |
3521 | 3521 |
3522 // If the object is not a value type, return the value. | 3522 // If the object is not a value type, return the value. |
3523 __ CompareObjectType(r1, r2, r2, JS_VALUE_TYPE); | 3523 __ CompareObjectType(r1, r2, r2, JS_VALUE_TYPE); |
3524 __ b(ne, &done); | 3524 __ b(ne, &done); |
3525 | 3525 |
3526 // Store the value. | 3526 // Store the value. |
3527 __ str(r0, FieldMemOperand(r1, JSValue::kValueOffset)); | 3527 __ str(r0, FieldMemOperand(r1, JSValue::kValueOffset)); |
3528 // Update the write barrier. Save the value as it will be | 3528 // Update the write barrier. Save the value as it will be |
3529 // overwritten by the write barrier code and is needed afterward. | 3529 // overwritten by the write barrier code and is needed afterward. |
3530 __ mov(r2, r0); | 3530 __ mov(r2, r0); |
3531 __ RecordWriteField( | 3531 __ RecordWriteField( |
3532 r1, JSValue::kValueOffset, r2, r3, kLRHasBeenSaved, kDontSaveFPRegs); | 3532 r1, JSValue::kValueOffset, r2, r3, kLRHasBeenSaved, kDontSaveFPRegs); |
3533 | 3533 |
3534 __ bind(&done); | 3534 __ bind(&done); |
3535 context()->Plug(r0); | 3535 context()->Plug(r0); |
3536 } | 3536 } |
3537 | 3537 |
3538 | 3538 |
3539 void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) { | 3539 void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) { |
3540 ZoneList<Expression*>* args = expr->arguments(); | 3540 ZoneList<Expression*>* args = expr->arguments(); |
3541 ASSERT_EQ(args->length(), 1); | 3541 DCHECK_EQ(args->length(), 1); |
3542 // Load the argument into r0 and call the stub. | 3542 // Load the argument into r0 and call the stub. |
3543 VisitForAccumulatorValue(args->at(0)); | 3543 VisitForAccumulatorValue(args->at(0)); |
3544 | 3544 |
3545 NumberToStringStub stub(isolate()); | 3545 NumberToStringStub stub(isolate()); |
3546 __ CallStub(&stub); | 3546 __ CallStub(&stub); |
3547 context()->Plug(r0); | 3547 context()->Plug(r0); |
3548 } | 3548 } |
3549 | 3549 |
3550 | 3550 |
3551 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) { | 3551 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) { |
3552 ZoneList<Expression*>* args = expr->arguments(); | 3552 ZoneList<Expression*>* args = expr->arguments(); |
3553 ASSERT(args->length() == 1); | 3553 DCHECK(args->length() == 1); |
3554 VisitForAccumulatorValue(args->at(0)); | 3554 VisitForAccumulatorValue(args->at(0)); |
3555 | 3555 |
3556 Label done; | 3556 Label done; |
3557 StringCharFromCodeGenerator generator(r0, r1); | 3557 StringCharFromCodeGenerator generator(r0, r1); |
3558 generator.GenerateFast(masm_); | 3558 generator.GenerateFast(masm_); |
3559 __ jmp(&done); | 3559 __ jmp(&done); |
3560 | 3560 |
3561 NopRuntimeCallHelper call_helper; | 3561 NopRuntimeCallHelper call_helper; |
3562 generator.GenerateSlow(masm_, call_helper); | 3562 generator.GenerateSlow(masm_, call_helper); |
3563 | 3563 |
3564 __ bind(&done); | 3564 __ bind(&done); |
3565 context()->Plug(r1); | 3565 context()->Plug(r1); |
3566 } | 3566 } |
3567 | 3567 |
3568 | 3568 |
3569 void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) { | 3569 void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) { |
3570 ZoneList<Expression*>* args = expr->arguments(); | 3570 ZoneList<Expression*>* args = expr->arguments(); |
3571 ASSERT(args->length() == 2); | 3571 DCHECK(args->length() == 2); |
3572 VisitForStackValue(args->at(0)); | 3572 VisitForStackValue(args->at(0)); |
3573 VisitForAccumulatorValue(args->at(1)); | 3573 VisitForAccumulatorValue(args->at(1)); |
3574 | 3574 |
3575 Register object = r1; | 3575 Register object = r1; |
3576 Register index = r0; | 3576 Register index = r0; |
3577 Register result = r3; | 3577 Register result = r3; |
3578 | 3578 |
3579 __ pop(object); | 3579 __ pop(object); |
3580 | 3580 |
3581 Label need_conversion; | 3581 Label need_conversion; |
(...skipping 24 matching lines...) Expand all Loading... |
3606 NopRuntimeCallHelper call_helper; | 3606 NopRuntimeCallHelper call_helper; |
3607 generator.GenerateSlow(masm_, call_helper); | 3607 generator.GenerateSlow(masm_, call_helper); |
3608 | 3608 |
3609 __ bind(&done); | 3609 __ bind(&done); |
3610 context()->Plug(result); | 3610 context()->Plug(result); |
3611 } | 3611 } |
3612 | 3612 |
3613 | 3613 |
3614 void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) { | 3614 void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) { |
3615 ZoneList<Expression*>* args = expr->arguments(); | 3615 ZoneList<Expression*>* args = expr->arguments(); |
3616 ASSERT(args->length() == 2); | 3616 DCHECK(args->length() == 2); |
3617 VisitForStackValue(args->at(0)); | 3617 VisitForStackValue(args->at(0)); |
3618 VisitForAccumulatorValue(args->at(1)); | 3618 VisitForAccumulatorValue(args->at(1)); |
3619 | 3619 |
3620 Register object = r1; | 3620 Register object = r1; |
3621 Register index = r0; | 3621 Register index = r0; |
3622 Register scratch = r3; | 3622 Register scratch = r3; |
3623 Register result = r0; | 3623 Register result = r0; |
3624 | 3624 |
3625 __ pop(object); | 3625 __ pop(object); |
3626 | 3626 |
(...skipping 26 matching lines...) Expand all Loading... |
3653 NopRuntimeCallHelper call_helper; | 3653 NopRuntimeCallHelper call_helper; |
3654 generator.GenerateSlow(masm_, call_helper); | 3654 generator.GenerateSlow(masm_, call_helper); |
3655 | 3655 |
3656 __ bind(&done); | 3656 __ bind(&done); |
3657 context()->Plug(result); | 3657 context()->Plug(result); |
3658 } | 3658 } |
3659 | 3659 |
3660 | 3660 |
3661 void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) { | 3661 void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) { |
3662 ZoneList<Expression*>* args = expr->arguments(); | 3662 ZoneList<Expression*>* args = expr->arguments(); |
3663 ASSERT_EQ(2, args->length()); | 3663 DCHECK_EQ(2, args->length()); |
3664 VisitForStackValue(args->at(0)); | 3664 VisitForStackValue(args->at(0)); |
3665 VisitForAccumulatorValue(args->at(1)); | 3665 VisitForAccumulatorValue(args->at(1)); |
3666 | 3666 |
3667 __ pop(r1); | 3667 __ pop(r1); |
3668 StringAddStub stub(isolate(), STRING_ADD_CHECK_BOTH, NOT_TENURED); | 3668 StringAddStub stub(isolate(), STRING_ADD_CHECK_BOTH, NOT_TENURED); |
3669 __ CallStub(&stub); | 3669 __ CallStub(&stub); |
3670 context()->Plug(r0); | 3670 context()->Plug(r0); |
3671 } | 3671 } |
3672 | 3672 |
3673 | 3673 |
3674 void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) { | 3674 void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) { |
3675 ZoneList<Expression*>* args = expr->arguments(); | 3675 ZoneList<Expression*>* args = expr->arguments(); |
3676 ASSERT_EQ(2, args->length()); | 3676 DCHECK_EQ(2, args->length()); |
3677 VisitForStackValue(args->at(0)); | 3677 VisitForStackValue(args->at(0)); |
3678 VisitForStackValue(args->at(1)); | 3678 VisitForStackValue(args->at(1)); |
3679 | 3679 |
3680 StringCompareStub stub(isolate()); | 3680 StringCompareStub stub(isolate()); |
3681 __ CallStub(&stub); | 3681 __ CallStub(&stub); |
3682 context()->Plug(r0); | 3682 context()->Plug(r0); |
3683 } | 3683 } |
3684 | 3684 |
3685 | 3685 |
3686 void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) { | 3686 void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) { |
3687 ZoneList<Expression*>* args = expr->arguments(); | 3687 ZoneList<Expression*>* args = expr->arguments(); |
3688 ASSERT(args->length() >= 2); | 3688 DCHECK(args->length() >= 2); |
3689 | 3689 |
3690 int arg_count = args->length() - 2; // 2 ~ receiver and function. | 3690 int arg_count = args->length() - 2; // 2 ~ receiver and function. |
3691 for (int i = 0; i < arg_count + 1; i++) { | 3691 for (int i = 0; i < arg_count + 1; i++) { |
3692 VisitForStackValue(args->at(i)); | 3692 VisitForStackValue(args->at(i)); |
3693 } | 3693 } |
3694 VisitForAccumulatorValue(args->last()); // Function. | 3694 VisitForAccumulatorValue(args->last()); // Function. |
3695 | 3695 |
3696 Label runtime, done; | 3696 Label runtime, done; |
3697 // Check for non-function argument (including proxy). | 3697 // Check for non-function argument (including proxy). |
3698 __ JumpIfSmi(r0, &runtime); | 3698 __ JumpIfSmi(r0, &runtime); |
(...skipping 12 matching lines...) Expand all Loading... |
3711 __ CallRuntime(Runtime::kCall, args->length()); | 3711 __ CallRuntime(Runtime::kCall, args->length()); |
3712 __ bind(&done); | 3712 __ bind(&done); |
3713 | 3713 |
3714 context()->Plug(r0); | 3714 context()->Plug(r0); |
3715 } | 3715 } |
3716 | 3716 |
3717 | 3717 |
3718 void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) { | 3718 void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) { |
3719 RegExpConstructResultStub stub(isolate()); | 3719 RegExpConstructResultStub stub(isolate()); |
3720 ZoneList<Expression*>* args = expr->arguments(); | 3720 ZoneList<Expression*>* args = expr->arguments(); |
3721 ASSERT(args->length() == 3); | 3721 DCHECK(args->length() == 3); |
3722 VisitForStackValue(args->at(0)); | 3722 VisitForStackValue(args->at(0)); |
3723 VisitForStackValue(args->at(1)); | 3723 VisitForStackValue(args->at(1)); |
3724 VisitForAccumulatorValue(args->at(2)); | 3724 VisitForAccumulatorValue(args->at(2)); |
3725 __ pop(r1); | 3725 __ pop(r1); |
3726 __ pop(r2); | 3726 __ pop(r2); |
3727 __ CallStub(&stub); | 3727 __ CallStub(&stub); |
3728 context()->Plug(r0); | 3728 context()->Plug(r0); |
3729 } | 3729 } |
3730 | 3730 |
3731 | 3731 |
3732 void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) { | 3732 void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) { |
3733 ZoneList<Expression*>* args = expr->arguments(); | 3733 ZoneList<Expression*>* args = expr->arguments(); |
3734 ASSERT_EQ(2, args->length()); | 3734 DCHECK_EQ(2, args->length()); |
3735 ASSERT_NE(NULL, args->at(0)->AsLiteral()); | 3735 DCHECK_NE(NULL, args->at(0)->AsLiteral()); |
3736 int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->value()))->value(); | 3736 int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->value()))->value(); |
3737 | 3737 |
3738 Handle<FixedArray> jsfunction_result_caches( | 3738 Handle<FixedArray> jsfunction_result_caches( |
3739 isolate()->native_context()->jsfunction_result_caches()); | 3739 isolate()->native_context()->jsfunction_result_caches()); |
3740 if (jsfunction_result_caches->length() <= cache_id) { | 3740 if (jsfunction_result_caches->length() <= cache_id) { |
3741 __ Abort(kAttemptToUseUndefinedCache); | 3741 __ Abort(kAttemptToUseUndefinedCache); |
3742 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); | 3742 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); |
3743 context()->Plug(r0); | 3743 context()->Plug(r0); |
3744 return; | 3744 return; |
3745 } | 3745 } |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3793 __ tst(r0, Operand(String::kContainsCachedArrayIndexMask)); | 3793 __ tst(r0, Operand(String::kContainsCachedArrayIndexMask)); |
3794 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 3794 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
3795 Split(eq, if_true, if_false, fall_through); | 3795 Split(eq, if_true, if_false, fall_through); |
3796 | 3796 |
3797 context()->Plug(if_true, if_false); | 3797 context()->Plug(if_true, if_false); |
3798 } | 3798 } |
3799 | 3799 |
3800 | 3800 |
3801 void FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) { | 3801 void FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) { |
3802 ZoneList<Expression*>* args = expr->arguments(); | 3802 ZoneList<Expression*>* args = expr->arguments(); |
3803 ASSERT(args->length() == 1); | 3803 DCHECK(args->length() == 1); |
3804 VisitForAccumulatorValue(args->at(0)); | 3804 VisitForAccumulatorValue(args->at(0)); |
3805 | 3805 |
3806 __ AssertString(r0); | 3806 __ AssertString(r0); |
3807 | 3807 |
3808 __ ldr(r0, FieldMemOperand(r0, String::kHashFieldOffset)); | 3808 __ ldr(r0, FieldMemOperand(r0, String::kHashFieldOffset)); |
3809 __ IndexFromHash(r0, r0); | 3809 __ IndexFromHash(r0, r0); |
3810 | 3810 |
3811 context()->Plug(r0); | 3811 context()->Plug(r0); |
3812 } | 3812 } |
3813 | 3813 |
3814 | 3814 |
3815 void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) { | 3815 void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) { |
3816 Label bailout, done, one_char_separator, long_separator, non_trivial_array, | 3816 Label bailout, done, one_char_separator, long_separator, non_trivial_array, |
3817 not_size_one_array, loop, empty_separator_loop, one_char_separator_loop, | 3817 not_size_one_array, loop, empty_separator_loop, one_char_separator_loop, |
3818 one_char_separator_loop_entry, long_separator_loop; | 3818 one_char_separator_loop_entry, long_separator_loop; |
3819 ZoneList<Expression*>* args = expr->arguments(); | 3819 ZoneList<Expression*>* args = expr->arguments(); |
3820 ASSERT(args->length() == 2); | 3820 DCHECK(args->length() == 2); |
3821 VisitForStackValue(args->at(1)); | 3821 VisitForStackValue(args->at(1)); |
3822 VisitForAccumulatorValue(args->at(0)); | 3822 VisitForAccumulatorValue(args->at(0)); |
3823 | 3823 |
3824 // All aliases of the same register have disjoint lifetimes. | 3824 // All aliases of the same register have disjoint lifetimes. |
3825 Register array = r0; | 3825 Register array = r0; |
3826 Register elements = no_reg; // Will be r0. | 3826 Register elements = no_reg; // Will be r0. |
3827 Register result = no_reg; // Will be r0. | 3827 Register result = no_reg; // Will be r0. |
3828 Register separator = r1; | 3828 Register separator = r1; |
3829 Register array_length = r2; | 3829 Register array_length = r2; |
3830 Register result_pos = no_reg; // Will be r2 | 3830 Register result_pos = no_reg; // Will be r2 |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3968 // Copy next array element to the result. | 3968 // Copy next array element to the result. |
3969 __ ldr(string, MemOperand(element, kPointerSize, PostIndex)); | 3969 __ ldr(string, MemOperand(element, kPointerSize, PostIndex)); |
3970 __ ldr(string_length, FieldMemOperand(string, String::kLengthOffset)); | 3970 __ ldr(string_length, FieldMemOperand(string, String::kLengthOffset)); |
3971 __ SmiUntag(string_length); | 3971 __ SmiUntag(string_length); |
3972 __ add(string, | 3972 __ add(string, |
3973 string, | 3973 string, |
3974 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); | 3974 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); |
3975 __ CopyBytes(string, result_pos, string_length, scratch); | 3975 __ CopyBytes(string, result_pos, string_length, scratch); |
3976 __ cmp(element, elements_end); | 3976 __ cmp(element, elements_end); |
3977 __ b(lt, &empty_separator_loop); // End while (element < elements_end). | 3977 __ b(lt, &empty_separator_loop); // End while (element < elements_end). |
3978 ASSERT(result.is(r0)); | 3978 DCHECK(result.is(r0)); |
3979 __ b(&done); | 3979 __ b(&done); |
3980 | 3980 |
3981 // One-character separator case | 3981 // One-character separator case |
3982 __ bind(&one_char_separator); | 3982 __ bind(&one_char_separator); |
3983 // Replace separator with its ASCII character value. | 3983 // Replace separator with its ASCII character value. |
3984 __ ldrb(separator, FieldMemOperand(separator, SeqOneByteString::kHeaderSize)); | 3984 __ ldrb(separator, FieldMemOperand(separator, SeqOneByteString::kHeaderSize)); |
3985 // Jump into the loop after the code that copies the separator, so the first | 3985 // Jump into the loop after the code that copies the separator, so the first |
3986 // element is not preceded by a separator | 3986 // element is not preceded by a separator |
3987 __ jmp(&one_char_separator_loop_entry); | 3987 __ jmp(&one_char_separator_loop_entry); |
3988 | 3988 |
(...skipping 11 matching lines...) Expand all Loading... |
4000 __ bind(&one_char_separator_loop_entry); | 4000 __ bind(&one_char_separator_loop_entry); |
4001 __ ldr(string, MemOperand(element, kPointerSize, PostIndex)); | 4001 __ ldr(string, MemOperand(element, kPointerSize, PostIndex)); |
4002 __ ldr(string_length, FieldMemOperand(string, String::kLengthOffset)); | 4002 __ ldr(string_length, FieldMemOperand(string, String::kLengthOffset)); |
4003 __ SmiUntag(string_length); | 4003 __ SmiUntag(string_length); |
4004 __ add(string, | 4004 __ add(string, |
4005 string, | 4005 string, |
4006 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); | 4006 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); |
4007 __ CopyBytes(string, result_pos, string_length, scratch); | 4007 __ CopyBytes(string, result_pos, string_length, scratch); |
4008 __ cmp(element, elements_end); | 4008 __ cmp(element, elements_end); |
4009 __ b(lt, &one_char_separator_loop); // End while (element < elements_end). | 4009 __ b(lt, &one_char_separator_loop); // End while (element < elements_end). |
4010 ASSERT(result.is(r0)); | 4010 DCHECK(result.is(r0)); |
4011 __ b(&done); | 4011 __ b(&done); |
4012 | 4012 |
4013 // Long separator case (separator is more than one character). Entry is at the | 4013 // Long separator case (separator is more than one character). Entry is at the |
4014 // label long_separator below. | 4014 // label long_separator below. |
4015 __ bind(&long_separator_loop); | 4015 __ bind(&long_separator_loop); |
4016 // Live values in registers: | 4016 // Live values in registers: |
4017 // result_pos: the position to which we are currently copying characters. | 4017 // result_pos: the position to which we are currently copying characters. |
4018 // element: Current array element. | 4018 // element: Current array element. |
4019 // elements_end: Array end. | 4019 // elements_end: Array end. |
4020 // separator: Separator string. | 4020 // separator: Separator string. |
4021 | 4021 |
4022 // Copy the separator to the result. | 4022 // Copy the separator to the result. |
4023 __ ldr(string_length, FieldMemOperand(separator, String::kLengthOffset)); | 4023 __ ldr(string_length, FieldMemOperand(separator, String::kLengthOffset)); |
4024 __ SmiUntag(string_length); | 4024 __ SmiUntag(string_length); |
4025 __ add(string, | 4025 __ add(string, |
4026 separator, | 4026 separator, |
4027 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); | 4027 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); |
4028 __ CopyBytes(string, result_pos, string_length, scratch); | 4028 __ CopyBytes(string, result_pos, string_length, scratch); |
4029 | 4029 |
4030 __ bind(&long_separator); | 4030 __ bind(&long_separator); |
4031 __ ldr(string, MemOperand(element, kPointerSize, PostIndex)); | 4031 __ ldr(string, MemOperand(element, kPointerSize, PostIndex)); |
4032 __ ldr(string_length, FieldMemOperand(string, String::kLengthOffset)); | 4032 __ ldr(string_length, FieldMemOperand(string, String::kLengthOffset)); |
4033 __ SmiUntag(string_length); | 4033 __ SmiUntag(string_length); |
4034 __ add(string, | 4034 __ add(string, |
4035 string, | 4035 string, |
4036 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); | 4036 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); |
4037 __ CopyBytes(string, result_pos, string_length, scratch); | 4037 __ CopyBytes(string, result_pos, string_length, scratch); |
4038 __ cmp(element, elements_end); | 4038 __ cmp(element, elements_end); |
4039 __ b(lt, &long_separator_loop); // End while (element < elements_end). | 4039 __ b(lt, &long_separator_loop); // End while (element < elements_end). |
4040 ASSERT(result.is(r0)); | 4040 DCHECK(result.is(r0)); |
4041 __ b(&done); | 4041 __ b(&done); |
4042 | 4042 |
4043 __ bind(&bailout); | 4043 __ bind(&bailout); |
4044 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); | 4044 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); |
4045 __ bind(&done); | 4045 __ bind(&done); |
4046 context()->Plug(r0); | 4046 context()->Plug(r0); |
4047 } | 4047 } |
4048 | 4048 |
4049 | 4049 |
4050 void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) { | 4050 void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) { |
4051 ASSERT(expr->arguments()->length() == 0); | 4051 DCHECK(expr->arguments()->length() == 0); |
4052 ExternalReference debug_is_active = | 4052 ExternalReference debug_is_active = |
4053 ExternalReference::debug_is_active_address(isolate()); | 4053 ExternalReference::debug_is_active_address(isolate()); |
4054 __ mov(ip, Operand(debug_is_active)); | 4054 __ mov(ip, Operand(debug_is_active)); |
4055 __ ldrb(r0, MemOperand(ip)); | 4055 __ ldrb(r0, MemOperand(ip)); |
4056 __ SmiTag(r0); | 4056 __ SmiTag(r0); |
4057 context()->Plug(r0); | 4057 context()->Plug(r0); |
4058 } | 4058 } |
4059 | 4059 |
4060 | 4060 |
4061 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { | 4061 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4132 VisitForStackValue(property->obj()); | 4132 VisitForStackValue(property->obj()); |
4133 VisitForStackValue(property->key()); | 4133 VisitForStackValue(property->key()); |
4134 __ mov(r1, Operand(Smi::FromInt(strict_mode()))); | 4134 __ mov(r1, Operand(Smi::FromInt(strict_mode()))); |
4135 __ push(r1); | 4135 __ push(r1); |
4136 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); | 4136 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); |
4137 context()->Plug(r0); | 4137 context()->Plug(r0); |
4138 } else if (proxy != NULL) { | 4138 } else if (proxy != NULL) { |
4139 Variable* var = proxy->var(); | 4139 Variable* var = proxy->var(); |
4140 // Delete of an unqualified identifier is disallowed in strict mode | 4140 // Delete of an unqualified identifier is disallowed in strict mode |
4141 // but "delete this" is allowed. | 4141 // but "delete this" is allowed. |
4142 ASSERT(strict_mode() == SLOPPY || var->is_this()); | 4142 DCHECK(strict_mode() == SLOPPY || var->is_this()); |
4143 if (var->IsUnallocated()) { | 4143 if (var->IsUnallocated()) { |
4144 __ ldr(r2, GlobalObjectOperand()); | 4144 __ ldr(r2, GlobalObjectOperand()); |
4145 __ mov(r1, Operand(var->name())); | 4145 __ mov(r1, Operand(var->name())); |
4146 __ mov(r0, Operand(Smi::FromInt(SLOPPY))); | 4146 __ mov(r0, Operand(Smi::FromInt(SLOPPY))); |
4147 __ Push(r2, r1, r0); | 4147 __ Push(r2, r1, r0); |
4148 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); | 4148 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); |
4149 context()->Plug(r0); | 4149 context()->Plug(r0); |
4150 } else if (var->IsStackAllocated() || var->IsContextSlot()) { | 4150 } else if (var->IsStackAllocated() || var->IsContextSlot()) { |
4151 // Result of deleting non-global, non-dynamic variables is false. | 4151 // Result of deleting non-global, non-dynamic variables is false. |
4152 // The subexpression does not have side effects. | 4152 // The subexpression does not have side effects. |
4153 context()->Plug(var->is_this()); | 4153 context()->Plug(var->is_this()); |
4154 } else { | 4154 } else { |
4155 // Non-global variable. Call the runtime to try to delete from the | 4155 // Non-global variable. Call the runtime to try to delete from the |
4156 // context where the variable was introduced. | 4156 // context where the variable was introduced. |
4157 ASSERT(!context_register().is(r2)); | 4157 DCHECK(!context_register().is(r2)); |
4158 __ mov(r2, Operand(var->name())); | 4158 __ mov(r2, Operand(var->name())); |
4159 __ Push(context_register(), r2); | 4159 __ Push(context_register(), r2); |
4160 __ CallRuntime(Runtime::kDeleteLookupSlot, 2); | 4160 __ CallRuntime(Runtime::kDeleteLookupSlot, 2); |
4161 context()->Plug(r0); | 4161 context()->Plug(r0); |
4162 } | 4162 } |
4163 } else { | 4163 } else { |
4164 // Result of deleting non-property, non-variable reference is true. | 4164 // Result of deleting non-property, non-variable reference is true. |
4165 // The subexpression may have side effects. | 4165 // The subexpression may have side effects. |
4166 VisitForEffect(expr->expression()); | 4166 VisitForEffect(expr->expression()); |
4167 context()->Plug(true); | 4167 context()->Plug(true); |
(...skipping 20 matching lines...) Expand all Loading... |
4188 VisitForControl(expr->expression(), | 4188 VisitForControl(expr->expression(), |
4189 test->false_label(), | 4189 test->false_label(), |
4190 test->true_label(), | 4190 test->true_label(), |
4191 test->fall_through()); | 4191 test->fall_through()); |
4192 context()->Plug(test->true_label(), test->false_label()); | 4192 context()->Plug(test->true_label(), test->false_label()); |
4193 } else { | 4193 } else { |
4194 // We handle value contexts explicitly rather than simply visiting | 4194 // We handle value contexts explicitly rather than simply visiting |
4195 // for control and plugging the control flow into the context, | 4195 // for control and plugging the control flow into the context, |
4196 // because we need to prepare a pair of extra administrative AST ids | 4196 // because we need to prepare a pair of extra administrative AST ids |
4197 // for the optimizing compiler. | 4197 // for the optimizing compiler. |
4198 ASSERT(context()->IsAccumulatorValue() || context()->IsStackValue()); | 4198 DCHECK(context()->IsAccumulatorValue() || context()->IsStackValue()); |
4199 Label materialize_true, materialize_false, done; | 4199 Label materialize_true, materialize_false, done; |
4200 VisitForControl(expr->expression(), | 4200 VisitForControl(expr->expression(), |
4201 &materialize_false, | 4201 &materialize_false, |
4202 &materialize_true, | 4202 &materialize_true, |
4203 &materialize_true); | 4203 &materialize_true); |
4204 __ bind(&materialize_true); | 4204 __ bind(&materialize_true); |
4205 PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS); | 4205 PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS); |
4206 __ LoadRoot(r0, Heap::kTrueValueRootIndex); | 4206 __ LoadRoot(r0, Heap::kTrueValueRootIndex); |
4207 if (context()->IsStackValue()) __ push(r0); | 4207 if (context()->IsStackValue()) __ push(r0); |
4208 __ jmp(&done); | 4208 __ jmp(&done); |
(...skipping 16 matching lines...) Expand all Loading... |
4225 break; | 4225 break; |
4226 } | 4226 } |
4227 | 4227 |
4228 default: | 4228 default: |
4229 UNREACHABLE(); | 4229 UNREACHABLE(); |
4230 } | 4230 } |
4231 } | 4231 } |
4232 | 4232 |
4233 | 4233 |
4234 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { | 4234 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { |
4235 ASSERT(expr->expression()->IsValidReferenceExpression()); | 4235 DCHECK(expr->expression()->IsValidReferenceExpression()); |
4236 | 4236 |
4237 Comment cmnt(masm_, "[ CountOperation"); | 4237 Comment cmnt(masm_, "[ CountOperation"); |
4238 SetSourcePosition(expr->position()); | 4238 SetSourcePosition(expr->position()); |
4239 | 4239 |
4240 // Expression can only be a property, a global or a (parameter or local) | 4240 // Expression can only be a property, a global or a (parameter or local) |
4241 // slot. | 4241 // slot. |
4242 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 4242 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
4243 LhsKind assign_type = VARIABLE; | 4243 LhsKind assign_type = VARIABLE; |
4244 Property* prop = expr->expression()->AsProperty(); | 4244 Property* prop = expr->expression()->AsProperty(); |
4245 // In case of a property we use the uninitialized expression context | 4245 // In case of a property we use the uninitialized expression context |
4246 // of the key to detect a named property. | 4246 // of the key to detect a named property. |
4247 if (prop != NULL) { | 4247 if (prop != NULL) { |
4248 assign_type = | 4248 assign_type = |
4249 (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; | 4249 (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; |
4250 } | 4250 } |
4251 | 4251 |
4252 // Evaluate expression and get value. | 4252 // Evaluate expression and get value. |
4253 if (assign_type == VARIABLE) { | 4253 if (assign_type == VARIABLE) { |
4254 ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); | 4254 DCHECK(expr->expression()->AsVariableProxy()->var() != NULL); |
4255 AccumulatorValueContext context(this); | 4255 AccumulatorValueContext context(this); |
4256 EmitVariableLoad(expr->expression()->AsVariableProxy()); | 4256 EmitVariableLoad(expr->expression()->AsVariableProxy()); |
4257 } else { | 4257 } else { |
4258 // Reserve space for result of postfix operation. | 4258 // Reserve space for result of postfix operation. |
4259 if (expr->is_postfix() && !context()->IsEffect()) { | 4259 if (expr->is_postfix() && !context()->IsEffect()) { |
4260 __ mov(ip, Operand(Smi::FromInt(0))); | 4260 __ mov(ip, Operand(Smi::FromInt(0))); |
4261 __ push(ip); | 4261 __ push(ip); |
4262 } | 4262 } |
4263 if (assign_type == NAMED_PROPERTY) { | 4263 if (assign_type == NAMED_PROPERTY) { |
4264 // Put the object both on the stack and in the register. | 4264 // Put the object both on the stack and in the register. |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4405 } else { | 4405 } else { |
4406 context()->Plug(r0); | 4406 context()->Plug(r0); |
4407 } | 4407 } |
4408 break; | 4408 break; |
4409 } | 4409 } |
4410 } | 4410 } |
4411 } | 4411 } |
4412 | 4412 |
4413 | 4413 |
4414 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { | 4414 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { |
4415 ASSERT(!context()->IsEffect()); | 4415 DCHECK(!context()->IsEffect()); |
4416 ASSERT(!context()->IsTest()); | 4416 DCHECK(!context()->IsTest()); |
4417 VariableProxy* proxy = expr->AsVariableProxy(); | 4417 VariableProxy* proxy = expr->AsVariableProxy(); |
4418 if (proxy != NULL && proxy->var()->IsUnallocated()) { | 4418 if (proxy != NULL && proxy->var()->IsUnallocated()) { |
4419 Comment cmnt(masm_, "[ Global variable"); | 4419 Comment cmnt(masm_, "[ Global variable"); |
4420 __ ldr(LoadIC::ReceiverRegister(), GlobalObjectOperand()); | 4420 __ ldr(LoadIC::ReceiverRegister(), GlobalObjectOperand()); |
4421 __ mov(LoadIC::NameRegister(), Operand(proxy->name())); | 4421 __ mov(LoadIC::NameRegister(), Operand(proxy->name())); |
4422 if (FLAG_vector_ics) { | 4422 if (FLAG_vector_ics) { |
4423 __ mov(LoadIC::SlotRegister(), | 4423 __ mov(LoadIC::SlotRegister(), |
4424 Operand(Smi::FromInt(proxy->VariableFeedbackSlot()))); | 4424 Operand(Smi::FromInt(proxy->VariableFeedbackSlot()))); |
4425 } | 4425 } |
4426 // Use a regular load, not a contextual load, to avoid a reference | 4426 // Use a regular load, not a contextual load, to avoid a reference |
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4639 return r0; | 4639 return r0; |
4640 } | 4640 } |
4641 | 4641 |
4642 | 4642 |
4643 Register FullCodeGenerator::context_register() { | 4643 Register FullCodeGenerator::context_register() { |
4644 return cp; | 4644 return cp; |
4645 } | 4645 } |
4646 | 4646 |
4647 | 4647 |
4648 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { | 4648 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { |
4649 ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset); | 4649 DCHECK_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset); |
4650 __ str(value, MemOperand(fp, frame_offset)); | 4650 __ str(value, MemOperand(fp, frame_offset)); |
4651 } | 4651 } |
4652 | 4652 |
4653 | 4653 |
4654 void FullCodeGenerator::LoadContextField(Register dst, int context_index) { | 4654 void FullCodeGenerator::LoadContextField(Register dst, int context_index) { |
4655 __ ldr(dst, ContextOperand(cp, context_index)); | 4655 __ ldr(dst, ContextOperand(cp, context_index)); |
4656 } | 4656 } |
4657 | 4657 |
4658 | 4658 |
4659 void FullCodeGenerator::PushFunctionArgumentForContextAllocation() { | 4659 void FullCodeGenerator::PushFunctionArgumentForContextAllocation() { |
4660 Scope* declaration_scope = scope()->DeclarationScope(); | 4660 Scope* declaration_scope = scope()->DeclarationScope(); |
4661 if (declaration_scope->is_global_scope() || | 4661 if (declaration_scope->is_global_scope() || |
4662 declaration_scope->is_module_scope()) { | 4662 declaration_scope->is_module_scope()) { |
4663 // Contexts nested in the native context have a canonical empty function | 4663 // Contexts nested in the native context have a canonical empty function |
4664 // as their closure, not the anonymous closure containing the global | 4664 // as their closure, not the anonymous closure containing the global |
4665 // code. Pass a smi sentinel and let the runtime look up the empty | 4665 // code. Pass a smi sentinel and let the runtime look up the empty |
4666 // function. | 4666 // function. |
4667 __ mov(ip, Operand(Smi::FromInt(0))); | 4667 __ mov(ip, Operand(Smi::FromInt(0))); |
4668 } else if (declaration_scope->is_eval_scope()) { | 4668 } else if (declaration_scope->is_eval_scope()) { |
4669 // Contexts created by a call to eval have the same closure as the | 4669 // Contexts created by a call to eval have the same closure as the |
4670 // context calling eval, not the anonymous closure containing the eval | 4670 // context calling eval, not the anonymous closure containing the eval |
4671 // code. Fetch it from the context. | 4671 // code. Fetch it from the context. |
4672 __ ldr(ip, ContextOperand(cp, Context::CLOSURE_INDEX)); | 4672 __ ldr(ip, ContextOperand(cp, Context::CLOSURE_INDEX)); |
4673 } else { | 4673 } else { |
4674 ASSERT(declaration_scope->is_function_scope()); | 4674 DCHECK(declaration_scope->is_function_scope()); |
4675 __ ldr(ip, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 4675 __ ldr(ip, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
4676 } | 4676 } |
4677 __ push(ip); | 4677 __ push(ip); |
4678 } | 4678 } |
4679 | 4679 |
4680 | 4680 |
4681 // ---------------------------------------------------------------------------- | 4681 // ---------------------------------------------------------------------------- |
4682 // Non-local control flow support. | 4682 // Non-local control flow support. |
4683 | 4683 |
4684 void FullCodeGenerator::EnterFinallyBlock() { | 4684 void FullCodeGenerator::EnterFinallyBlock() { |
4685 ASSERT(!result_register().is(r1)); | 4685 DCHECK(!result_register().is(r1)); |
4686 // Store result register while executing finally block. | 4686 // Store result register while executing finally block. |
4687 __ push(result_register()); | 4687 __ push(result_register()); |
4688 // Cook return address in link register to stack (smi encoded Code* delta) | 4688 // Cook return address in link register to stack (smi encoded Code* delta) |
4689 __ sub(r1, lr, Operand(masm_->CodeObject())); | 4689 __ sub(r1, lr, Operand(masm_->CodeObject())); |
4690 __ SmiTag(r1); | 4690 __ SmiTag(r1); |
4691 | 4691 |
4692 // Store result register while executing finally block. | 4692 // Store result register while executing finally block. |
4693 __ push(r1); | 4693 __ push(r1); |
4694 | 4694 |
4695 // Store pending message while executing finally block. | 4695 // Store pending message while executing finally block. |
(...skipping 13 matching lines...) Expand all Loading... |
4709 | 4709 |
4710 ExternalReference pending_message_script = | 4710 ExternalReference pending_message_script = |
4711 ExternalReference::address_of_pending_message_script(isolate()); | 4711 ExternalReference::address_of_pending_message_script(isolate()); |
4712 __ mov(ip, Operand(pending_message_script)); | 4712 __ mov(ip, Operand(pending_message_script)); |
4713 __ ldr(r1, MemOperand(ip)); | 4713 __ ldr(r1, MemOperand(ip)); |
4714 __ push(r1); | 4714 __ push(r1); |
4715 } | 4715 } |
4716 | 4716 |
4717 | 4717 |
4718 void FullCodeGenerator::ExitFinallyBlock() { | 4718 void FullCodeGenerator::ExitFinallyBlock() { |
4719 ASSERT(!result_register().is(r1)); | 4719 DCHECK(!result_register().is(r1)); |
4720 // Restore pending message from stack. | 4720 // Restore pending message from stack. |
4721 __ pop(r1); | 4721 __ pop(r1); |
4722 ExternalReference pending_message_script = | 4722 ExternalReference pending_message_script = |
4723 ExternalReference::address_of_pending_message_script(isolate()); | 4723 ExternalReference::address_of_pending_message_script(isolate()); |
4724 __ mov(ip, Operand(pending_message_script)); | 4724 __ mov(ip, Operand(pending_message_script)); |
4725 __ str(r1, MemOperand(ip)); | 4725 __ str(r1, MemOperand(ip)); |
4726 | 4726 |
4727 __ pop(r1); | 4727 __ pop(r1); |
4728 __ SmiUntag(r1); | 4728 __ SmiUntag(r1); |
4729 ExternalReference has_pending_message = | 4729 ExternalReference has_pending_message = |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4775 return previous_; | 4775 return previous_; |
4776 } | 4776 } |
4777 | 4777 |
4778 | 4778 |
4779 #undef __ | 4779 #undef __ |
4780 | 4780 |
4781 | 4781 |
4782 static Address GetInterruptImmediateLoadAddress(Address pc) { | 4782 static Address GetInterruptImmediateLoadAddress(Address pc) { |
4783 Address load_address = pc - 2 * Assembler::kInstrSize; | 4783 Address load_address = pc - 2 * Assembler::kInstrSize; |
4784 if (!FLAG_enable_ool_constant_pool) { | 4784 if (!FLAG_enable_ool_constant_pool) { |
4785 ASSERT(Assembler::IsLdrPcImmediateOffset(Memory::int32_at(load_address))); | 4785 DCHECK(Assembler::IsLdrPcImmediateOffset(Memory::int32_at(load_address))); |
4786 } else if (Assembler::IsLdrPpRegOffset(Memory::int32_at(load_address))) { | 4786 } else if (Assembler::IsLdrPpRegOffset(Memory::int32_at(load_address))) { |
4787 // This is an extended constant pool lookup. | 4787 // This is an extended constant pool lookup. |
4788 load_address -= 2 * Assembler::kInstrSize; | 4788 load_address -= 2 * Assembler::kInstrSize; |
4789 ASSERT(Assembler::IsMovW(Memory::int32_at(load_address))); | 4789 DCHECK(Assembler::IsMovW(Memory::int32_at(load_address))); |
4790 ASSERT(Assembler::IsMovT( | 4790 DCHECK(Assembler::IsMovT( |
4791 Memory::int32_at(load_address + Assembler::kInstrSize))); | 4791 Memory::int32_at(load_address + Assembler::kInstrSize))); |
4792 } else if (Assembler::IsMovT(Memory::int32_at(load_address))) { | 4792 } else if (Assembler::IsMovT(Memory::int32_at(load_address))) { |
4793 // This is a movw_movt immediate load. | 4793 // This is a movw_movt immediate load. |
4794 load_address -= Assembler::kInstrSize; | 4794 load_address -= Assembler::kInstrSize; |
4795 ASSERT(Assembler::IsMovW(Memory::int32_at(load_address))); | 4795 DCHECK(Assembler::IsMovW(Memory::int32_at(load_address))); |
4796 } else { | 4796 } else { |
4797 // This is a small constant pool lookup. | 4797 // This is a small constant pool lookup. |
4798 ASSERT(Assembler::IsLdrPpImmediateOffset(Memory::int32_at(load_address))); | 4798 DCHECK(Assembler::IsLdrPpImmediateOffset(Memory::int32_at(load_address))); |
4799 } | 4799 } |
4800 return load_address; | 4800 return load_address; |
4801 } | 4801 } |
4802 | 4802 |
4803 | 4803 |
4804 void BackEdgeTable::PatchAt(Code* unoptimized_code, | 4804 void BackEdgeTable::PatchAt(Code* unoptimized_code, |
4805 Address pc, | 4805 Address pc, |
4806 BackEdgeState target_state, | 4806 BackEdgeState target_state, |
4807 Code* replacement_code) { | 4807 Code* replacement_code) { |
4808 Address pc_immediate_load_address = GetInterruptImmediateLoadAddress(pc); | 4808 Address pc_immediate_load_address = GetInterruptImmediateLoadAddress(pc); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4852 | 4852 |
4853 unoptimized_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch( | 4853 unoptimized_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch( |
4854 unoptimized_code, pc_immediate_load_address, replacement_code); | 4854 unoptimized_code, pc_immediate_load_address, replacement_code); |
4855 } | 4855 } |
4856 | 4856 |
4857 | 4857 |
4858 BackEdgeTable::BackEdgeState BackEdgeTable::GetBackEdgeState( | 4858 BackEdgeTable::BackEdgeState BackEdgeTable::GetBackEdgeState( |
4859 Isolate* isolate, | 4859 Isolate* isolate, |
4860 Code* unoptimized_code, | 4860 Code* unoptimized_code, |
4861 Address pc) { | 4861 Address pc) { |
4862 ASSERT(Assembler::IsBlxIp(Memory::int32_at(pc - Assembler::kInstrSize))); | 4862 DCHECK(Assembler::IsBlxIp(Memory::int32_at(pc - Assembler::kInstrSize))); |
4863 | 4863 |
4864 Address pc_immediate_load_address = GetInterruptImmediateLoadAddress(pc); | 4864 Address pc_immediate_load_address = GetInterruptImmediateLoadAddress(pc); |
4865 Address branch_address = pc_immediate_load_address - Assembler::kInstrSize; | 4865 Address branch_address = pc_immediate_load_address - Assembler::kInstrSize; |
4866 Address interrupt_address = Assembler::target_address_at( | 4866 Address interrupt_address = Assembler::target_address_at( |
4867 pc_immediate_load_address, unoptimized_code); | 4867 pc_immediate_load_address, unoptimized_code); |
4868 | 4868 |
4869 if (Assembler::IsBranch(Assembler::instr_at(branch_address))) { | 4869 if (Assembler::IsBranch(Assembler::instr_at(branch_address))) { |
4870 ASSERT(interrupt_address == | 4870 DCHECK(interrupt_address == |
4871 isolate->builtins()->InterruptCheck()->entry()); | 4871 isolate->builtins()->InterruptCheck()->entry()); |
4872 return INTERRUPT; | 4872 return INTERRUPT; |
4873 } | 4873 } |
4874 | 4874 |
4875 ASSERT(Assembler::IsNop(Assembler::instr_at(branch_address))); | 4875 DCHECK(Assembler::IsNop(Assembler::instr_at(branch_address))); |
4876 | 4876 |
4877 if (interrupt_address == | 4877 if (interrupt_address == |
4878 isolate->builtins()->OnStackReplacement()->entry()) { | 4878 isolate->builtins()->OnStackReplacement()->entry()) { |
4879 return ON_STACK_REPLACEMENT; | 4879 return ON_STACK_REPLACEMENT; |
4880 } | 4880 } |
4881 | 4881 |
4882 ASSERT(interrupt_address == | 4882 DCHECK(interrupt_address == |
4883 isolate->builtins()->OsrAfterStackCheck()->entry()); | 4883 isolate->builtins()->OsrAfterStackCheck()->entry()); |
4884 return OSR_AFTER_STACK_CHECK; | 4884 return OSR_AFTER_STACK_CHECK; |
4885 } | 4885 } |
4886 | 4886 |
4887 | 4887 |
4888 } } // namespace v8::internal | 4888 } } // namespace v8::internal |
4889 | 4889 |
4890 #endif // V8_TARGET_ARCH_ARM | 4890 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |