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_X87 | 7 #if V8_TARGET_ARCH_X87 |
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 13 matching lines...) Expand all Loading... |
24 | 24 |
25 class JumpPatchSite BASE_EMBEDDED { | 25 class JumpPatchSite BASE_EMBEDDED { |
26 public: | 26 public: |
27 explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm) { | 27 explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm) { |
28 #ifdef DEBUG | 28 #ifdef DEBUG |
29 info_emitted_ = false; | 29 info_emitted_ = false; |
30 #endif | 30 #endif |
31 } | 31 } |
32 | 32 |
33 ~JumpPatchSite() { | 33 ~JumpPatchSite() { |
34 ASSERT(patch_site_.is_bound() == info_emitted_); | 34 DCHECK(patch_site_.is_bound() == info_emitted_); |
35 } | 35 } |
36 | 36 |
37 void EmitJumpIfNotSmi(Register reg, | 37 void EmitJumpIfNotSmi(Register reg, |
38 Label* target, | 38 Label* target, |
39 Label::Distance distance = Label::kFar) { | 39 Label::Distance distance = Label::kFar) { |
40 __ test(reg, Immediate(kSmiTagMask)); | 40 __ test(reg, Immediate(kSmiTagMask)); |
41 EmitJump(not_carry, target, distance); // Always taken before patched. | 41 EmitJump(not_carry, target, distance); // Always taken before patched. |
42 } | 42 } |
43 | 43 |
44 void EmitJumpIfSmi(Register reg, | 44 void EmitJumpIfSmi(Register reg, |
45 Label* target, | 45 Label* target, |
46 Label::Distance distance = Label::kFar) { | 46 Label::Distance distance = Label::kFar) { |
47 __ test(reg, Immediate(kSmiTagMask)); | 47 __ test(reg, Immediate(kSmiTagMask)); |
48 EmitJump(carry, target, distance); // Never taken before patched. | 48 EmitJump(carry, target, distance); // Never taken before patched. |
49 } | 49 } |
50 | 50 |
51 void EmitPatchInfo() { | 51 void EmitPatchInfo() { |
52 if (patch_site_.is_bound()) { | 52 if (patch_site_.is_bound()) { |
53 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(&patch_site_); | 53 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(&patch_site_); |
54 ASSERT(is_uint8(delta_to_patch_site)); | 54 DCHECK(is_uint8(delta_to_patch_site)); |
55 __ test(eax, Immediate(delta_to_patch_site)); | 55 __ test(eax, Immediate(delta_to_patch_site)); |
56 #ifdef DEBUG | 56 #ifdef DEBUG |
57 info_emitted_ = true; | 57 info_emitted_ = true; |
58 #endif | 58 #endif |
59 } else { | 59 } else { |
60 __ nop(); // Signals no inlined code. | 60 __ nop(); // Signals no inlined code. |
61 } | 61 } |
62 } | 62 } |
63 | 63 |
64 private: | 64 private: |
65 // jc will be patched with jz, jnc will become jnz. | 65 // jc will be patched with jz, jnc will become jnz. |
66 void EmitJump(Condition cc, Label* target, Label::Distance distance) { | 66 void EmitJump(Condition cc, Label* target, Label::Distance distance) { |
67 ASSERT(!patch_site_.is_bound() && !info_emitted_); | 67 DCHECK(!patch_site_.is_bound() && !info_emitted_); |
68 ASSERT(cc == carry || cc == not_carry); | 68 DCHECK(cc == carry || cc == not_carry); |
69 __ bind(&patch_site_); | 69 __ bind(&patch_site_); |
70 __ j(cc, target, distance); | 70 __ j(cc, target, distance); |
71 } | 71 } |
72 | 72 |
73 MacroAssembler* masm_; | 73 MacroAssembler* masm_; |
74 Label patch_site_; | 74 Label patch_site_; |
75 #ifdef DEBUG | 75 #ifdef DEBUG |
76 bool info_emitted_; | 76 bool info_emitted_; |
77 #endif | 77 #endif |
78 }; | 78 }; |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
135 // the frame (that is done below). | 135 // the frame (that is done below). |
136 FrameScope frame_scope(masm_, StackFrame::MANUAL); | 136 FrameScope frame_scope(masm_, StackFrame::MANUAL); |
137 | 137 |
138 info->set_prologue_offset(masm_->pc_offset()); | 138 info->set_prologue_offset(masm_->pc_offset()); |
139 __ Prologue(info->IsCodePreAgingActive()); | 139 __ Prologue(info->IsCodePreAgingActive()); |
140 info->AddNoFrameRange(0, masm_->pc_offset()); | 140 info->AddNoFrameRange(0, masm_->pc_offset()); |
141 | 141 |
142 { Comment cmnt(masm_, "[ Allocate locals"); | 142 { Comment cmnt(masm_, "[ Allocate locals"); |
143 int locals_count = info->scope()->num_stack_slots(); | 143 int locals_count = info->scope()->num_stack_slots(); |
144 // Generators allocate locals, if any, in context slots. | 144 // Generators allocate locals, if any, in context slots. |
145 ASSERT(!info->function()->is_generator() || locals_count == 0); | 145 DCHECK(!info->function()->is_generator() || locals_count == 0); |
146 if (locals_count == 1) { | 146 if (locals_count == 1) { |
147 __ push(Immediate(isolate()->factory()->undefined_value())); | 147 __ push(Immediate(isolate()->factory()->undefined_value())); |
148 } else if (locals_count > 1) { | 148 } else if (locals_count > 1) { |
149 if (locals_count >= 128) { | 149 if (locals_count >= 128) { |
150 Label ok; | 150 Label ok; |
151 __ mov(ecx, esp); | 151 __ mov(ecx, esp); |
152 __ sub(ecx, Immediate(locals_count * kPointerSize)); | 152 __ sub(ecx, Immediate(locals_count * kPointerSize)); |
153 ExternalReference stack_limit = | 153 ExternalReference stack_limit = |
154 ExternalReference::address_of_real_stack_limit(isolate()); | 154 ExternalReference::address_of_real_stack_limit(isolate()); |
155 __ cmp(ecx, Operand::StaticVariable(stack_limit)); | 155 __ cmp(ecx, Operand::StaticVariable(stack_limit)); |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
278 Comment cmnt(masm_, "[ Declarations"); | 278 Comment cmnt(masm_, "[ Declarations"); |
279 scope()->VisitIllegalRedeclaration(this); | 279 scope()->VisitIllegalRedeclaration(this); |
280 | 280 |
281 } else { | 281 } else { |
282 PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS); | 282 PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS); |
283 { Comment cmnt(masm_, "[ Declarations"); | 283 { Comment cmnt(masm_, "[ Declarations"); |
284 // For named function expressions, declare the function name as a | 284 // For named function expressions, declare the function name as a |
285 // constant. | 285 // constant. |
286 if (scope()->is_function_scope() && scope()->function() != NULL) { | 286 if (scope()->is_function_scope() && scope()->function() != NULL) { |
287 VariableDeclaration* function = scope()->function(); | 287 VariableDeclaration* function = scope()->function(); |
288 ASSERT(function->proxy()->var()->mode() == CONST || | 288 DCHECK(function->proxy()->var()->mode() == CONST || |
289 function->proxy()->var()->mode() == CONST_LEGACY); | 289 function->proxy()->var()->mode() == CONST_LEGACY); |
290 ASSERT(function->proxy()->var()->location() != Variable::UNALLOCATED); | 290 DCHECK(function->proxy()->var()->location() != Variable::UNALLOCATED); |
291 VisitVariableDeclaration(function); | 291 VisitVariableDeclaration(function); |
292 } | 292 } |
293 VisitDeclarations(scope()->declarations()); | 293 VisitDeclarations(scope()->declarations()); |
294 } | 294 } |
295 | 295 |
296 { Comment cmnt(masm_, "[ Stack check"); | 296 { Comment cmnt(masm_, "[ Stack check"); |
297 PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS); | 297 PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS); |
298 Label ok; | 298 Label ok; |
299 ExternalReference stack_limit | 299 ExternalReference stack_limit |
300 = ExternalReference::address_of_stack_limit(isolate()); | 300 = ExternalReference::address_of_stack_limit(isolate()); |
301 __ cmp(esp, Operand::StaticVariable(stack_limit)); | 301 __ cmp(esp, Operand::StaticVariable(stack_limit)); |
302 __ j(above_equal, &ok, Label::kNear); | 302 __ j(above_equal, &ok, Label::kNear); |
303 __ call(isolate()->builtins()->StackCheck(), RelocInfo::CODE_TARGET); | 303 __ call(isolate()->builtins()->StackCheck(), RelocInfo::CODE_TARGET); |
304 __ bind(&ok); | 304 __ bind(&ok); |
305 } | 305 } |
306 | 306 |
307 { Comment cmnt(masm_, "[ Body"); | 307 { Comment cmnt(masm_, "[ Body"); |
308 ASSERT(loop_depth() == 0); | 308 DCHECK(loop_depth() == 0); |
309 VisitStatements(function()->body()); | 309 VisitStatements(function()->body()); |
310 ASSERT(loop_depth() == 0); | 310 DCHECK(loop_depth() == 0); |
311 } | 311 } |
312 } | 312 } |
313 | 313 |
314 // Always emit a 'return undefined' in case control fell off the end of | 314 // Always emit a 'return undefined' in case control fell off the end of |
315 // the body. | 315 // the body. |
316 { Comment cmnt(masm_, "[ return <undefined>;"); | 316 { Comment cmnt(masm_, "[ return <undefined>;"); |
317 __ mov(eax, isolate()->factory()->undefined_value()); | 317 __ mov(eax, isolate()->factory()->undefined_value()); |
318 EmitReturnSequence(); | 318 EmitReturnSequence(); |
319 } | 319 } |
320 } | 320 } |
(...skipping 17 matching lines...) Expand all Loading... |
338 __ mov(FieldOperand(ebx, Cell::kValueOffset), | 338 __ mov(FieldOperand(ebx, Cell::kValueOffset), |
339 Immediate(Smi::FromInt(reset_value))); | 339 Immediate(Smi::FromInt(reset_value))); |
340 } | 340 } |
341 | 341 |
342 | 342 |
343 void FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt, | 343 void FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt, |
344 Label* back_edge_target) { | 344 Label* back_edge_target) { |
345 Comment cmnt(masm_, "[ Back edge bookkeeping"); | 345 Comment cmnt(masm_, "[ Back edge bookkeeping"); |
346 Label ok; | 346 Label ok; |
347 | 347 |
348 ASSERT(back_edge_target->is_bound()); | 348 DCHECK(back_edge_target->is_bound()); |
349 int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target); | 349 int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target); |
350 int weight = Min(kMaxBackEdgeWeight, | 350 int weight = Min(kMaxBackEdgeWeight, |
351 Max(1, distance / kCodeSizeMultiplier)); | 351 Max(1, distance / kCodeSizeMultiplier)); |
352 EmitProfilingCounterDecrement(weight); | 352 EmitProfilingCounterDecrement(weight); |
353 __ j(positive, &ok, Label::kNear); | 353 __ j(positive, &ok, Label::kNear); |
354 __ call(isolate()->builtins()->InterruptCheck(), RelocInfo::CODE_TARGET); | 354 __ call(isolate()->builtins()->InterruptCheck(), RelocInfo::CODE_TARGET); |
355 | 355 |
356 // Record a mapping of this PC offset to the OSR id. This is used to find | 356 // Record a mapping of this PC offset to the OSR id. This is used to find |
357 // the AST id from the unoptimized code in order to use it as a key into | 357 // the AST id from the unoptimized code in order to use it as a key into |
358 // the deoptimization input data found in the optimized code. | 358 // the deoptimization input data found in the optimized code. |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
408 // Do not use the leave instruction here because it is too short to | 408 // Do not use the leave instruction here because it is too short to |
409 // patch with the code required by the debugger. | 409 // patch with the code required by the debugger. |
410 __ mov(esp, ebp); | 410 __ mov(esp, ebp); |
411 int no_frame_start = masm_->pc_offset(); | 411 int no_frame_start = masm_->pc_offset(); |
412 __ pop(ebp); | 412 __ pop(ebp); |
413 | 413 |
414 int arguments_bytes = (info_->scope()->num_parameters() + 1) * kPointerSize; | 414 int arguments_bytes = (info_->scope()->num_parameters() + 1) * kPointerSize; |
415 __ Ret(arguments_bytes, ecx); | 415 __ Ret(arguments_bytes, ecx); |
416 // Check that the size of the code used for returning is large enough | 416 // Check that the size of the code used for returning is large enough |
417 // for the debugger's requirements. | 417 // for the debugger's requirements. |
418 ASSERT(Assembler::kJSReturnSequenceLength <= | 418 DCHECK(Assembler::kJSReturnSequenceLength <= |
419 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); | 419 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); |
420 info_->AddNoFrameRange(no_frame_start, masm_->pc_offset()); | 420 info_->AddNoFrameRange(no_frame_start, masm_->pc_offset()); |
421 } | 421 } |
422 } | 422 } |
423 | 423 |
424 | 424 |
425 void FullCodeGenerator::EffectContext::Plug(Variable* var) const { | 425 void FullCodeGenerator::EffectContext::Plug(Variable* var) const { |
426 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); | 426 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
427 } | 427 } |
428 | 428 |
429 | 429 |
430 void FullCodeGenerator::AccumulatorValueContext::Plug(Variable* var) const { | 430 void FullCodeGenerator::AccumulatorValueContext::Plug(Variable* var) const { |
431 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); | 431 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
432 codegen()->GetVar(result_register(), var); | 432 codegen()->GetVar(result_register(), var); |
433 } | 433 } |
434 | 434 |
435 | 435 |
436 void FullCodeGenerator::StackValueContext::Plug(Variable* var) const { | 436 void FullCodeGenerator::StackValueContext::Plug(Variable* var) const { |
437 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); | 437 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
438 MemOperand operand = codegen()->VarOperand(var, result_register()); | 438 MemOperand operand = codegen()->VarOperand(var, result_register()); |
439 // Memory operands can be pushed directly. | 439 // Memory operands can be pushed directly. |
440 __ push(operand); | 440 __ push(operand); |
441 } | 441 } |
442 | 442 |
443 | 443 |
444 void FullCodeGenerator::TestContext::Plug(Variable* var) const { | 444 void FullCodeGenerator::TestContext::Plug(Variable* var) const { |
445 // For simplicity we always test the accumulator register. | 445 // For simplicity we always test the accumulator register. |
446 codegen()->GetVar(result_register(), var); | 446 codegen()->GetVar(result_register(), var); |
447 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); | 447 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
492 __ push(Immediate(lit)); | 492 __ push(Immediate(lit)); |
493 } | 493 } |
494 } | 494 } |
495 | 495 |
496 | 496 |
497 void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const { | 497 void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const { |
498 codegen()->PrepareForBailoutBeforeSplit(condition(), | 498 codegen()->PrepareForBailoutBeforeSplit(condition(), |
499 true, | 499 true, |
500 true_label_, | 500 true_label_, |
501 false_label_); | 501 false_label_); |
502 ASSERT(!lit->IsUndetectableObject()); // There are no undetectable literals. | 502 DCHECK(!lit->IsUndetectableObject()); // There are no undetectable literals. |
503 if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) { | 503 if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) { |
504 if (false_label_ != fall_through_) __ jmp(false_label_); | 504 if (false_label_ != fall_through_) __ jmp(false_label_); |
505 } else if (lit->IsTrue() || lit->IsJSObject()) { | 505 } else if (lit->IsTrue() || lit->IsJSObject()) { |
506 if (true_label_ != fall_through_) __ jmp(true_label_); | 506 if (true_label_ != fall_through_) __ jmp(true_label_); |
507 } else if (lit->IsString()) { | 507 } else if (lit->IsString()) { |
508 if (String::cast(*lit)->length() == 0) { | 508 if (String::cast(*lit)->length() == 0) { |
509 if (false_label_ != fall_through_) __ jmp(false_label_); | 509 if (false_label_ != fall_through_) __ jmp(false_label_); |
510 } else { | 510 } else { |
511 if (true_label_ != fall_through_) __ jmp(true_label_); | 511 if (true_label_ != fall_through_) __ jmp(true_label_); |
512 } | 512 } |
513 } else if (lit->IsSmi()) { | 513 } else if (lit->IsSmi()) { |
514 if (Smi::cast(*lit)->value() == 0) { | 514 if (Smi::cast(*lit)->value() == 0) { |
515 if (false_label_ != fall_through_) __ jmp(false_label_); | 515 if (false_label_ != fall_through_) __ jmp(false_label_); |
516 } else { | 516 } else { |
517 if (true_label_ != fall_through_) __ jmp(true_label_); | 517 if (true_label_ != fall_through_) __ jmp(true_label_); |
518 } | 518 } |
519 } else { | 519 } else { |
520 // For simplicity we always test the accumulator register. | 520 // For simplicity we always test the accumulator register. |
521 __ mov(result_register(), lit); | 521 __ mov(result_register(), lit); |
522 codegen()->DoTest(this); | 522 codegen()->DoTest(this); |
523 } | 523 } |
524 } | 524 } |
525 | 525 |
526 | 526 |
527 void FullCodeGenerator::EffectContext::DropAndPlug(int count, | 527 void FullCodeGenerator::EffectContext::DropAndPlug(int count, |
528 Register reg) const { | 528 Register reg) const { |
529 ASSERT(count > 0); | 529 DCHECK(count > 0); |
530 __ Drop(count); | 530 __ Drop(count); |
531 } | 531 } |
532 | 532 |
533 | 533 |
534 void FullCodeGenerator::AccumulatorValueContext::DropAndPlug( | 534 void FullCodeGenerator::AccumulatorValueContext::DropAndPlug( |
535 int count, | 535 int count, |
536 Register reg) const { | 536 Register reg) const { |
537 ASSERT(count > 0); | 537 DCHECK(count > 0); |
538 __ Drop(count); | 538 __ Drop(count); |
539 __ Move(result_register(), reg); | 539 __ Move(result_register(), reg); |
540 } | 540 } |
541 | 541 |
542 | 542 |
543 void FullCodeGenerator::StackValueContext::DropAndPlug(int count, | 543 void FullCodeGenerator::StackValueContext::DropAndPlug(int count, |
544 Register reg) const { | 544 Register reg) const { |
545 ASSERT(count > 0); | 545 DCHECK(count > 0); |
546 if (count > 1) __ Drop(count - 1); | 546 if (count > 1) __ Drop(count - 1); |
547 __ mov(Operand(esp, 0), reg); | 547 __ mov(Operand(esp, 0), reg); |
548 } | 548 } |
549 | 549 |
550 | 550 |
551 void FullCodeGenerator::TestContext::DropAndPlug(int count, | 551 void FullCodeGenerator::TestContext::DropAndPlug(int count, |
552 Register reg) const { | 552 Register reg) const { |
553 ASSERT(count > 0); | 553 DCHECK(count > 0); |
554 // For simplicity we always test the accumulator register. | 554 // For simplicity we always test the accumulator register. |
555 __ Drop(count); | 555 __ Drop(count); |
556 __ Move(result_register(), reg); | 556 __ Move(result_register(), reg); |
557 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); | 557 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); |
558 codegen()->DoTest(this); | 558 codegen()->DoTest(this); |
559 } | 559 } |
560 | 560 |
561 | 561 |
562 void FullCodeGenerator::EffectContext::Plug(Label* materialize_true, | 562 void FullCodeGenerator::EffectContext::Plug(Label* materialize_true, |
563 Label* materialize_false) const { | 563 Label* materialize_false) const { |
564 ASSERT(materialize_true == materialize_false); | 564 DCHECK(materialize_true == materialize_false); |
565 __ bind(materialize_true); | 565 __ bind(materialize_true); |
566 } | 566 } |
567 | 567 |
568 | 568 |
569 void FullCodeGenerator::AccumulatorValueContext::Plug( | 569 void FullCodeGenerator::AccumulatorValueContext::Plug( |
570 Label* materialize_true, | 570 Label* materialize_true, |
571 Label* materialize_false) const { | 571 Label* materialize_false) const { |
572 Label done; | 572 Label done; |
573 __ bind(materialize_true); | 573 __ bind(materialize_true); |
574 __ mov(result_register(), isolate()->factory()->true_value()); | 574 __ mov(result_register(), isolate()->factory()->true_value()); |
(...skipping 12 matching lines...) Expand all Loading... |
587 __ push(Immediate(isolate()->factory()->true_value())); | 587 __ push(Immediate(isolate()->factory()->true_value())); |
588 __ jmp(&done, Label::kNear); | 588 __ jmp(&done, Label::kNear); |
589 __ bind(materialize_false); | 589 __ bind(materialize_false); |
590 __ push(Immediate(isolate()->factory()->false_value())); | 590 __ push(Immediate(isolate()->factory()->false_value())); |
591 __ bind(&done); | 591 __ bind(&done); |
592 } | 592 } |
593 | 593 |
594 | 594 |
595 void FullCodeGenerator::TestContext::Plug(Label* materialize_true, | 595 void FullCodeGenerator::TestContext::Plug(Label* materialize_true, |
596 Label* materialize_false) const { | 596 Label* materialize_false) const { |
597 ASSERT(materialize_true == true_label_); | 597 DCHECK(materialize_true == true_label_); |
598 ASSERT(materialize_false == false_label_); | 598 DCHECK(materialize_false == false_label_); |
599 } | 599 } |
600 | 600 |
601 | 601 |
602 void FullCodeGenerator::EffectContext::Plug(bool flag) const { | 602 void FullCodeGenerator::EffectContext::Plug(bool flag) const { |
603 } | 603 } |
604 | 604 |
605 | 605 |
606 void FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const { | 606 void FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const { |
607 Handle<Object> value = flag | 607 Handle<Object> value = flag |
608 ? isolate()->factory()->true_value() | 608 ? isolate()->factory()->true_value() |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
653 } else if (if_true == fall_through) { | 653 } else if (if_true == fall_through) { |
654 __ j(NegateCondition(cc), if_false); | 654 __ j(NegateCondition(cc), if_false); |
655 } else { | 655 } else { |
656 __ j(cc, if_true); | 656 __ j(cc, if_true); |
657 __ jmp(if_false); | 657 __ jmp(if_false); |
658 } | 658 } |
659 } | 659 } |
660 | 660 |
661 | 661 |
662 MemOperand FullCodeGenerator::StackOperand(Variable* var) { | 662 MemOperand FullCodeGenerator::StackOperand(Variable* var) { |
663 ASSERT(var->IsStackAllocated()); | 663 DCHECK(var->IsStackAllocated()); |
664 // Offset is negative because higher indexes are at lower addresses. | 664 // Offset is negative because higher indexes are at lower addresses. |
665 int offset = -var->index() * kPointerSize; | 665 int offset = -var->index() * kPointerSize; |
666 // Adjust by a (parameter or local) base offset. | 666 // Adjust by a (parameter or local) base offset. |
667 if (var->IsParameter()) { | 667 if (var->IsParameter()) { |
668 offset += (info_->scope()->num_parameters() + 1) * kPointerSize; | 668 offset += (info_->scope()->num_parameters() + 1) * kPointerSize; |
669 } else { | 669 } else { |
670 offset += JavaScriptFrameConstants::kLocal0Offset; | 670 offset += JavaScriptFrameConstants::kLocal0Offset; |
671 } | 671 } |
672 return Operand(ebp, offset); | 672 return Operand(ebp, offset); |
673 } | 673 } |
674 | 674 |
675 | 675 |
676 MemOperand FullCodeGenerator::VarOperand(Variable* var, Register scratch) { | 676 MemOperand FullCodeGenerator::VarOperand(Variable* var, Register scratch) { |
677 ASSERT(var->IsContextSlot() || var->IsStackAllocated()); | 677 DCHECK(var->IsContextSlot() || var->IsStackAllocated()); |
678 if (var->IsContextSlot()) { | 678 if (var->IsContextSlot()) { |
679 int context_chain_length = scope()->ContextChainLength(var->scope()); | 679 int context_chain_length = scope()->ContextChainLength(var->scope()); |
680 __ LoadContext(scratch, context_chain_length); | 680 __ LoadContext(scratch, context_chain_length); |
681 return ContextOperand(scratch, var->index()); | 681 return ContextOperand(scratch, var->index()); |
682 } else { | 682 } else { |
683 return StackOperand(var); | 683 return StackOperand(var); |
684 } | 684 } |
685 } | 685 } |
686 | 686 |
687 | 687 |
688 void FullCodeGenerator::GetVar(Register dest, Variable* var) { | 688 void FullCodeGenerator::GetVar(Register dest, Variable* var) { |
689 ASSERT(var->IsContextSlot() || var->IsStackAllocated()); | 689 DCHECK(var->IsContextSlot() || var->IsStackAllocated()); |
690 MemOperand location = VarOperand(var, dest); | 690 MemOperand location = VarOperand(var, dest); |
691 __ mov(dest, location); | 691 __ mov(dest, location); |
692 } | 692 } |
693 | 693 |
694 | 694 |
695 void FullCodeGenerator::SetVar(Variable* var, | 695 void FullCodeGenerator::SetVar(Variable* var, |
696 Register src, | 696 Register src, |
697 Register scratch0, | 697 Register scratch0, |
698 Register scratch1) { | 698 Register scratch1) { |
699 ASSERT(var->IsContextSlot() || var->IsStackAllocated()); | 699 DCHECK(var->IsContextSlot() || var->IsStackAllocated()); |
700 ASSERT(!scratch0.is(src)); | 700 DCHECK(!scratch0.is(src)); |
701 ASSERT(!scratch0.is(scratch1)); | 701 DCHECK(!scratch0.is(scratch1)); |
702 ASSERT(!scratch1.is(src)); | 702 DCHECK(!scratch1.is(src)); |
703 MemOperand location = VarOperand(var, scratch0); | 703 MemOperand location = VarOperand(var, scratch0); |
704 __ mov(location, src); | 704 __ mov(location, src); |
705 | 705 |
706 // Emit the write barrier code if the location is in the heap. | 706 // Emit the write barrier code if the location is in the heap. |
707 if (var->IsContextSlot()) { | 707 if (var->IsContextSlot()) { |
708 int offset = Context::SlotOffset(var->index()); | 708 int offset = Context::SlotOffset(var->index()); |
709 ASSERT(!scratch0.is(esi) && !src.is(esi) && !scratch1.is(esi)); | 709 DCHECK(!scratch0.is(esi) && !src.is(esi) && !scratch1.is(esi)); |
710 __ RecordWriteContextSlot(scratch0, offset, src, scratch1); | 710 __ RecordWriteContextSlot(scratch0, offset, src, scratch1); |
711 } | 711 } |
712 } | 712 } |
713 | 713 |
714 | 714 |
715 void FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr, | 715 void FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr, |
716 bool should_normalize, | 716 bool should_normalize, |
717 Label* if_true, | 717 Label* if_true, |
718 Label* if_false) { | 718 Label* if_false) { |
719 // Only prepare for bailouts before splits if we're in a test | 719 // Only prepare for bailouts before splits if we're in a test |
720 // context. Otherwise, we let the Visit function deal with the | 720 // context. Otherwise, we let the Visit function deal with the |
721 // preparation to avoid preparing with the same AST id twice. | 721 // preparation to avoid preparing with the same AST id twice. |
722 if (!context()->IsTest() || !info_->IsOptimizable()) return; | 722 if (!context()->IsTest() || !info_->IsOptimizable()) return; |
723 | 723 |
724 Label skip; | 724 Label skip; |
725 if (should_normalize) __ jmp(&skip, Label::kNear); | 725 if (should_normalize) __ jmp(&skip, Label::kNear); |
726 PrepareForBailout(expr, TOS_REG); | 726 PrepareForBailout(expr, TOS_REG); |
727 if (should_normalize) { | 727 if (should_normalize) { |
728 __ cmp(eax, isolate()->factory()->true_value()); | 728 __ cmp(eax, isolate()->factory()->true_value()); |
729 Split(equal, if_true, if_false, NULL); | 729 Split(equal, if_true, if_false, NULL); |
730 __ bind(&skip); | 730 __ bind(&skip); |
731 } | 731 } |
732 } | 732 } |
733 | 733 |
734 | 734 |
735 void FullCodeGenerator::EmitDebugCheckDeclarationContext(Variable* variable) { | 735 void FullCodeGenerator::EmitDebugCheckDeclarationContext(Variable* variable) { |
736 // The variable in the declaration always resides in the current context. | 736 // The variable in the declaration always resides in the current context. |
737 ASSERT_EQ(0, scope()->ContextChainLength(variable->scope())); | 737 DCHECK_EQ(0, scope()->ContextChainLength(variable->scope())); |
738 if (generate_debug_code_) { | 738 if (generate_debug_code_) { |
739 // Check that we're not inside a with or catch context. | 739 // Check that we're not inside a with or catch context. |
740 __ mov(ebx, FieldOperand(esi, HeapObject::kMapOffset)); | 740 __ mov(ebx, FieldOperand(esi, HeapObject::kMapOffset)); |
741 __ cmp(ebx, isolate()->factory()->with_context_map()); | 741 __ cmp(ebx, isolate()->factory()->with_context_map()); |
742 __ Check(not_equal, kDeclarationInWithContext); | 742 __ Check(not_equal, kDeclarationInWithContext); |
743 __ cmp(ebx, isolate()->factory()->catch_context_map()); | 743 __ cmp(ebx, isolate()->factory()->catch_context_map()); |
744 __ Check(not_equal, kDeclarationInCatchContext); | 744 __ Check(not_equal, kDeclarationInCatchContext); |
745 } | 745 } |
746 } | 746 } |
747 | 747 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
781 // No write barrier since the hole value is in old space. | 781 // No write barrier since the hole value is in old space. |
782 PrepareForBailoutForId(proxy->id(), NO_REGISTERS); | 782 PrepareForBailoutForId(proxy->id(), NO_REGISTERS); |
783 } | 783 } |
784 break; | 784 break; |
785 | 785 |
786 case Variable::LOOKUP: { | 786 case Variable::LOOKUP: { |
787 Comment cmnt(masm_, "[ VariableDeclaration"); | 787 Comment cmnt(masm_, "[ VariableDeclaration"); |
788 __ push(esi); | 788 __ push(esi); |
789 __ push(Immediate(variable->name())); | 789 __ push(Immediate(variable->name())); |
790 // VariableDeclaration nodes are always introduced in one of four modes. | 790 // VariableDeclaration nodes are always introduced in one of four modes. |
791 ASSERT(IsDeclaredVariableMode(mode)); | 791 DCHECK(IsDeclaredVariableMode(mode)); |
792 PropertyAttributes attr = | 792 PropertyAttributes attr = |
793 IsImmutableVariableMode(mode) ? READ_ONLY : NONE; | 793 IsImmutableVariableMode(mode) ? READ_ONLY : NONE; |
794 __ push(Immediate(Smi::FromInt(attr))); | 794 __ push(Immediate(Smi::FromInt(attr))); |
795 // Push initial value, if any. | 795 // Push initial value, if any. |
796 // Note: For variables we must not push an initial value (such as | 796 // Note: For variables we must not push an initial value (such as |
797 // 'undefined') because we may have a (legal) redeclaration and we | 797 // 'undefined') because we may have a (legal) redeclaration and we |
798 // must not destroy the current value. | 798 // must not destroy the current value. |
799 if (hole_init) { | 799 if (hole_init) { |
800 __ push(Immediate(isolate()->factory()->the_hole_value())); | 800 __ push(Immediate(isolate()->factory()->the_hole_value())); |
801 } else { | 801 } else { |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
855 VisitForStackValue(declaration->fun()); | 855 VisitForStackValue(declaration->fun()); |
856 __ CallRuntime(Runtime::kDeclareLookupSlot, 4); | 856 __ CallRuntime(Runtime::kDeclareLookupSlot, 4); |
857 break; | 857 break; |
858 } | 858 } |
859 } | 859 } |
860 } | 860 } |
861 | 861 |
862 | 862 |
863 void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) { | 863 void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) { |
864 Variable* variable = declaration->proxy()->var(); | 864 Variable* variable = declaration->proxy()->var(); |
865 ASSERT(variable->location() == Variable::CONTEXT); | 865 DCHECK(variable->location() == Variable::CONTEXT); |
866 ASSERT(variable->interface()->IsFrozen()); | 866 DCHECK(variable->interface()->IsFrozen()); |
867 | 867 |
868 Comment cmnt(masm_, "[ ModuleDeclaration"); | 868 Comment cmnt(masm_, "[ ModuleDeclaration"); |
869 EmitDebugCheckDeclarationContext(variable); | 869 EmitDebugCheckDeclarationContext(variable); |
870 | 870 |
871 // Load instance object. | 871 // Load instance object. |
872 __ LoadContext(eax, scope_->ContextChainLength(scope_->GlobalScope())); | 872 __ LoadContext(eax, scope_->ContextChainLength(scope_->GlobalScope())); |
873 __ mov(eax, ContextOperand(eax, variable->interface()->Index())); | 873 __ mov(eax, ContextOperand(eax, variable->interface()->Index())); |
874 __ mov(eax, ContextOperand(eax, Context::EXTENSION_INDEX)); | 874 __ mov(eax, ContextOperand(eax, Context::EXTENSION_INDEX)); |
875 | 875 |
876 // Assign it. | 876 // Assign it. |
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1145 | 1145 |
1146 // Check if the expected map still matches that of the enumerable. | 1146 // Check if the expected map still matches that of the enumerable. |
1147 // If not, we may have to filter the key. | 1147 // If not, we may have to filter the key. |
1148 Label update_each; | 1148 Label update_each; |
1149 __ mov(ecx, Operand(esp, 4 * kPointerSize)); | 1149 __ mov(ecx, Operand(esp, 4 * kPointerSize)); |
1150 __ cmp(edx, FieldOperand(ecx, HeapObject::kMapOffset)); | 1150 __ cmp(edx, FieldOperand(ecx, HeapObject::kMapOffset)); |
1151 __ j(equal, &update_each, Label::kNear); | 1151 __ j(equal, &update_each, Label::kNear); |
1152 | 1152 |
1153 // For proxies, no filtering is done. | 1153 // For proxies, no filtering is done. |
1154 // TODO(rossberg): What if only a prototype is a proxy? Not specified yet. | 1154 // TODO(rossberg): What if only a prototype is a proxy? Not specified yet. |
1155 ASSERT(Smi::FromInt(0) == 0); | 1155 DCHECK(Smi::FromInt(0) == 0); |
1156 __ test(edx, edx); | 1156 __ test(edx, edx); |
1157 __ j(zero, &update_each); | 1157 __ j(zero, &update_each); |
1158 | 1158 |
1159 // Convert the entry to a string or null if it isn't a property | 1159 // Convert the entry to a string or null if it isn't a property |
1160 // anymore. If the property has been removed while iterating, we | 1160 // anymore. If the property has been removed while iterating, we |
1161 // just skip it. | 1161 // just skip it. |
1162 __ push(ecx); // Enumerable. | 1162 __ push(ecx); // Enumerable. |
1163 __ push(ebx); // Current entry. | 1163 __ push(ebx); // Current entry. |
1164 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION); | 1164 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION); |
1165 __ test(eax, eax); | 1165 __ test(eax, eax); |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1335 ContextualMode mode = (typeof_state == INSIDE_TYPEOF) | 1335 ContextualMode mode = (typeof_state == INSIDE_TYPEOF) |
1336 ? NOT_CONTEXTUAL | 1336 ? NOT_CONTEXTUAL |
1337 : CONTEXTUAL; | 1337 : CONTEXTUAL; |
1338 | 1338 |
1339 CallLoadIC(mode); | 1339 CallLoadIC(mode); |
1340 } | 1340 } |
1341 | 1341 |
1342 | 1342 |
1343 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, | 1343 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, |
1344 Label* slow) { | 1344 Label* slow) { |
1345 ASSERT(var->IsContextSlot()); | 1345 DCHECK(var->IsContextSlot()); |
1346 Register context = esi; | 1346 Register context = esi; |
1347 Register temp = ebx; | 1347 Register temp = ebx; |
1348 | 1348 |
1349 for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { | 1349 for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { |
1350 if (s->num_heap_slots() > 0) { | 1350 if (s->num_heap_slots() > 0) { |
1351 if (s->calls_sloppy_eval()) { | 1351 if (s->calls_sloppy_eval()) { |
1352 // Check that extension is NULL. | 1352 // Check that extension is NULL. |
1353 __ cmp(ContextOperand(context, Context::EXTENSION_INDEX), | 1353 __ cmp(ContextOperand(context, Context::EXTENSION_INDEX), |
1354 Immediate(0)); | 1354 Immediate(0)); |
1355 __ j(not_equal, slow); | 1355 __ j(not_equal, slow); |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1427 case Variable::LOCAL: | 1427 case Variable::LOCAL: |
1428 case Variable::CONTEXT: { | 1428 case Variable::CONTEXT: { |
1429 Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable" | 1429 Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable" |
1430 : "[ Stack variable"); | 1430 : "[ Stack variable"); |
1431 if (var->binding_needs_init()) { | 1431 if (var->binding_needs_init()) { |
1432 // var->scope() may be NULL when the proxy is located in eval code and | 1432 // var->scope() may be NULL when the proxy is located in eval code and |
1433 // refers to a potential outside binding. Currently those bindings are | 1433 // refers to a potential outside binding. Currently those bindings are |
1434 // always looked up dynamically, i.e. in that case | 1434 // always looked up dynamically, i.e. in that case |
1435 // var->location() == LOOKUP. | 1435 // var->location() == LOOKUP. |
1436 // always holds. | 1436 // always holds. |
1437 ASSERT(var->scope() != NULL); | 1437 DCHECK(var->scope() != NULL); |
1438 | 1438 |
1439 // Check if the binding really needs an initialization check. The check | 1439 // Check if the binding really needs an initialization check. The check |
1440 // can be skipped in the following situation: we have a LET or CONST | 1440 // can be skipped in the following situation: we have a LET or CONST |
1441 // binding in harmony mode, both the Variable and the VariableProxy have | 1441 // binding in harmony mode, both the Variable and the VariableProxy have |
1442 // the same declaration scope (i.e. they are both in global code, in the | 1442 // the same declaration scope (i.e. they are both in global code, in the |
1443 // same function or in the same eval code) and the VariableProxy is in | 1443 // same function or in the same eval code) and the VariableProxy is in |
1444 // the source physically located after the initializer of the variable. | 1444 // the source physically located after the initializer of the variable. |
1445 // | 1445 // |
1446 // We cannot skip any initialization checks for CONST in non-harmony | 1446 // We cannot skip any initialization checks for CONST in non-harmony |
1447 // mode because const variables may be declared but never initialized: | 1447 // mode because const variables may be declared but never initialized: |
1448 // if (false) { const x; }; var y = x; | 1448 // if (false) { const x; }; var y = x; |
1449 // | 1449 // |
1450 // The condition on the declaration scopes is a conservative check for | 1450 // The condition on the declaration scopes is a conservative check for |
1451 // nested functions that access a binding and are called before the | 1451 // nested functions that access a binding and are called before the |
1452 // binding is initialized: | 1452 // binding is initialized: |
1453 // function() { f(); let x = 1; function f() { x = 2; } } | 1453 // function() { f(); let x = 1; function f() { x = 2; } } |
1454 // | 1454 // |
1455 bool skip_init_check; | 1455 bool skip_init_check; |
1456 if (var->scope()->DeclarationScope() != scope()->DeclarationScope()) { | 1456 if (var->scope()->DeclarationScope() != scope()->DeclarationScope()) { |
1457 skip_init_check = false; | 1457 skip_init_check = false; |
1458 } else { | 1458 } else { |
1459 // Check that we always have valid source position. | 1459 // Check that we always have valid source position. |
1460 ASSERT(var->initializer_position() != RelocInfo::kNoPosition); | 1460 DCHECK(var->initializer_position() != RelocInfo::kNoPosition); |
1461 ASSERT(proxy->position() != RelocInfo::kNoPosition); | 1461 DCHECK(proxy->position() != RelocInfo::kNoPosition); |
1462 skip_init_check = var->mode() != CONST_LEGACY && | 1462 skip_init_check = var->mode() != CONST_LEGACY && |
1463 var->initializer_position() < proxy->position(); | 1463 var->initializer_position() < proxy->position(); |
1464 } | 1464 } |
1465 | 1465 |
1466 if (!skip_init_check) { | 1466 if (!skip_init_check) { |
1467 // Let and const need a read barrier. | 1467 // Let and const need a read barrier. |
1468 Label done; | 1468 Label done; |
1469 GetVar(eax, var); | 1469 GetVar(eax, var); |
1470 __ cmp(eax, isolate()->factory()->the_hole_value()); | 1470 __ cmp(eax, isolate()->factory()->the_hole_value()); |
1471 __ j(not_equal, &done, Label::kNear); | 1471 __ j(not_equal, &done, Label::kNear); |
1472 if (var->mode() == LET || var->mode() == CONST) { | 1472 if (var->mode() == LET || var->mode() == CONST) { |
1473 // Throw a reference error when using an uninitialized let/const | 1473 // Throw a reference error when using an uninitialized let/const |
1474 // binding in harmony mode. | 1474 // binding in harmony mode. |
1475 __ push(Immediate(var->name())); | 1475 __ push(Immediate(var->name())); |
1476 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 1476 __ CallRuntime(Runtime::kThrowReferenceError, 1); |
1477 } else { | 1477 } else { |
1478 // Uninitalized const bindings outside of harmony mode are unholed. | 1478 // Uninitalized const bindings outside of harmony mode are unholed. |
1479 ASSERT(var->mode() == CONST_LEGACY); | 1479 DCHECK(var->mode() == CONST_LEGACY); |
1480 __ mov(eax, isolate()->factory()->undefined_value()); | 1480 __ mov(eax, isolate()->factory()->undefined_value()); |
1481 } | 1481 } |
1482 __ bind(&done); | 1482 __ bind(&done); |
1483 context()->Plug(eax); | 1483 context()->Plug(eax); |
1484 break; | 1484 break; |
1485 } | 1485 } |
1486 } | 1486 } |
1487 context()->Plug(var); | 1487 context()->Plug(var); |
1488 break; | 1488 break; |
1489 } | 1489 } |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1618 Literal* key = property->key(); | 1618 Literal* key = property->key(); |
1619 Expression* value = property->value(); | 1619 Expression* value = property->value(); |
1620 if (!result_saved) { | 1620 if (!result_saved) { |
1621 __ push(eax); // Save result on the stack | 1621 __ push(eax); // Save result on the stack |
1622 result_saved = true; | 1622 result_saved = true; |
1623 } | 1623 } |
1624 switch (property->kind()) { | 1624 switch (property->kind()) { |
1625 case ObjectLiteral::Property::CONSTANT: | 1625 case ObjectLiteral::Property::CONSTANT: |
1626 UNREACHABLE(); | 1626 UNREACHABLE(); |
1627 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 1627 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
1628 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); | 1628 DCHECK(!CompileTimeValue::IsCompileTimeValue(value)); |
1629 // Fall through. | 1629 // Fall through. |
1630 case ObjectLiteral::Property::COMPUTED: | 1630 case ObjectLiteral::Property::COMPUTED: |
1631 if (key->value()->IsInternalizedString()) { | 1631 if (key->value()->IsInternalizedString()) { |
1632 if (property->emit_store()) { | 1632 if (property->emit_store()) { |
1633 VisitForAccumulatorValue(value); | 1633 VisitForAccumulatorValue(value); |
1634 ASSERT(StoreIC::ValueRegister().is(eax)); | 1634 DCHECK(StoreIC::ValueRegister().is(eax)); |
1635 __ mov(StoreIC::NameRegister(), Immediate(key->value())); | 1635 __ mov(StoreIC::NameRegister(), Immediate(key->value())); |
1636 __ mov(StoreIC::ReceiverRegister(), Operand(esp, 0)); | 1636 __ mov(StoreIC::ReceiverRegister(), Operand(esp, 0)); |
1637 CallStoreIC(key->LiteralFeedbackId()); | 1637 CallStoreIC(key->LiteralFeedbackId()); |
1638 PrepareForBailoutForId(key->id(), NO_REGISTERS); | 1638 PrepareForBailoutForId(key->id(), NO_REGISTERS); |
1639 } else { | 1639 } else { |
1640 VisitForEffect(value); | 1640 VisitForEffect(value); |
1641 } | 1641 } |
1642 break; | 1642 break; |
1643 } | 1643 } |
1644 __ push(Operand(esp, 0)); // Duplicate receiver. | 1644 __ push(Operand(esp, 0)); // Duplicate receiver. |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1676 ++it) { | 1676 ++it) { |
1677 __ push(Operand(esp, 0)); // Duplicate receiver. | 1677 __ push(Operand(esp, 0)); // Duplicate receiver. |
1678 VisitForStackValue(it->first); | 1678 VisitForStackValue(it->first); |
1679 EmitAccessor(it->second->getter); | 1679 EmitAccessor(it->second->getter); |
1680 EmitAccessor(it->second->setter); | 1680 EmitAccessor(it->second->setter); |
1681 __ push(Immediate(Smi::FromInt(NONE))); | 1681 __ push(Immediate(Smi::FromInt(NONE))); |
1682 __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5); | 1682 __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5); |
1683 } | 1683 } |
1684 | 1684 |
1685 if (expr->has_function()) { | 1685 if (expr->has_function()) { |
1686 ASSERT(result_saved); | 1686 DCHECK(result_saved); |
1687 __ push(Operand(esp, 0)); | 1687 __ push(Operand(esp, 0)); |
1688 __ CallRuntime(Runtime::kToFastProperties, 1); | 1688 __ CallRuntime(Runtime::kToFastProperties, 1); |
1689 } | 1689 } |
1690 | 1690 |
1691 if (result_saved) { | 1691 if (result_saved) { |
1692 context()->PlugTOS(); | 1692 context()->PlugTOS(); |
1693 } else { | 1693 } else { |
1694 context()->Plug(eax); | 1694 context()->Plug(eax); |
1695 } | 1695 } |
1696 } | 1696 } |
1697 | 1697 |
1698 | 1698 |
1699 void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { | 1699 void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { |
1700 Comment cmnt(masm_, "[ ArrayLiteral"); | 1700 Comment cmnt(masm_, "[ ArrayLiteral"); |
1701 | 1701 |
1702 expr->BuildConstantElements(isolate()); | 1702 expr->BuildConstantElements(isolate()); |
1703 int flags = expr->depth() == 1 | 1703 int flags = expr->depth() == 1 |
1704 ? ArrayLiteral::kShallowElements | 1704 ? ArrayLiteral::kShallowElements |
1705 : ArrayLiteral::kNoFlags; | 1705 : ArrayLiteral::kNoFlags; |
1706 | 1706 |
1707 ZoneList<Expression*>* subexprs = expr->values(); | 1707 ZoneList<Expression*>* subexprs = expr->values(); |
1708 int length = subexprs->length(); | 1708 int length = subexprs->length(); |
1709 Handle<FixedArray> constant_elements = expr->constant_elements(); | 1709 Handle<FixedArray> constant_elements = expr->constant_elements(); |
1710 ASSERT_EQ(2, constant_elements->length()); | 1710 DCHECK_EQ(2, constant_elements->length()); |
1711 ElementsKind constant_elements_kind = | 1711 ElementsKind constant_elements_kind = |
1712 static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value()); | 1712 static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value()); |
1713 bool has_constant_fast_elements = | 1713 bool has_constant_fast_elements = |
1714 IsFastObjectElementsKind(constant_elements_kind); | 1714 IsFastObjectElementsKind(constant_elements_kind); |
1715 Handle<FixedArrayBase> constant_elements_values( | 1715 Handle<FixedArrayBase> constant_elements_values( |
1716 FixedArrayBase::cast(constant_elements->get(1))); | 1716 FixedArrayBase::cast(constant_elements->get(1))); |
1717 | 1717 |
1718 AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE; | 1718 AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE; |
1719 if (has_constant_fast_elements && !FLAG_allocation_site_pretenuring) { | 1719 if (has_constant_fast_elements && !FLAG_allocation_site_pretenuring) { |
1720 // If the only customer of allocation sites is transitioning, then | 1720 // If the only customer of allocation sites is transitioning, then |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1780 if (result_saved) { | 1780 if (result_saved) { |
1781 __ add(esp, Immediate(kPointerSize)); // literal index | 1781 __ add(esp, Immediate(kPointerSize)); // literal index |
1782 context()->PlugTOS(); | 1782 context()->PlugTOS(); |
1783 } else { | 1783 } else { |
1784 context()->Plug(eax); | 1784 context()->Plug(eax); |
1785 } | 1785 } |
1786 } | 1786 } |
1787 | 1787 |
1788 | 1788 |
1789 void FullCodeGenerator::VisitAssignment(Assignment* expr) { | 1789 void FullCodeGenerator::VisitAssignment(Assignment* expr) { |
1790 ASSERT(expr->target()->IsValidReferenceExpression()); | 1790 DCHECK(expr->target()->IsValidReferenceExpression()); |
1791 | 1791 |
1792 Comment cmnt(masm_, "[ Assignment"); | 1792 Comment cmnt(masm_, "[ Assignment"); |
1793 | 1793 |
1794 // Left-hand side can only be a property, a global or a (parameter or local) | 1794 // Left-hand side can only be a property, a global or a (parameter or local) |
1795 // slot. | 1795 // slot. |
1796 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 1796 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
1797 LhsKind assign_type = VARIABLE; | 1797 LhsKind assign_type = VARIABLE; |
1798 Property* property = expr->target()->AsProperty(); | 1798 Property* property = expr->target()->AsProperty(); |
1799 if (property != NULL) { | 1799 if (property != NULL) { |
1800 assign_type = (property->key()->IsPropertyName()) | 1800 assign_type = (property->key()->IsPropertyName()) |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1911 case Yield::INITIAL: { | 1911 case Yield::INITIAL: { |
1912 Label suspend, continuation, post_runtime, resume; | 1912 Label suspend, continuation, post_runtime, resume; |
1913 | 1913 |
1914 __ jmp(&suspend); | 1914 __ jmp(&suspend); |
1915 | 1915 |
1916 __ bind(&continuation); | 1916 __ bind(&continuation); |
1917 __ jmp(&resume); | 1917 __ jmp(&resume); |
1918 | 1918 |
1919 __ bind(&suspend); | 1919 __ bind(&suspend); |
1920 VisitForAccumulatorValue(expr->generator_object()); | 1920 VisitForAccumulatorValue(expr->generator_object()); |
1921 ASSERT(continuation.pos() > 0 && Smi::IsValid(continuation.pos())); | 1921 DCHECK(continuation.pos() > 0 && Smi::IsValid(continuation.pos())); |
1922 __ mov(FieldOperand(eax, JSGeneratorObject::kContinuationOffset), | 1922 __ mov(FieldOperand(eax, JSGeneratorObject::kContinuationOffset), |
1923 Immediate(Smi::FromInt(continuation.pos()))); | 1923 Immediate(Smi::FromInt(continuation.pos()))); |
1924 __ mov(FieldOperand(eax, JSGeneratorObject::kContextOffset), esi); | 1924 __ mov(FieldOperand(eax, JSGeneratorObject::kContextOffset), esi); |
1925 __ mov(ecx, esi); | 1925 __ mov(ecx, esi); |
1926 __ RecordWriteField(eax, JSGeneratorObject::kContextOffset, ecx, edx); | 1926 __ RecordWriteField(eax, JSGeneratorObject::kContextOffset, ecx, edx); |
1927 __ lea(ebx, Operand(ebp, StandardFrameConstants::kExpressionsOffset)); | 1927 __ lea(ebx, Operand(ebp, StandardFrameConstants::kExpressionsOffset)); |
1928 __ cmp(esp, ebx); | 1928 __ cmp(esp, ebx); |
1929 __ j(equal, &post_runtime); | 1929 __ j(equal, &post_runtime); |
1930 __ push(eax); // generator object | 1930 __ push(eax); // generator object |
1931 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); | 1931 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1985 __ PushTryHandler(StackHandler::CATCH, expr->index()); | 1985 __ PushTryHandler(StackHandler::CATCH, expr->index()); |
1986 const int handler_size = StackHandlerConstants::kSize; | 1986 const int handler_size = StackHandlerConstants::kSize; |
1987 __ push(eax); // result | 1987 __ push(eax); // result |
1988 __ jmp(&l_suspend); | 1988 __ jmp(&l_suspend); |
1989 __ bind(&l_continuation); | 1989 __ bind(&l_continuation); |
1990 __ jmp(&l_resume); | 1990 __ jmp(&l_resume); |
1991 __ bind(&l_suspend); | 1991 __ bind(&l_suspend); |
1992 const int generator_object_depth = kPointerSize + handler_size; | 1992 const int generator_object_depth = kPointerSize + handler_size; |
1993 __ mov(eax, Operand(esp, generator_object_depth)); | 1993 __ mov(eax, Operand(esp, generator_object_depth)); |
1994 __ push(eax); // g | 1994 __ push(eax); // g |
1995 ASSERT(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos())); | 1995 DCHECK(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos())); |
1996 __ mov(FieldOperand(eax, JSGeneratorObject::kContinuationOffset), | 1996 __ mov(FieldOperand(eax, JSGeneratorObject::kContinuationOffset), |
1997 Immediate(Smi::FromInt(l_continuation.pos()))); | 1997 Immediate(Smi::FromInt(l_continuation.pos()))); |
1998 __ mov(FieldOperand(eax, JSGeneratorObject::kContextOffset), esi); | 1998 __ mov(FieldOperand(eax, JSGeneratorObject::kContextOffset), esi); |
1999 __ mov(ecx, esi); | 1999 __ mov(ecx, esi); |
2000 __ RecordWriteField(eax, JSGeneratorObject::kContextOffset, ecx, edx); | 2000 __ RecordWriteField(eax, JSGeneratorObject::kContextOffset, ecx, edx); |
2001 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); | 2001 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); |
2002 __ mov(context_register(), | 2002 __ mov(context_register(), |
2003 Operand(ebp, StandardFrameConstants::kContextOffset)); | 2003 Operand(ebp, StandardFrameConstants::kContextOffset)); |
2004 __ pop(eax); // result | 2004 __ pop(eax); // result |
2005 EmitReturnSequence(); | 2005 EmitReturnSequence(); |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2187 __ bind(&gc_required); | 2187 __ bind(&gc_required); |
2188 __ Push(Smi::FromInt(map->instance_size())); | 2188 __ Push(Smi::FromInt(map->instance_size())); |
2189 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); | 2189 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); |
2190 __ mov(context_register(), | 2190 __ mov(context_register(), |
2191 Operand(ebp, StandardFrameConstants::kContextOffset)); | 2191 Operand(ebp, StandardFrameConstants::kContextOffset)); |
2192 | 2192 |
2193 __ bind(&allocated); | 2193 __ bind(&allocated); |
2194 __ mov(ebx, map); | 2194 __ mov(ebx, map); |
2195 __ pop(ecx); | 2195 __ pop(ecx); |
2196 __ mov(edx, isolate()->factory()->ToBoolean(done)); | 2196 __ mov(edx, isolate()->factory()->ToBoolean(done)); |
2197 ASSERT_EQ(map->instance_size(), 5 * kPointerSize); | 2197 DCHECK_EQ(map->instance_size(), 5 * kPointerSize); |
2198 __ mov(FieldOperand(eax, HeapObject::kMapOffset), ebx); | 2198 __ mov(FieldOperand(eax, HeapObject::kMapOffset), ebx); |
2199 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), | 2199 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), |
2200 isolate()->factory()->empty_fixed_array()); | 2200 isolate()->factory()->empty_fixed_array()); |
2201 __ mov(FieldOperand(eax, JSObject::kElementsOffset), | 2201 __ mov(FieldOperand(eax, JSObject::kElementsOffset), |
2202 isolate()->factory()->empty_fixed_array()); | 2202 isolate()->factory()->empty_fixed_array()); |
2203 __ mov(FieldOperand(eax, JSGeneratorObject::kResultValuePropertyOffset), ecx); | 2203 __ mov(FieldOperand(eax, JSGeneratorObject::kResultValuePropertyOffset), ecx); |
2204 __ mov(FieldOperand(eax, JSGeneratorObject::kResultDonePropertyOffset), edx); | 2204 __ mov(FieldOperand(eax, JSGeneratorObject::kResultDonePropertyOffset), edx); |
2205 | 2205 |
2206 // Only the value field needs a write barrier, as the other values are in the | 2206 // Only the value field needs a write barrier, as the other values are in the |
2207 // root set. | 2207 // root set. |
2208 __ RecordWriteField(eax, JSGeneratorObject::kResultValuePropertyOffset, | 2208 __ RecordWriteField(eax, JSGeneratorObject::kResultValuePropertyOffset, |
2209 ecx, edx); | 2209 ecx, edx); |
2210 } | 2210 } |
2211 | 2211 |
2212 | 2212 |
2213 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { | 2213 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { |
2214 SetSourcePosition(prop->position()); | 2214 SetSourcePosition(prop->position()); |
2215 Literal* key = prop->key()->AsLiteral(); | 2215 Literal* key = prop->key()->AsLiteral(); |
2216 ASSERT(!key->value()->IsSmi()); | 2216 DCHECK(!key->value()->IsSmi()); |
2217 __ mov(LoadIC::NameRegister(), Immediate(key->value())); | 2217 __ mov(LoadIC::NameRegister(), Immediate(key->value())); |
2218 if (FLAG_vector_ics) { | 2218 if (FLAG_vector_ics) { |
2219 __ mov(LoadIC::SlotRegister(), | 2219 __ mov(LoadIC::SlotRegister(), |
2220 Immediate(Smi::FromInt(prop->PropertyFeedbackSlot()))); | 2220 Immediate(Smi::FromInt(prop->PropertyFeedbackSlot()))); |
2221 CallLoadIC(NOT_CONTEXTUAL); | 2221 CallLoadIC(NOT_CONTEXTUAL); |
2222 } else { | 2222 } else { |
2223 CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId()); | 2223 CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId()); |
2224 } | 2224 } |
2225 } | 2225 } |
2226 | 2226 |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2339 __ pop(edx); | 2339 __ pop(edx); |
2340 BinaryOpICStub stub(isolate(), op, mode); | 2340 BinaryOpICStub stub(isolate(), op, mode); |
2341 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. | 2341 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. |
2342 CallIC(stub.GetCode(), expr->BinaryOperationFeedbackId()); | 2342 CallIC(stub.GetCode(), expr->BinaryOperationFeedbackId()); |
2343 patch_site.EmitPatchInfo(); | 2343 patch_site.EmitPatchInfo(); |
2344 context()->Plug(eax); | 2344 context()->Plug(eax); |
2345 } | 2345 } |
2346 | 2346 |
2347 | 2347 |
2348 void FullCodeGenerator::EmitAssignment(Expression* expr) { | 2348 void FullCodeGenerator::EmitAssignment(Expression* expr) { |
2349 ASSERT(expr->IsValidReferenceExpression()); | 2349 DCHECK(expr->IsValidReferenceExpression()); |
2350 | 2350 |
2351 // Left-hand side can only be a property, a global or a (parameter or local) | 2351 // Left-hand side can only be a property, a global or a (parameter or local) |
2352 // slot. | 2352 // slot. |
2353 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 2353 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
2354 LhsKind assign_type = VARIABLE; | 2354 LhsKind assign_type = VARIABLE; |
2355 Property* prop = expr->AsProperty(); | 2355 Property* prop = expr->AsProperty(); |
2356 if (prop != NULL) { | 2356 if (prop != NULL) { |
2357 assign_type = (prop->key()->IsPropertyName()) | 2357 assign_type = (prop->key()->IsPropertyName()) |
2358 ? NAMED_PROPERTY | 2358 ? NAMED_PROPERTY |
2359 : KEYED_PROPERTY; | 2359 : KEYED_PROPERTY; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2407 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 2407 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
2408 Token::Value op) { | 2408 Token::Value op) { |
2409 if (var->IsUnallocated()) { | 2409 if (var->IsUnallocated()) { |
2410 // Global var, const, or let. | 2410 // Global var, const, or let. |
2411 __ mov(StoreIC::NameRegister(), var->name()); | 2411 __ mov(StoreIC::NameRegister(), var->name()); |
2412 __ mov(StoreIC::ReceiverRegister(), GlobalObjectOperand()); | 2412 __ mov(StoreIC::ReceiverRegister(), GlobalObjectOperand()); |
2413 CallStoreIC(); | 2413 CallStoreIC(); |
2414 | 2414 |
2415 } else if (op == Token::INIT_CONST_LEGACY) { | 2415 } else if (op == Token::INIT_CONST_LEGACY) { |
2416 // Const initializers need a write barrier. | 2416 // Const initializers need a write barrier. |
2417 ASSERT(!var->IsParameter()); // No const parameters. | 2417 DCHECK(!var->IsParameter()); // No const parameters. |
2418 if (var->IsLookupSlot()) { | 2418 if (var->IsLookupSlot()) { |
2419 __ push(eax); | 2419 __ push(eax); |
2420 __ push(esi); | 2420 __ push(esi); |
2421 __ push(Immediate(var->name())); | 2421 __ push(Immediate(var->name())); |
2422 __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot, 3); | 2422 __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot, 3); |
2423 } else { | 2423 } else { |
2424 ASSERT(var->IsStackLocal() || var->IsContextSlot()); | 2424 DCHECK(var->IsStackLocal() || var->IsContextSlot()); |
2425 Label skip; | 2425 Label skip; |
2426 MemOperand location = VarOperand(var, ecx); | 2426 MemOperand location = VarOperand(var, ecx); |
2427 __ mov(edx, location); | 2427 __ mov(edx, location); |
2428 __ cmp(edx, isolate()->factory()->the_hole_value()); | 2428 __ cmp(edx, isolate()->factory()->the_hole_value()); |
2429 __ j(not_equal, &skip, Label::kNear); | 2429 __ j(not_equal, &skip, Label::kNear); |
2430 EmitStoreToStackLocalOrContextSlot(var, location); | 2430 EmitStoreToStackLocalOrContextSlot(var, location); |
2431 __ bind(&skip); | 2431 __ bind(&skip); |
2432 } | 2432 } |
2433 | 2433 |
2434 } else if (var->mode() == LET && op != Token::INIT_LET) { | 2434 } else if (var->mode() == LET && op != Token::INIT_LET) { |
2435 // Non-initializing assignment to let variable needs a write barrier. | 2435 // Non-initializing assignment to let variable needs a write barrier. |
2436 ASSERT(!var->IsLookupSlot()); | 2436 DCHECK(!var->IsLookupSlot()); |
2437 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); | 2437 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
2438 Label assign; | 2438 Label assign; |
2439 MemOperand location = VarOperand(var, ecx); | 2439 MemOperand location = VarOperand(var, ecx); |
2440 __ mov(edx, location); | 2440 __ mov(edx, location); |
2441 __ cmp(edx, isolate()->factory()->the_hole_value()); | 2441 __ cmp(edx, isolate()->factory()->the_hole_value()); |
2442 __ j(not_equal, &assign, Label::kNear); | 2442 __ j(not_equal, &assign, Label::kNear); |
2443 __ push(Immediate(var->name())); | 2443 __ push(Immediate(var->name())); |
2444 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 2444 __ CallRuntime(Runtime::kThrowReferenceError, 1); |
2445 __ bind(&assign); | 2445 __ bind(&assign); |
2446 EmitStoreToStackLocalOrContextSlot(var, location); | 2446 EmitStoreToStackLocalOrContextSlot(var, location); |
2447 | 2447 |
2448 } else if (!var->is_const_mode() || op == Token::INIT_CONST) { | 2448 } else if (!var->is_const_mode() || op == Token::INIT_CONST) { |
2449 if (var->IsLookupSlot()) { | 2449 if (var->IsLookupSlot()) { |
2450 // Assignment to var. | 2450 // Assignment to var. |
2451 __ push(eax); // Value. | 2451 __ push(eax); // Value. |
2452 __ push(esi); // Context. | 2452 __ push(esi); // Context. |
2453 __ push(Immediate(var->name())); | 2453 __ push(Immediate(var->name())); |
2454 __ push(Immediate(Smi::FromInt(strict_mode()))); | 2454 __ push(Immediate(Smi::FromInt(strict_mode()))); |
2455 __ CallRuntime(Runtime::kStoreLookupSlot, 4); | 2455 __ CallRuntime(Runtime::kStoreLookupSlot, 4); |
2456 } else { | 2456 } else { |
2457 // Assignment to var or initializing assignment to let/const in harmony | 2457 // Assignment to var or initializing assignment to let/const in harmony |
2458 // mode. | 2458 // mode. |
2459 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); | 2459 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
2460 MemOperand location = VarOperand(var, ecx); | 2460 MemOperand location = VarOperand(var, ecx); |
2461 if (generate_debug_code_ && op == Token::INIT_LET) { | 2461 if (generate_debug_code_ && op == Token::INIT_LET) { |
2462 // Check for an uninitialized let binding. | 2462 // Check for an uninitialized let binding. |
2463 __ mov(edx, location); | 2463 __ mov(edx, location); |
2464 __ cmp(edx, isolate()->factory()->the_hole_value()); | 2464 __ cmp(edx, isolate()->factory()->the_hole_value()); |
2465 __ Check(equal, kLetBindingReInitialization); | 2465 __ Check(equal, kLetBindingReInitialization); |
2466 } | 2466 } |
2467 EmitStoreToStackLocalOrContextSlot(var, location); | 2467 EmitStoreToStackLocalOrContextSlot(var, location); |
2468 } | 2468 } |
2469 } | 2469 } |
2470 // Non-initializing assignments to consts are ignored. | 2470 // Non-initializing assignments to consts are ignored. |
2471 } | 2471 } |
2472 | 2472 |
2473 | 2473 |
2474 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 2474 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
2475 // Assignment to a property, using a named store IC. | 2475 // Assignment to a property, using a named store IC. |
2476 // eax : value | 2476 // eax : value |
2477 // esp[0] : receiver | 2477 // esp[0] : receiver |
2478 | 2478 |
2479 Property* prop = expr->target()->AsProperty(); | 2479 Property* prop = expr->target()->AsProperty(); |
2480 ASSERT(prop != NULL); | 2480 DCHECK(prop != NULL); |
2481 ASSERT(prop->key()->IsLiteral()); | 2481 DCHECK(prop->key()->IsLiteral()); |
2482 | 2482 |
2483 // Record source code position before IC call. | 2483 // Record source code position before IC call. |
2484 SetSourcePosition(expr->position()); | 2484 SetSourcePosition(expr->position()); |
2485 __ mov(StoreIC::NameRegister(), prop->key()->AsLiteral()->value()); | 2485 __ mov(StoreIC::NameRegister(), prop->key()->AsLiteral()->value()); |
2486 __ pop(StoreIC::ReceiverRegister()); | 2486 __ pop(StoreIC::ReceiverRegister()); |
2487 CallStoreIC(expr->AssignmentFeedbackId()); | 2487 CallStoreIC(expr->AssignmentFeedbackId()); |
2488 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 2488 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
2489 context()->Plug(eax); | 2489 context()->Plug(eax); |
2490 } | 2490 } |
2491 | 2491 |
2492 | 2492 |
2493 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 2493 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
2494 // Assignment to a property, using a keyed store IC. | 2494 // Assignment to a property, using a keyed store IC. |
2495 // eax : value | 2495 // eax : value |
2496 // esp[0] : key | 2496 // esp[0] : key |
2497 // esp[kPointerSize] : receiver | 2497 // esp[kPointerSize] : receiver |
2498 | 2498 |
2499 __ pop(KeyedStoreIC::NameRegister()); // Key. | 2499 __ pop(KeyedStoreIC::NameRegister()); // Key. |
2500 __ pop(KeyedStoreIC::ReceiverRegister()); | 2500 __ pop(KeyedStoreIC::ReceiverRegister()); |
2501 ASSERT(KeyedStoreIC::ValueRegister().is(eax)); | 2501 DCHECK(KeyedStoreIC::ValueRegister().is(eax)); |
2502 // Record source code position before IC call. | 2502 // Record source code position before IC call. |
2503 SetSourcePosition(expr->position()); | 2503 SetSourcePosition(expr->position()); |
2504 Handle<Code> ic = strict_mode() == SLOPPY | 2504 Handle<Code> ic = strict_mode() == SLOPPY |
2505 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 2505 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
2506 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 2506 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
2507 CallIC(ic, expr->AssignmentFeedbackId()); | 2507 CallIC(ic, expr->AssignmentFeedbackId()); |
2508 | 2508 |
2509 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 2509 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
2510 context()->Plug(eax); | 2510 context()->Plug(eax); |
2511 } | 2511 } |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2550 if (call_type == CallIC::FUNCTION) { | 2550 if (call_type == CallIC::FUNCTION) { |
2551 { StackValueContext context(this); | 2551 { StackValueContext context(this); |
2552 EmitVariableLoad(callee->AsVariableProxy()); | 2552 EmitVariableLoad(callee->AsVariableProxy()); |
2553 PrepareForBailout(callee, NO_REGISTERS); | 2553 PrepareForBailout(callee, NO_REGISTERS); |
2554 } | 2554 } |
2555 // Push undefined as receiver. This is patched in the method prologue if it | 2555 // Push undefined as receiver. This is patched in the method prologue if it |
2556 // is a sloppy mode method. | 2556 // is a sloppy mode method. |
2557 __ push(Immediate(isolate()->factory()->undefined_value())); | 2557 __ push(Immediate(isolate()->factory()->undefined_value())); |
2558 } else { | 2558 } else { |
2559 // Load the function from the receiver. | 2559 // Load the function from the receiver. |
2560 ASSERT(callee->IsProperty()); | 2560 DCHECK(callee->IsProperty()); |
2561 __ mov(LoadIC::ReceiverRegister(), Operand(esp, 0)); | 2561 __ mov(LoadIC::ReceiverRegister(), Operand(esp, 0)); |
2562 EmitNamedPropertyLoad(callee->AsProperty()); | 2562 EmitNamedPropertyLoad(callee->AsProperty()); |
2563 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); | 2563 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); |
2564 // Push the target function under the receiver. | 2564 // Push the target function under the receiver. |
2565 __ push(Operand(esp, 0)); | 2565 __ push(Operand(esp, 0)); |
2566 __ mov(Operand(esp, kPointerSize), eax); | 2566 __ mov(Operand(esp, kPointerSize), eax); |
2567 } | 2567 } |
2568 | 2568 |
2569 EmitCall(expr, call_type); | 2569 EmitCall(expr, call_type); |
2570 } | 2570 } |
2571 | 2571 |
2572 | 2572 |
2573 // Code common for calls using the IC. | 2573 // Code common for calls using the IC. |
2574 void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr, | 2574 void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr, |
2575 Expression* key) { | 2575 Expression* key) { |
2576 // Load the key. | 2576 // Load the key. |
2577 VisitForAccumulatorValue(key); | 2577 VisitForAccumulatorValue(key); |
2578 | 2578 |
2579 Expression* callee = expr->expression(); | 2579 Expression* callee = expr->expression(); |
2580 | 2580 |
2581 // Load the function from the receiver. | 2581 // Load the function from the receiver. |
2582 ASSERT(callee->IsProperty()); | 2582 DCHECK(callee->IsProperty()); |
2583 __ mov(LoadIC::ReceiverRegister(), Operand(esp, 0)); | 2583 __ mov(LoadIC::ReceiverRegister(), Operand(esp, 0)); |
2584 __ mov(LoadIC::NameRegister(), eax); | 2584 __ mov(LoadIC::NameRegister(), eax); |
2585 EmitKeyedPropertyLoad(callee->AsProperty()); | 2585 EmitKeyedPropertyLoad(callee->AsProperty()); |
2586 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); | 2586 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); |
2587 | 2587 |
2588 // Push the target function under the receiver. | 2588 // Push the target function under the receiver. |
2589 __ push(Operand(esp, 0)); | 2589 __ push(Operand(esp, 0)); |
2590 __ mov(Operand(esp, kPointerSize), eax); | 2590 __ mov(Operand(esp, kPointerSize), eax); |
2591 | 2591 |
2592 EmitCall(expr, CallIC::METHOD); | 2592 EmitCall(expr, CallIC::METHOD); |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2733 { PreservePositionScope scope(masm()->positions_recorder()); | 2733 { PreservePositionScope scope(masm()->positions_recorder()); |
2734 VisitForStackValue(property->obj()); | 2734 VisitForStackValue(property->obj()); |
2735 } | 2735 } |
2736 if (property->key()->IsPropertyName()) { | 2736 if (property->key()->IsPropertyName()) { |
2737 EmitCallWithLoadIC(expr); | 2737 EmitCallWithLoadIC(expr); |
2738 } else { | 2738 } else { |
2739 EmitKeyedCallWithLoadIC(expr, property->key()); | 2739 EmitKeyedCallWithLoadIC(expr, property->key()); |
2740 } | 2740 } |
2741 | 2741 |
2742 } else { | 2742 } else { |
2743 ASSERT(call_type == Call::OTHER_CALL); | 2743 DCHECK(call_type == Call::OTHER_CALL); |
2744 // Call to an arbitrary expression not handled specially above. | 2744 // Call to an arbitrary expression not handled specially above. |
2745 { PreservePositionScope scope(masm()->positions_recorder()); | 2745 { PreservePositionScope scope(masm()->positions_recorder()); |
2746 VisitForStackValue(callee); | 2746 VisitForStackValue(callee); |
2747 } | 2747 } |
2748 __ push(Immediate(isolate()->factory()->undefined_value())); | 2748 __ push(Immediate(isolate()->factory()->undefined_value())); |
2749 // Emit function call. | 2749 // Emit function call. |
2750 EmitCall(expr); | 2750 EmitCall(expr); |
2751 } | 2751 } |
2752 | 2752 |
2753 #ifdef DEBUG | 2753 #ifdef DEBUG |
2754 // RecordJSReturnSite should have been called. | 2754 // RecordJSReturnSite should have been called. |
2755 ASSERT(expr->return_is_recorded_); | 2755 DCHECK(expr->return_is_recorded_); |
2756 #endif | 2756 #endif |
2757 } | 2757 } |
2758 | 2758 |
2759 | 2759 |
2760 void FullCodeGenerator::VisitCallNew(CallNew* expr) { | 2760 void FullCodeGenerator::VisitCallNew(CallNew* expr) { |
2761 Comment cmnt(masm_, "[ CallNew"); | 2761 Comment cmnt(masm_, "[ CallNew"); |
2762 // According to ECMA-262, section 11.2.2, page 44, the function | 2762 // According to ECMA-262, section 11.2.2, page 44, the function |
2763 // expression in new calls must be evaluated before the | 2763 // expression in new calls must be evaluated before the |
2764 // arguments. | 2764 // arguments. |
2765 | 2765 |
(...skipping 13 matching lines...) Expand all Loading... |
2779 // constructor invocation. | 2779 // constructor invocation. |
2780 SetSourcePosition(expr->position()); | 2780 SetSourcePosition(expr->position()); |
2781 | 2781 |
2782 // Load function and argument count into edi and eax. | 2782 // Load function and argument count into edi and eax. |
2783 __ Move(eax, Immediate(arg_count)); | 2783 __ Move(eax, Immediate(arg_count)); |
2784 __ mov(edi, Operand(esp, arg_count * kPointerSize)); | 2784 __ mov(edi, Operand(esp, arg_count * kPointerSize)); |
2785 | 2785 |
2786 // Record call targets in unoptimized code. | 2786 // Record call targets in unoptimized code. |
2787 if (FLAG_pretenuring_call_new) { | 2787 if (FLAG_pretenuring_call_new) { |
2788 EnsureSlotContainsAllocationSite(expr->AllocationSiteFeedbackSlot()); | 2788 EnsureSlotContainsAllocationSite(expr->AllocationSiteFeedbackSlot()); |
2789 ASSERT(expr->AllocationSiteFeedbackSlot() == | 2789 DCHECK(expr->AllocationSiteFeedbackSlot() == |
2790 expr->CallNewFeedbackSlot() + 1); | 2790 expr->CallNewFeedbackSlot() + 1); |
2791 } | 2791 } |
2792 | 2792 |
2793 __ LoadHeapObject(ebx, FeedbackVector()); | 2793 __ LoadHeapObject(ebx, FeedbackVector()); |
2794 __ mov(edx, Immediate(Smi::FromInt(expr->CallNewFeedbackSlot()))); | 2794 __ mov(edx, Immediate(Smi::FromInt(expr->CallNewFeedbackSlot()))); |
2795 | 2795 |
2796 CallConstructStub stub(isolate(), RECORD_CONSTRUCTOR_TARGET); | 2796 CallConstructStub stub(isolate(), RECORD_CONSTRUCTOR_TARGET); |
2797 __ call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL); | 2797 __ call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL); |
2798 PrepareForBailoutForId(expr->ReturnId(), TOS_REG); | 2798 PrepareForBailoutForId(expr->ReturnId(), TOS_REG); |
2799 context()->Plug(eax); | 2799 context()->Plug(eax); |
2800 } | 2800 } |
2801 | 2801 |
2802 | 2802 |
2803 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { | 2803 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { |
2804 ZoneList<Expression*>* args = expr->arguments(); | 2804 ZoneList<Expression*>* args = expr->arguments(); |
2805 ASSERT(args->length() == 1); | 2805 DCHECK(args->length() == 1); |
2806 | 2806 |
2807 VisitForAccumulatorValue(args->at(0)); | 2807 VisitForAccumulatorValue(args->at(0)); |
2808 | 2808 |
2809 Label materialize_true, materialize_false; | 2809 Label materialize_true, materialize_false; |
2810 Label* if_true = NULL; | 2810 Label* if_true = NULL; |
2811 Label* if_false = NULL; | 2811 Label* if_false = NULL; |
2812 Label* fall_through = NULL; | 2812 Label* fall_through = NULL; |
2813 context()->PrepareTest(&materialize_true, &materialize_false, | 2813 context()->PrepareTest(&materialize_true, &materialize_false, |
2814 &if_true, &if_false, &fall_through); | 2814 &if_true, &if_false, &fall_through); |
2815 | 2815 |
2816 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 2816 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
2817 __ test(eax, Immediate(kSmiTagMask)); | 2817 __ test(eax, Immediate(kSmiTagMask)); |
2818 Split(zero, if_true, if_false, fall_through); | 2818 Split(zero, if_true, if_false, fall_through); |
2819 | 2819 |
2820 context()->Plug(if_true, if_false); | 2820 context()->Plug(if_true, if_false); |
2821 } | 2821 } |
2822 | 2822 |
2823 | 2823 |
2824 void FullCodeGenerator::EmitIsNonNegativeSmi(CallRuntime* expr) { | 2824 void FullCodeGenerator::EmitIsNonNegativeSmi(CallRuntime* expr) { |
2825 ZoneList<Expression*>* args = expr->arguments(); | 2825 ZoneList<Expression*>* args = expr->arguments(); |
2826 ASSERT(args->length() == 1); | 2826 DCHECK(args->length() == 1); |
2827 | 2827 |
2828 VisitForAccumulatorValue(args->at(0)); | 2828 VisitForAccumulatorValue(args->at(0)); |
2829 | 2829 |
2830 Label materialize_true, materialize_false; | 2830 Label materialize_true, materialize_false; |
2831 Label* if_true = NULL; | 2831 Label* if_true = NULL; |
2832 Label* if_false = NULL; | 2832 Label* if_false = NULL; |
2833 Label* fall_through = NULL; | 2833 Label* fall_through = NULL; |
2834 context()->PrepareTest(&materialize_true, &materialize_false, | 2834 context()->PrepareTest(&materialize_true, &materialize_false, |
2835 &if_true, &if_false, &fall_through); | 2835 &if_true, &if_false, &fall_through); |
2836 | 2836 |
2837 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 2837 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
2838 __ test(eax, Immediate(kSmiTagMask | 0x80000000)); | 2838 __ test(eax, Immediate(kSmiTagMask | 0x80000000)); |
2839 Split(zero, if_true, if_false, fall_through); | 2839 Split(zero, if_true, if_false, fall_through); |
2840 | 2840 |
2841 context()->Plug(if_true, if_false); | 2841 context()->Plug(if_true, if_false); |
2842 } | 2842 } |
2843 | 2843 |
2844 | 2844 |
2845 void FullCodeGenerator::EmitIsObject(CallRuntime* expr) { | 2845 void FullCodeGenerator::EmitIsObject(CallRuntime* expr) { |
2846 ZoneList<Expression*>* args = expr->arguments(); | 2846 ZoneList<Expression*>* args = expr->arguments(); |
2847 ASSERT(args->length() == 1); | 2847 DCHECK(args->length() == 1); |
2848 | 2848 |
2849 VisitForAccumulatorValue(args->at(0)); | 2849 VisitForAccumulatorValue(args->at(0)); |
2850 | 2850 |
2851 Label materialize_true, materialize_false; | 2851 Label materialize_true, materialize_false; |
2852 Label* if_true = NULL; | 2852 Label* if_true = NULL; |
2853 Label* if_false = NULL; | 2853 Label* if_false = NULL; |
2854 Label* fall_through = NULL; | 2854 Label* fall_through = NULL; |
2855 context()->PrepareTest(&materialize_true, &materialize_false, | 2855 context()->PrepareTest(&materialize_true, &materialize_false, |
2856 &if_true, &if_false, &fall_through); | 2856 &if_true, &if_false, &fall_through); |
2857 | 2857 |
(...skipping 11 matching lines...) Expand all Loading... |
2869 __ cmp(ecx, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); | 2869 __ cmp(ecx, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); |
2870 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 2870 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
2871 Split(below_equal, if_true, if_false, fall_through); | 2871 Split(below_equal, if_true, if_false, fall_through); |
2872 | 2872 |
2873 context()->Plug(if_true, if_false); | 2873 context()->Plug(if_true, if_false); |
2874 } | 2874 } |
2875 | 2875 |
2876 | 2876 |
2877 void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) { | 2877 void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) { |
2878 ZoneList<Expression*>* args = expr->arguments(); | 2878 ZoneList<Expression*>* args = expr->arguments(); |
2879 ASSERT(args->length() == 1); | 2879 DCHECK(args->length() == 1); |
2880 | 2880 |
2881 VisitForAccumulatorValue(args->at(0)); | 2881 VisitForAccumulatorValue(args->at(0)); |
2882 | 2882 |
2883 Label materialize_true, materialize_false; | 2883 Label materialize_true, materialize_false; |
2884 Label* if_true = NULL; | 2884 Label* if_true = NULL; |
2885 Label* if_false = NULL; | 2885 Label* if_false = NULL; |
2886 Label* fall_through = NULL; | 2886 Label* fall_through = NULL; |
2887 context()->PrepareTest(&materialize_true, &materialize_false, | 2887 context()->PrepareTest(&materialize_true, &materialize_false, |
2888 &if_true, &if_false, &fall_through); | 2888 &if_true, &if_false, &fall_through); |
2889 | 2889 |
2890 __ JumpIfSmi(eax, if_false); | 2890 __ JumpIfSmi(eax, if_false); |
2891 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ebx); | 2891 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ebx); |
2892 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 2892 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
2893 Split(above_equal, if_true, if_false, fall_through); | 2893 Split(above_equal, if_true, if_false, fall_through); |
2894 | 2894 |
2895 context()->Plug(if_true, if_false); | 2895 context()->Plug(if_true, if_false); |
2896 } | 2896 } |
2897 | 2897 |
2898 | 2898 |
2899 void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) { | 2899 void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) { |
2900 ZoneList<Expression*>* args = expr->arguments(); | 2900 ZoneList<Expression*>* args = expr->arguments(); |
2901 ASSERT(args->length() == 1); | 2901 DCHECK(args->length() == 1); |
2902 | 2902 |
2903 VisitForAccumulatorValue(args->at(0)); | 2903 VisitForAccumulatorValue(args->at(0)); |
2904 | 2904 |
2905 Label materialize_true, materialize_false; | 2905 Label materialize_true, materialize_false; |
2906 Label* if_true = NULL; | 2906 Label* if_true = NULL; |
2907 Label* if_false = NULL; | 2907 Label* if_false = NULL; |
2908 Label* fall_through = NULL; | 2908 Label* fall_through = NULL; |
2909 context()->PrepareTest(&materialize_true, &materialize_false, | 2909 context()->PrepareTest(&materialize_true, &materialize_false, |
2910 &if_true, &if_false, &fall_through); | 2910 &if_true, &if_false, &fall_through); |
2911 | 2911 |
2912 __ JumpIfSmi(eax, if_false); | 2912 __ JumpIfSmi(eax, if_false); |
2913 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | 2913 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
2914 __ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset)); | 2914 __ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset)); |
2915 __ test(ebx, Immediate(1 << Map::kIsUndetectable)); | 2915 __ test(ebx, Immediate(1 << Map::kIsUndetectable)); |
2916 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 2916 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
2917 Split(not_zero, if_true, if_false, fall_through); | 2917 Split(not_zero, if_true, if_false, fall_through); |
2918 | 2918 |
2919 context()->Plug(if_true, if_false); | 2919 context()->Plug(if_true, if_false); |
2920 } | 2920 } |
2921 | 2921 |
2922 | 2922 |
2923 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( | 2923 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( |
2924 CallRuntime* expr) { | 2924 CallRuntime* expr) { |
2925 ZoneList<Expression*>* args = expr->arguments(); | 2925 ZoneList<Expression*>* args = expr->arguments(); |
2926 ASSERT(args->length() == 1); | 2926 DCHECK(args->length() == 1); |
2927 | 2927 |
2928 VisitForAccumulatorValue(args->at(0)); | 2928 VisitForAccumulatorValue(args->at(0)); |
2929 | 2929 |
2930 Label materialize_true, materialize_false, skip_lookup; | 2930 Label materialize_true, materialize_false, skip_lookup; |
2931 Label* if_true = NULL; | 2931 Label* if_true = NULL; |
2932 Label* if_false = NULL; | 2932 Label* if_false = NULL; |
2933 Label* fall_through = NULL; | 2933 Label* fall_through = NULL; |
2934 context()->PrepareTest(&materialize_true, &materialize_false, | 2934 context()->PrepareTest(&materialize_true, &materialize_false, |
2935 &if_true, &if_false, &fall_through); | 2935 &if_true, &if_false, &fall_through); |
2936 | 2936 |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3006 Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX)); | 3006 Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX)); |
3007 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 3007 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
3008 Split(equal, if_true, if_false, fall_through); | 3008 Split(equal, if_true, if_false, fall_through); |
3009 | 3009 |
3010 context()->Plug(if_true, if_false); | 3010 context()->Plug(if_true, if_false); |
3011 } | 3011 } |
3012 | 3012 |
3013 | 3013 |
3014 void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) { | 3014 void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) { |
3015 ZoneList<Expression*>* args = expr->arguments(); | 3015 ZoneList<Expression*>* args = expr->arguments(); |
3016 ASSERT(args->length() == 1); | 3016 DCHECK(args->length() == 1); |
3017 | 3017 |
3018 VisitForAccumulatorValue(args->at(0)); | 3018 VisitForAccumulatorValue(args->at(0)); |
3019 | 3019 |
3020 Label materialize_true, materialize_false; | 3020 Label materialize_true, materialize_false; |
3021 Label* if_true = NULL; | 3021 Label* if_true = NULL; |
3022 Label* if_false = NULL; | 3022 Label* if_false = NULL; |
3023 Label* fall_through = NULL; | 3023 Label* fall_through = NULL; |
3024 context()->PrepareTest(&materialize_true, &materialize_false, | 3024 context()->PrepareTest(&materialize_true, &materialize_false, |
3025 &if_true, &if_false, &fall_through); | 3025 &if_true, &if_false, &fall_through); |
3026 | 3026 |
3027 __ JumpIfSmi(eax, if_false); | 3027 __ JumpIfSmi(eax, if_false); |
3028 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); | 3028 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); |
3029 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 3029 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
3030 Split(equal, if_true, if_false, fall_through); | 3030 Split(equal, if_true, if_false, fall_through); |
3031 | 3031 |
3032 context()->Plug(if_true, if_false); | 3032 context()->Plug(if_true, if_false); |
3033 } | 3033 } |
3034 | 3034 |
3035 | 3035 |
3036 void FullCodeGenerator::EmitIsMinusZero(CallRuntime* expr) { | 3036 void FullCodeGenerator::EmitIsMinusZero(CallRuntime* expr) { |
3037 ZoneList<Expression*>* args = expr->arguments(); | 3037 ZoneList<Expression*>* args = expr->arguments(); |
3038 ASSERT(args->length() == 1); | 3038 DCHECK(args->length() == 1); |
3039 | 3039 |
3040 VisitForAccumulatorValue(args->at(0)); | 3040 VisitForAccumulatorValue(args->at(0)); |
3041 | 3041 |
3042 Label materialize_true, materialize_false; | 3042 Label materialize_true, materialize_false; |
3043 Label* if_true = NULL; | 3043 Label* if_true = NULL; |
3044 Label* if_false = NULL; | 3044 Label* if_false = NULL; |
3045 Label* fall_through = NULL; | 3045 Label* fall_through = NULL; |
3046 context()->PrepareTest(&materialize_true, &materialize_false, | 3046 context()->PrepareTest(&materialize_true, &materialize_false, |
3047 &if_true, &if_false, &fall_through); | 3047 &if_true, &if_false, &fall_through); |
3048 | 3048 |
3049 Handle<Map> map = masm()->isolate()->factory()->heap_number_map(); | 3049 Handle<Map> map = masm()->isolate()->factory()->heap_number_map(); |
3050 __ CheckMap(eax, map, if_false, DO_SMI_CHECK); | 3050 __ CheckMap(eax, map, if_false, DO_SMI_CHECK); |
3051 // Check if the exponent half is 0x80000000. Comparing against 1 and | 3051 // Check if the exponent half is 0x80000000. Comparing against 1 and |
3052 // checking for overflow is the shortest possible encoding. | 3052 // checking for overflow is the shortest possible encoding. |
3053 __ cmp(FieldOperand(eax, HeapNumber::kExponentOffset), Immediate(0x1)); | 3053 __ cmp(FieldOperand(eax, HeapNumber::kExponentOffset), Immediate(0x1)); |
3054 __ j(no_overflow, if_false); | 3054 __ j(no_overflow, if_false); |
3055 __ cmp(FieldOperand(eax, HeapNumber::kMantissaOffset), Immediate(0x0)); | 3055 __ cmp(FieldOperand(eax, HeapNumber::kMantissaOffset), Immediate(0x0)); |
3056 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 3056 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
3057 Split(equal, if_true, if_false, fall_through); | 3057 Split(equal, if_true, if_false, fall_through); |
3058 | 3058 |
3059 context()->Plug(if_true, if_false); | 3059 context()->Plug(if_true, if_false); |
3060 } | 3060 } |
3061 | 3061 |
3062 | 3062 |
3063 | 3063 |
3064 void FullCodeGenerator::EmitIsArray(CallRuntime* expr) { | 3064 void FullCodeGenerator::EmitIsArray(CallRuntime* expr) { |
3065 ZoneList<Expression*>* args = expr->arguments(); | 3065 ZoneList<Expression*>* args = expr->arguments(); |
3066 ASSERT(args->length() == 1); | 3066 DCHECK(args->length() == 1); |
3067 | 3067 |
3068 VisitForAccumulatorValue(args->at(0)); | 3068 VisitForAccumulatorValue(args->at(0)); |
3069 | 3069 |
3070 Label materialize_true, materialize_false; | 3070 Label materialize_true, materialize_false; |
3071 Label* if_true = NULL; | 3071 Label* if_true = NULL; |
3072 Label* if_false = NULL; | 3072 Label* if_false = NULL; |
3073 Label* fall_through = NULL; | 3073 Label* fall_through = NULL; |
3074 context()->PrepareTest(&materialize_true, &materialize_false, | 3074 context()->PrepareTest(&materialize_true, &materialize_false, |
3075 &if_true, &if_false, &fall_through); | 3075 &if_true, &if_false, &fall_through); |
3076 | 3076 |
3077 __ JumpIfSmi(eax, if_false); | 3077 __ JumpIfSmi(eax, if_false); |
3078 __ CmpObjectType(eax, JS_ARRAY_TYPE, ebx); | 3078 __ CmpObjectType(eax, JS_ARRAY_TYPE, ebx); |
3079 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 3079 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
3080 Split(equal, if_true, if_false, fall_through); | 3080 Split(equal, if_true, if_false, fall_through); |
3081 | 3081 |
3082 context()->Plug(if_true, if_false); | 3082 context()->Plug(if_true, if_false); |
3083 } | 3083 } |
3084 | 3084 |
3085 | 3085 |
3086 void FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) { | 3086 void FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) { |
3087 ZoneList<Expression*>* args = expr->arguments(); | 3087 ZoneList<Expression*>* args = expr->arguments(); |
3088 ASSERT(args->length() == 1); | 3088 DCHECK(args->length() == 1); |
3089 | 3089 |
3090 VisitForAccumulatorValue(args->at(0)); | 3090 VisitForAccumulatorValue(args->at(0)); |
3091 | 3091 |
3092 Label materialize_true, materialize_false; | 3092 Label materialize_true, materialize_false; |
3093 Label* if_true = NULL; | 3093 Label* if_true = NULL; |
3094 Label* if_false = NULL; | 3094 Label* if_false = NULL; |
3095 Label* fall_through = NULL; | 3095 Label* fall_through = NULL; |
3096 context()->PrepareTest(&materialize_true, &materialize_false, | 3096 context()->PrepareTest(&materialize_true, &materialize_false, |
3097 &if_true, &if_false, &fall_through); | 3097 &if_true, &if_false, &fall_through); |
3098 | 3098 |
3099 __ JumpIfSmi(eax, if_false); | 3099 __ JumpIfSmi(eax, if_false); |
3100 __ CmpObjectType(eax, JS_REGEXP_TYPE, ebx); | 3100 __ CmpObjectType(eax, JS_REGEXP_TYPE, ebx); |
3101 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 3101 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
3102 Split(equal, if_true, if_false, fall_through); | 3102 Split(equal, if_true, if_false, fall_through); |
3103 | 3103 |
3104 context()->Plug(if_true, if_false); | 3104 context()->Plug(if_true, if_false); |
3105 } | 3105 } |
3106 | 3106 |
3107 | 3107 |
3108 | 3108 |
3109 void FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) { | 3109 void FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) { |
3110 ASSERT(expr->arguments()->length() == 0); | 3110 DCHECK(expr->arguments()->length() == 0); |
3111 | 3111 |
3112 Label materialize_true, materialize_false; | 3112 Label materialize_true, materialize_false; |
3113 Label* if_true = NULL; | 3113 Label* if_true = NULL; |
3114 Label* if_false = NULL; | 3114 Label* if_false = NULL; |
3115 Label* fall_through = NULL; | 3115 Label* fall_through = NULL; |
3116 context()->PrepareTest(&materialize_true, &materialize_false, | 3116 context()->PrepareTest(&materialize_true, &materialize_false, |
3117 &if_true, &if_false, &fall_through); | 3117 &if_true, &if_false, &fall_through); |
3118 | 3118 |
3119 // Get the frame pointer for the calling frame. | 3119 // Get the frame pointer for the calling frame. |
3120 __ mov(eax, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); | 3120 __ mov(eax, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); |
(...skipping 11 matching lines...) Expand all Loading... |
3132 Immediate(Smi::FromInt(StackFrame::CONSTRUCT))); | 3132 Immediate(Smi::FromInt(StackFrame::CONSTRUCT))); |
3133 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 3133 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
3134 Split(equal, if_true, if_false, fall_through); | 3134 Split(equal, if_true, if_false, fall_through); |
3135 | 3135 |
3136 context()->Plug(if_true, if_false); | 3136 context()->Plug(if_true, if_false); |
3137 } | 3137 } |
3138 | 3138 |
3139 | 3139 |
3140 void FullCodeGenerator::EmitObjectEquals(CallRuntime* expr) { | 3140 void FullCodeGenerator::EmitObjectEquals(CallRuntime* expr) { |
3141 ZoneList<Expression*>* args = expr->arguments(); | 3141 ZoneList<Expression*>* args = expr->arguments(); |
3142 ASSERT(args->length() == 2); | 3142 DCHECK(args->length() == 2); |
3143 | 3143 |
3144 // Load the two objects into registers and perform the comparison. | 3144 // Load the two objects into registers and perform the comparison. |
3145 VisitForStackValue(args->at(0)); | 3145 VisitForStackValue(args->at(0)); |
3146 VisitForAccumulatorValue(args->at(1)); | 3146 VisitForAccumulatorValue(args->at(1)); |
3147 | 3147 |
3148 Label materialize_true, materialize_false; | 3148 Label materialize_true, materialize_false; |
3149 Label* if_true = NULL; | 3149 Label* if_true = NULL; |
3150 Label* if_false = NULL; | 3150 Label* if_false = NULL; |
3151 Label* fall_through = NULL; | 3151 Label* fall_through = NULL; |
3152 context()->PrepareTest(&materialize_true, &materialize_false, | 3152 context()->PrepareTest(&materialize_true, &materialize_false, |
3153 &if_true, &if_false, &fall_through); | 3153 &if_true, &if_false, &fall_through); |
3154 | 3154 |
3155 __ pop(ebx); | 3155 __ pop(ebx); |
3156 __ cmp(eax, ebx); | 3156 __ cmp(eax, ebx); |
3157 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 3157 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
3158 Split(equal, if_true, if_false, fall_through); | 3158 Split(equal, if_true, if_false, fall_through); |
3159 | 3159 |
3160 context()->Plug(if_true, if_false); | 3160 context()->Plug(if_true, if_false); |
3161 } | 3161 } |
3162 | 3162 |
3163 | 3163 |
3164 void FullCodeGenerator::EmitArguments(CallRuntime* expr) { | 3164 void FullCodeGenerator::EmitArguments(CallRuntime* expr) { |
3165 ZoneList<Expression*>* args = expr->arguments(); | 3165 ZoneList<Expression*>* args = expr->arguments(); |
3166 ASSERT(args->length() == 1); | 3166 DCHECK(args->length() == 1); |
3167 | 3167 |
3168 // ArgumentsAccessStub expects the key in edx and the formal | 3168 // ArgumentsAccessStub expects the key in edx and the formal |
3169 // parameter count in eax. | 3169 // parameter count in eax. |
3170 VisitForAccumulatorValue(args->at(0)); | 3170 VisitForAccumulatorValue(args->at(0)); |
3171 __ mov(edx, eax); | 3171 __ mov(edx, eax); |
3172 __ Move(eax, Immediate(Smi::FromInt(info_->scope()->num_parameters()))); | 3172 __ Move(eax, Immediate(Smi::FromInt(info_->scope()->num_parameters()))); |
3173 ArgumentsAccessStub stub(isolate(), ArgumentsAccessStub::READ_ELEMENT); | 3173 ArgumentsAccessStub stub(isolate(), ArgumentsAccessStub::READ_ELEMENT); |
3174 __ CallStub(&stub); | 3174 __ CallStub(&stub); |
3175 context()->Plug(eax); | 3175 context()->Plug(eax); |
3176 } | 3176 } |
3177 | 3177 |
3178 | 3178 |
3179 void FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) { | 3179 void FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) { |
3180 ASSERT(expr->arguments()->length() == 0); | 3180 DCHECK(expr->arguments()->length() == 0); |
3181 | 3181 |
3182 Label exit; | 3182 Label exit; |
3183 // Get the number of formal parameters. | 3183 // Get the number of formal parameters. |
3184 __ Move(eax, Immediate(Smi::FromInt(info_->scope()->num_parameters()))); | 3184 __ Move(eax, Immediate(Smi::FromInt(info_->scope()->num_parameters()))); |
3185 | 3185 |
3186 // Check if the calling frame is an arguments adaptor frame. | 3186 // Check if the calling frame is an arguments adaptor frame. |
3187 __ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); | 3187 __ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); |
3188 __ cmp(Operand(ebx, StandardFrameConstants::kContextOffset), | 3188 __ cmp(Operand(ebx, StandardFrameConstants::kContextOffset), |
3189 Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 3189 Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
3190 __ j(not_equal, &exit); | 3190 __ j(not_equal, &exit); |
3191 | 3191 |
3192 // Arguments adaptor case: Read the arguments length from the | 3192 // Arguments adaptor case: Read the arguments length from the |
3193 // adaptor frame. | 3193 // adaptor frame. |
3194 __ mov(eax, Operand(ebx, ArgumentsAdaptorFrameConstants::kLengthOffset)); | 3194 __ mov(eax, Operand(ebx, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
3195 | 3195 |
3196 __ bind(&exit); | 3196 __ bind(&exit); |
3197 __ AssertSmi(eax); | 3197 __ AssertSmi(eax); |
3198 context()->Plug(eax); | 3198 context()->Plug(eax); |
3199 } | 3199 } |
3200 | 3200 |
3201 | 3201 |
3202 void FullCodeGenerator::EmitClassOf(CallRuntime* expr) { | 3202 void FullCodeGenerator::EmitClassOf(CallRuntime* expr) { |
3203 ZoneList<Expression*>* args = expr->arguments(); | 3203 ZoneList<Expression*>* args = expr->arguments(); |
3204 ASSERT(args->length() == 1); | 3204 DCHECK(args->length() == 1); |
3205 Label done, null, function, non_function_constructor; | 3205 Label done, null, function, non_function_constructor; |
3206 | 3206 |
3207 VisitForAccumulatorValue(args->at(0)); | 3207 VisitForAccumulatorValue(args->at(0)); |
3208 | 3208 |
3209 // If the object is a smi, we return null. | 3209 // If the object is a smi, we return null. |
3210 __ JumpIfSmi(eax, &null); | 3210 __ JumpIfSmi(eax, &null); |
3211 | 3211 |
3212 // Check that the object is a JS object but take special care of JS | 3212 // Check that the object is a JS object but take special care of JS |
3213 // functions to make sure they have 'Function' as their class. | 3213 // functions to make sure they have 'Function' as their class. |
3214 // Assume that there are only two callable types, and one of them is at | 3214 // 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... |
3257 __ bind(&done); | 3257 __ bind(&done); |
3258 | 3258 |
3259 context()->Plug(eax); | 3259 context()->Plug(eax); |
3260 } | 3260 } |
3261 | 3261 |
3262 | 3262 |
3263 void FullCodeGenerator::EmitSubString(CallRuntime* expr) { | 3263 void FullCodeGenerator::EmitSubString(CallRuntime* expr) { |
3264 // Load the arguments on the stack and call the stub. | 3264 // Load the arguments on the stack and call the stub. |
3265 SubStringStub stub(isolate()); | 3265 SubStringStub stub(isolate()); |
3266 ZoneList<Expression*>* args = expr->arguments(); | 3266 ZoneList<Expression*>* args = expr->arguments(); |
3267 ASSERT(args->length() == 3); | 3267 DCHECK(args->length() == 3); |
3268 VisitForStackValue(args->at(0)); | 3268 VisitForStackValue(args->at(0)); |
3269 VisitForStackValue(args->at(1)); | 3269 VisitForStackValue(args->at(1)); |
3270 VisitForStackValue(args->at(2)); | 3270 VisitForStackValue(args->at(2)); |
3271 __ CallStub(&stub); | 3271 __ CallStub(&stub); |
3272 context()->Plug(eax); | 3272 context()->Plug(eax); |
3273 } | 3273 } |
3274 | 3274 |
3275 | 3275 |
3276 void FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) { | 3276 void FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) { |
3277 // Load the arguments on the stack and call the stub. | 3277 // Load the arguments on the stack and call the stub. |
3278 RegExpExecStub stub(isolate()); | 3278 RegExpExecStub stub(isolate()); |
3279 ZoneList<Expression*>* args = expr->arguments(); | 3279 ZoneList<Expression*>* args = expr->arguments(); |
3280 ASSERT(args->length() == 4); | 3280 DCHECK(args->length() == 4); |
3281 VisitForStackValue(args->at(0)); | 3281 VisitForStackValue(args->at(0)); |
3282 VisitForStackValue(args->at(1)); | 3282 VisitForStackValue(args->at(1)); |
3283 VisitForStackValue(args->at(2)); | 3283 VisitForStackValue(args->at(2)); |
3284 VisitForStackValue(args->at(3)); | 3284 VisitForStackValue(args->at(3)); |
3285 __ CallStub(&stub); | 3285 __ CallStub(&stub); |
3286 context()->Plug(eax); | 3286 context()->Plug(eax); |
3287 } | 3287 } |
3288 | 3288 |
3289 | 3289 |
3290 void FullCodeGenerator::EmitValueOf(CallRuntime* expr) { | 3290 void FullCodeGenerator::EmitValueOf(CallRuntime* expr) { |
3291 ZoneList<Expression*>* args = expr->arguments(); | 3291 ZoneList<Expression*>* args = expr->arguments(); |
3292 ASSERT(args->length() == 1); | 3292 DCHECK(args->length() == 1); |
3293 | 3293 |
3294 VisitForAccumulatorValue(args->at(0)); // Load the object. | 3294 VisitForAccumulatorValue(args->at(0)); // Load the object. |
3295 | 3295 |
3296 Label done; | 3296 Label done; |
3297 // If the object is a smi return the object. | 3297 // If the object is a smi return the object. |
3298 __ JumpIfSmi(eax, &done, Label::kNear); | 3298 __ JumpIfSmi(eax, &done, Label::kNear); |
3299 // If the object is not a value type, return the object. | 3299 // If the object is not a value type, return the object. |
3300 __ CmpObjectType(eax, JS_VALUE_TYPE, ebx); | 3300 __ CmpObjectType(eax, JS_VALUE_TYPE, ebx); |
3301 __ j(not_equal, &done, Label::kNear); | 3301 __ j(not_equal, &done, Label::kNear); |
3302 __ mov(eax, FieldOperand(eax, JSValue::kValueOffset)); | 3302 __ mov(eax, FieldOperand(eax, JSValue::kValueOffset)); |
3303 | 3303 |
3304 __ bind(&done); | 3304 __ bind(&done); |
3305 context()->Plug(eax); | 3305 context()->Plug(eax); |
3306 } | 3306 } |
3307 | 3307 |
3308 | 3308 |
3309 void FullCodeGenerator::EmitDateField(CallRuntime* expr) { | 3309 void FullCodeGenerator::EmitDateField(CallRuntime* expr) { |
3310 ZoneList<Expression*>* args = expr->arguments(); | 3310 ZoneList<Expression*>* args = expr->arguments(); |
3311 ASSERT(args->length() == 2); | 3311 DCHECK(args->length() == 2); |
3312 ASSERT_NE(NULL, args->at(1)->AsLiteral()); | 3312 DCHECK_NE(NULL, args->at(1)->AsLiteral()); |
3313 Smi* index = Smi::cast(*(args->at(1)->AsLiteral()->value())); | 3313 Smi* index = Smi::cast(*(args->at(1)->AsLiteral()->value())); |
3314 | 3314 |
3315 VisitForAccumulatorValue(args->at(0)); // Load the object. | 3315 VisitForAccumulatorValue(args->at(0)); // Load the object. |
3316 | 3316 |
3317 Label runtime, done, not_date_object; | 3317 Label runtime, done, not_date_object; |
3318 Register object = eax; | 3318 Register object = eax; |
3319 Register result = eax; | 3319 Register result = eax; |
3320 Register scratch = ecx; | 3320 Register scratch = ecx; |
3321 | 3321 |
3322 __ JumpIfSmi(object, ¬_date_object); | 3322 __ JumpIfSmi(object, ¬_date_object); |
(...skipping 23 matching lines...) Expand all Loading... |
3346 | 3346 |
3347 __ bind(¬_date_object); | 3347 __ bind(¬_date_object); |
3348 __ CallRuntime(Runtime::kThrowNotDateError, 0); | 3348 __ CallRuntime(Runtime::kThrowNotDateError, 0); |
3349 __ bind(&done); | 3349 __ bind(&done); |
3350 context()->Plug(result); | 3350 context()->Plug(result); |
3351 } | 3351 } |
3352 | 3352 |
3353 | 3353 |
3354 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) { | 3354 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) { |
3355 ZoneList<Expression*>* args = expr->arguments(); | 3355 ZoneList<Expression*>* args = expr->arguments(); |
3356 ASSERT_EQ(3, args->length()); | 3356 DCHECK_EQ(3, args->length()); |
3357 | 3357 |
3358 Register string = eax; | 3358 Register string = eax; |
3359 Register index = ebx; | 3359 Register index = ebx; |
3360 Register value = ecx; | 3360 Register value = ecx; |
3361 | 3361 |
3362 VisitForStackValue(args->at(1)); // index | 3362 VisitForStackValue(args->at(1)); // index |
3363 VisitForStackValue(args->at(2)); // value | 3363 VisitForStackValue(args->at(2)); // value |
3364 VisitForAccumulatorValue(args->at(0)); // string | 3364 VisitForAccumulatorValue(args->at(0)); // string |
3365 | 3365 |
3366 __ pop(value); | 3366 __ pop(value); |
(...skipping 15 matching lines...) Expand all Loading... |
3382 } | 3382 } |
3383 | 3383 |
3384 __ mov_b(FieldOperand(string, index, times_1, SeqOneByteString::kHeaderSize), | 3384 __ mov_b(FieldOperand(string, index, times_1, SeqOneByteString::kHeaderSize), |
3385 value); | 3385 value); |
3386 context()->Plug(string); | 3386 context()->Plug(string); |
3387 } | 3387 } |
3388 | 3388 |
3389 | 3389 |
3390 void FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) { | 3390 void FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) { |
3391 ZoneList<Expression*>* args = expr->arguments(); | 3391 ZoneList<Expression*>* args = expr->arguments(); |
3392 ASSERT_EQ(3, args->length()); | 3392 DCHECK_EQ(3, args->length()); |
3393 | 3393 |
3394 Register string = eax; | 3394 Register string = eax; |
3395 Register index = ebx; | 3395 Register index = ebx; |
3396 Register value = ecx; | 3396 Register value = ecx; |
3397 | 3397 |
3398 VisitForStackValue(args->at(1)); // index | 3398 VisitForStackValue(args->at(1)); // index |
3399 VisitForStackValue(args->at(2)); // value | 3399 VisitForStackValue(args->at(2)); // value |
3400 VisitForAccumulatorValue(args->at(0)); // string | 3400 VisitForAccumulatorValue(args->at(0)); // string |
3401 __ pop(value); | 3401 __ pop(value); |
3402 __ pop(index); | 3402 __ pop(index); |
(...skipping 13 matching lines...) Expand all Loading... |
3416 // No need to untag a smi for two-byte addressing. | 3416 // No need to untag a smi for two-byte addressing. |
3417 __ mov_w(FieldOperand(string, index, times_1, SeqTwoByteString::kHeaderSize), | 3417 __ mov_w(FieldOperand(string, index, times_1, SeqTwoByteString::kHeaderSize), |
3418 value); | 3418 value); |
3419 context()->Plug(string); | 3419 context()->Plug(string); |
3420 } | 3420 } |
3421 | 3421 |
3422 | 3422 |
3423 void FullCodeGenerator::EmitMathPow(CallRuntime* expr) { | 3423 void FullCodeGenerator::EmitMathPow(CallRuntime* expr) { |
3424 // Load the arguments on the stack and call the runtime function. | 3424 // Load the arguments on the stack and call the runtime function. |
3425 ZoneList<Expression*>* args = expr->arguments(); | 3425 ZoneList<Expression*>* args = expr->arguments(); |
3426 ASSERT(args->length() == 2); | 3426 DCHECK(args->length() == 2); |
3427 VisitForStackValue(args->at(0)); | 3427 VisitForStackValue(args->at(0)); |
3428 VisitForStackValue(args->at(1)); | 3428 VisitForStackValue(args->at(1)); |
3429 | 3429 |
3430 __ CallRuntime(Runtime::kMathPowSlow, 2); | 3430 __ CallRuntime(Runtime::kMathPowSlow, 2); |
3431 context()->Plug(eax); | 3431 context()->Plug(eax); |
3432 } | 3432 } |
3433 | 3433 |
3434 | 3434 |
3435 void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) { | 3435 void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) { |
3436 ZoneList<Expression*>* args = expr->arguments(); | 3436 ZoneList<Expression*>* args = expr->arguments(); |
3437 ASSERT(args->length() == 2); | 3437 DCHECK(args->length() == 2); |
3438 | 3438 |
3439 VisitForStackValue(args->at(0)); // Load the object. | 3439 VisitForStackValue(args->at(0)); // Load the object. |
3440 VisitForAccumulatorValue(args->at(1)); // Load the value. | 3440 VisitForAccumulatorValue(args->at(1)); // Load the value. |
3441 __ pop(ebx); // eax = value. ebx = object. | 3441 __ pop(ebx); // eax = value. ebx = object. |
3442 | 3442 |
3443 Label done; | 3443 Label done; |
3444 // If the object is a smi, return the value. | 3444 // If the object is a smi, return the value. |
3445 __ JumpIfSmi(ebx, &done, Label::kNear); | 3445 __ JumpIfSmi(ebx, &done, Label::kNear); |
3446 | 3446 |
3447 // If the object is not a value type, return the value. | 3447 // If the object is not a value type, return the value. |
3448 __ CmpObjectType(ebx, JS_VALUE_TYPE, ecx); | 3448 __ CmpObjectType(ebx, JS_VALUE_TYPE, ecx); |
3449 __ j(not_equal, &done, Label::kNear); | 3449 __ j(not_equal, &done, Label::kNear); |
3450 | 3450 |
3451 // Store the value. | 3451 // Store the value. |
3452 __ mov(FieldOperand(ebx, JSValue::kValueOffset), eax); | 3452 __ mov(FieldOperand(ebx, JSValue::kValueOffset), eax); |
3453 | 3453 |
3454 // Update the write barrier. Save the value as it will be | 3454 // Update the write barrier. Save the value as it will be |
3455 // overwritten by the write barrier code and is needed afterward. | 3455 // overwritten by the write barrier code and is needed afterward. |
3456 __ mov(edx, eax); | 3456 __ mov(edx, eax); |
3457 __ RecordWriteField(ebx, JSValue::kValueOffset, edx, ecx); | 3457 __ RecordWriteField(ebx, JSValue::kValueOffset, edx, ecx); |
3458 | 3458 |
3459 __ bind(&done); | 3459 __ bind(&done); |
3460 context()->Plug(eax); | 3460 context()->Plug(eax); |
3461 } | 3461 } |
3462 | 3462 |
3463 | 3463 |
3464 void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) { | 3464 void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) { |
3465 ZoneList<Expression*>* args = expr->arguments(); | 3465 ZoneList<Expression*>* args = expr->arguments(); |
3466 ASSERT_EQ(args->length(), 1); | 3466 DCHECK_EQ(args->length(), 1); |
3467 | 3467 |
3468 // Load the argument into eax and call the stub. | 3468 // Load the argument into eax and call the stub. |
3469 VisitForAccumulatorValue(args->at(0)); | 3469 VisitForAccumulatorValue(args->at(0)); |
3470 | 3470 |
3471 NumberToStringStub stub(isolate()); | 3471 NumberToStringStub stub(isolate()); |
3472 __ CallStub(&stub); | 3472 __ CallStub(&stub); |
3473 context()->Plug(eax); | 3473 context()->Plug(eax); |
3474 } | 3474 } |
3475 | 3475 |
3476 | 3476 |
3477 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) { | 3477 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) { |
3478 ZoneList<Expression*>* args = expr->arguments(); | 3478 ZoneList<Expression*>* args = expr->arguments(); |
3479 ASSERT(args->length() == 1); | 3479 DCHECK(args->length() == 1); |
3480 | 3480 |
3481 VisitForAccumulatorValue(args->at(0)); | 3481 VisitForAccumulatorValue(args->at(0)); |
3482 | 3482 |
3483 Label done; | 3483 Label done; |
3484 StringCharFromCodeGenerator generator(eax, ebx); | 3484 StringCharFromCodeGenerator generator(eax, ebx); |
3485 generator.GenerateFast(masm_); | 3485 generator.GenerateFast(masm_); |
3486 __ jmp(&done); | 3486 __ jmp(&done); |
3487 | 3487 |
3488 NopRuntimeCallHelper call_helper; | 3488 NopRuntimeCallHelper call_helper; |
3489 generator.GenerateSlow(masm_, call_helper); | 3489 generator.GenerateSlow(masm_, call_helper); |
3490 | 3490 |
3491 __ bind(&done); | 3491 __ bind(&done); |
3492 context()->Plug(ebx); | 3492 context()->Plug(ebx); |
3493 } | 3493 } |
3494 | 3494 |
3495 | 3495 |
3496 void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) { | 3496 void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) { |
3497 ZoneList<Expression*>* args = expr->arguments(); | 3497 ZoneList<Expression*>* args = expr->arguments(); |
3498 ASSERT(args->length() == 2); | 3498 DCHECK(args->length() == 2); |
3499 | 3499 |
3500 VisitForStackValue(args->at(0)); | 3500 VisitForStackValue(args->at(0)); |
3501 VisitForAccumulatorValue(args->at(1)); | 3501 VisitForAccumulatorValue(args->at(1)); |
3502 | 3502 |
3503 Register object = ebx; | 3503 Register object = ebx; |
3504 Register index = eax; | 3504 Register index = eax; |
3505 Register result = edx; | 3505 Register result = edx; |
3506 | 3506 |
3507 __ pop(object); | 3507 __ pop(object); |
3508 | 3508 |
(...skipping 25 matching lines...) Expand all Loading... |
3534 NopRuntimeCallHelper call_helper; | 3534 NopRuntimeCallHelper call_helper; |
3535 generator.GenerateSlow(masm_, call_helper); | 3535 generator.GenerateSlow(masm_, call_helper); |
3536 | 3536 |
3537 __ bind(&done); | 3537 __ bind(&done); |
3538 context()->Plug(result); | 3538 context()->Plug(result); |
3539 } | 3539 } |
3540 | 3540 |
3541 | 3541 |
3542 void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) { | 3542 void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) { |
3543 ZoneList<Expression*>* args = expr->arguments(); | 3543 ZoneList<Expression*>* args = expr->arguments(); |
3544 ASSERT(args->length() == 2); | 3544 DCHECK(args->length() == 2); |
3545 | 3545 |
3546 VisitForStackValue(args->at(0)); | 3546 VisitForStackValue(args->at(0)); |
3547 VisitForAccumulatorValue(args->at(1)); | 3547 VisitForAccumulatorValue(args->at(1)); |
3548 | 3548 |
3549 Register object = ebx; | 3549 Register object = ebx; |
3550 Register index = eax; | 3550 Register index = eax; |
3551 Register scratch = edx; | 3551 Register scratch = edx; |
3552 Register result = eax; | 3552 Register result = eax; |
3553 | 3553 |
3554 __ pop(object); | 3554 __ pop(object); |
(...skipping 27 matching lines...) Expand all Loading... |
3582 NopRuntimeCallHelper call_helper; | 3582 NopRuntimeCallHelper call_helper; |
3583 generator.GenerateSlow(masm_, call_helper); | 3583 generator.GenerateSlow(masm_, call_helper); |
3584 | 3584 |
3585 __ bind(&done); | 3585 __ bind(&done); |
3586 context()->Plug(result); | 3586 context()->Plug(result); |
3587 } | 3587 } |
3588 | 3588 |
3589 | 3589 |
3590 void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) { | 3590 void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) { |
3591 ZoneList<Expression*>* args = expr->arguments(); | 3591 ZoneList<Expression*>* args = expr->arguments(); |
3592 ASSERT_EQ(2, args->length()); | 3592 DCHECK_EQ(2, args->length()); |
3593 VisitForStackValue(args->at(0)); | 3593 VisitForStackValue(args->at(0)); |
3594 VisitForAccumulatorValue(args->at(1)); | 3594 VisitForAccumulatorValue(args->at(1)); |
3595 | 3595 |
3596 __ pop(edx); | 3596 __ pop(edx); |
3597 StringAddStub stub(isolate(), STRING_ADD_CHECK_BOTH, NOT_TENURED); | 3597 StringAddStub stub(isolate(), STRING_ADD_CHECK_BOTH, NOT_TENURED); |
3598 __ CallStub(&stub); | 3598 __ CallStub(&stub); |
3599 context()->Plug(eax); | 3599 context()->Plug(eax); |
3600 } | 3600 } |
3601 | 3601 |
3602 | 3602 |
3603 void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) { | 3603 void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) { |
3604 ZoneList<Expression*>* args = expr->arguments(); | 3604 ZoneList<Expression*>* args = expr->arguments(); |
3605 ASSERT_EQ(2, args->length()); | 3605 DCHECK_EQ(2, args->length()); |
3606 | 3606 |
3607 VisitForStackValue(args->at(0)); | 3607 VisitForStackValue(args->at(0)); |
3608 VisitForStackValue(args->at(1)); | 3608 VisitForStackValue(args->at(1)); |
3609 | 3609 |
3610 StringCompareStub stub(isolate()); | 3610 StringCompareStub stub(isolate()); |
3611 __ CallStub(&stub); | 3611 __ CallStub(&stub); |
3612 context()->Plug(eax); | 3612 context()->Plug(eax); |
3613 } | 3613 } |
3614 | 3614 |
3615 | 3615 |
3616 void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) { | 3616 void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) { |
3617 ZoneList<Expression*>* args = expr->arguments(); | 3617 ZoneList<Expression*>* args = expr->arguments(); |
3618 ASSERT(args->length() >= 2); | 3618 DCHECK(args->length() >= 2); |
3619 | 3619 |
3620 int arg_count = args->length() - 2; // 2 ~ receiver and function. | 3620 int arg_count = args->length() - 2; // 2 ~ receiver and function. |
3621 for (int i = 0; i < arg_count + 1; ++i) { | 3621 for (int i = 0; i < arg_count + 1; ++i) { |
3622 VisitForStackValue(args->at(i)); | 3622 VisitForStackValue(args->at(i)); |
3623 } | 3623 } |
3624 VisitForAccumulatorValue(args->last()); // Function. | 3624 VisitForAccumulatorValue(args->last()); // Function. |
3625 | 3625 |
3626 Label runtime, done; | 3626 Label runtime, done; |
3627 // Check for non-function argument (including proxy). | 3627 // Check for non-function argument (including proxy). |
3628 __ JumpIfSmi(eax, &runtime); | 3628 __ JumpIfSmi(eax, &runtime); |
(...skipping 13 matching lines...) Expand all Loading... |
3642 __ bind(&done); | 3642 __ bind(&done); |
3643 | 3643 |
3644 context()->Plug(eax); | 3644 context()->Plug(eax); |
3645 } | 3645 } |
3646 | 3646 |
3647 | 3647 |
3648 void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) { | 3648 void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) { |
3649 // Load the arguments on the stack and call the stub. | 3649 // Load the arguments on the stack and call the stub. |
3650 RegExpConstructResultStub stub(isolate()); | 3650 RegExpConstructResultStub stub(isolate()); |
3651 ZoneList<Expression*>* args = expr->arguments(); | 3651 ZoneList<Expression*>* args = expr->arguments(); |
3652 ASSERT(args->length() == 3); | 3652 DCHECK(args->length() == 3); |
3653 VisitForStackValue(args->at(0)); | 3653 VisitForStackValue(args->at(0)); |
3654 VisitForStackValue(args->at(1)); | 3654 VisitForStackValue(args->at(1)); |
3655 VisitForAccumulatorValue(args->at(2)); | 3655 VisitForAccumulatorValue(args->at(2)); |
3656 __ pop(ebx); | 3656 __ pop(ebx); |
3657 __ pop(ecx); | 3657 __ pop(ecx); |
3658 __ CallStub(&stub); | 3658 __ CallStub(&stub); |
3659 context()->Plug(eax); | 3659 context()->Plug(eax); |
3660 } | 3660 } |
3661 | 3661 |
3662 | 3662 |
3663 void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) { | 3663 void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) { |
3664 ZoneList<Expression*>* args = expr->arguments(); | 3664 ZoneList<Expression*>* args = expr->arguments(); |
3665 ASSERT_EQ(2, args->length()); | 3665 DCHECK_EQ(2, args->length()); |
3666 | 3666 |
3667 ASSERT_NE(NULL, args->at(0)->AsLiteral()); | 3667 DCHECK_NE(NULL, args->at(0)->AsLiteral()); |
3668 int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->value()))->value(); | 3668 int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->value()))->value(); |
3669 | 3669 |
3670 Handle<FixedArray> jsfunction_result_caches( | 3670 Handle<FixedArray> jsfunction_result_caches( |
3671 isolate()->native_context()->jsfunction_result_caches()); | 3671 isolate()->native_context()->jsfunction_result_caches()); |
3672 if (jsfunction_result_caches->length() <= cache_id) { | 3672 if (jsfunction_result_caches->length() <= cache_id) { |
3673 __ Abort(kAttemptToUseUndefinedCache); | 3673 __ Abort(kAttemptToUseUndefinedCache); |
3674 __ mov(eax, isolate()->factory()->undefined_value()); | 3674 __ mov(eax, isolate()->factory()->undefined_value()); |
3675 context()->Plug(eax); | 3675 context()->Plug(eax); |
3676 return; | 3676 return; |
3677 } | 3677 } |
(...skipping 26 matching lines...) Expand all Loading... |
3704 __ push(key); | 3704 __ push(key); |
3705 __ CallRuntime(Runtime::kGetFromCache, 2); | 3705 __ CallRuntime(Runtime::kGetFromCache, 2); |
3706 | 3706 |
3707 __ bind(&done); | 3707 __ bind(&done); |
3708 context()->Plug(eax); | 3708 context()->Plug(eax); |
3709 } | 3709 } |
3710 | 3710 |
3711 | 3711 |
3712 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) { | 3712 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) { |
3713 ZoneList<Expression*>* args = expr->arguments(); | 3713 ZoneList<Expression*>* args = expr->arguments(); |
3714 ASSERT(args->length() == 1); | 3714 DCHECK(args->length() == 1); |
3715 | 3715 |
3716 VisitForAccumulatorValue(args->at(0)); | 3716 VisitForAccumulatorValue(args->at(0)); |
3717 | 3717 |
3718 __ AssertString(eax); | 3718 __ AssertString(eax); |
3719 | 3719 |
3720 Label materialize_true, materialize_false; | 3720 Label materialize_true, materialize_false; |
3721 Label* if_true = NULL; | 3721 Label* if_true = NULL; |
3722 Label* if_false = NULL; | 3722 Label* if_false = NULL; |
3723 Label* fall_through = NULL; | 3723 Label* fall_through = NULL; |
3724 context()->PrepareTest(&materialize_true, &materialize_false, | 3724 context()->PrepareTest(&materialize_true, &materialize_false, |
3725 &if_true, &if_false, &fall_through); | 3725 &if_true, &if_false, &fall_through); |
3726 | 3726 |
3727 __ test(FieldOperand(eax, String::kHashFieldOffset), | 3727 __ test(FieldOperand(eax, String::kHashFieldOffset), |
3728 Immediate(String::kContainsCachedArrayIndexMask)); | 3728 Immediate(String::kContainsCachedArrayIndexMask)); |
3729 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 3729 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
3730 Split(zero, if_true, if_false, fall_through); | 3730 Split(zero, if_true, if_false, fall_through); |
3731 | 3731 |
3732 context()->Plug(if_true, if_false); | 3732 context()->Plug(if_true, if_false); |
3733 } | 3733 } |
3734 | 3734 |
3735 | 3735 |
3736 void FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) { | 3736 void FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) { |
3737 ZoneList<Expression*>* args = expr->arguments(); | 3737 ZoneList<Expression*>* args = expr->arguments(); |
3738 ASSERT(args->length() == 1); | 3738 DCHECK(args->length() == 1); |
3739 VisitForAccumulatorValue(args->at(0)); | 3739 VisitForAccumulatorValue(args->at(0)); |
3740 | 3740 |
3741 __ AssertString(eax); | 3741 __ AssertString(eax); |
3742 | 3742 |
3743 __ mov(eax, FieldOperand(eax, String::kHashFieldOffset)); | 3743 __ mov(eax, FieldOperand(eax, String::kHashFieldOffset)); |
3744 __ IndexFromHash(eax, eax); | 3744 __ IndexFromHash(eax, eax); |
3745 | 3745 |
3746 context()->Plug(eax); | 3746 context()->Plug(eax); |
3747 } | 3747 } |
3748 | 3748 |
3749 | 3749 |
3750 void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) { | 3750 void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) { |
3751 Label bailout, done, one_char_separator, long_separator, | 3751 Label bailout, done, one_char_separator, long_separator, |
3752 non_trivial_array, not_size_one_array, loop, | 3752 non_trivial_array, not_size_one_array, loop, |
3753 loop_1, loop_1_condition, loop_2, loop_2_entry, loop_3, loop_3_entry; | 3753 loop_1, loop_1_condition, loop_2, loop_2_entry, loop_3, loop_3_entry; |
3754 | 3754 |
3755 ZoneList<Expression*>* args = expr->arguments(); | 3755 ZoneList<Expression*>* args = expr->arguments(); |
3756 ASSERT(args->length() == 2); | 3756 DCHECK(args->length() == 2); |
3757 // We will leave the separator on the stack until the end of the function. | 3757 // We will leave the separator on the stack until the end of the function. |
3758 VisitForStackValue(args->at(1)); | 3758 VisitForStackValue(args->at(1)); |
3759 // Load this to eax (= array) | 3759 // Load this to eax (= array) |
3760 VisitForAccumulatorValue(args->at(0)); | 3760 VisitForAccumulatorValue(args->at(0)); |
3761 // All aliases of the same register have disjoint lifetimes. | 3761 // All aliases of the same register have disjoint lifetimes. |
3762 Register array = eax; | 3762 Register array = eax; |
3763 Register elements = no_reg; // Will be eax. | 3763 Register elements = no_reg; // Will be eax. |
3764 | 3764 |
3765 Register index = edx; | 3765 Register index = edx; |
3766 | 3766 |
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4005 __ mov(eax, result_operand); | 4005 __ mov(eax, result_operand); |
4006 // Drop temp values from the stack, and restore context register. | 4006 // Drop temp values from the stack, and restore context register. |
4007 __ add(esp, Immediate(3 * kPointerSize)); | 4007 __ add(esp, Immediate(3 * kPointerSize)); |
4008 | 4008 |
4009 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 4009 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
4010 context()->Plug(eax); | 4010 context()->Plug(eax); |
4011 } | 4011 } |
4012 | 4012 |
4013 | 4013 |
4014 void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) { | 4014 void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) { |
4015 ASSERT(expr->arguments()->length() == 0); | 4015 DCHECK(expr->arguments()->length() == 0); |
4016 ExternalReference debug_is_active = | 4016 ExternalReference debug_is_active = |
4017 ExternalReference::debug_is_active_address(isolate()); | 4017 ExternalReference::debug_is_active_address(isolate()); |
4018 __ movzx_b(eax, Operand::StaticVariable(debug_is_active)); | 4018 __ movzx_b(eax, Operand::StaticVariable(debug_is_active)); |
4019 __ SmiTag(eax); | 4019 __ SmiTag(eax); |
4020 context()->Plug(eax); | 4020 context()->Plug(eax); |
4021 } | 4021 } |
4022 | 4022 |
4023 | 4023 |
4024 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { | 4024 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { |
4025 if (expr->function() != NULL && | 4025 if (expr->function() != NULL && |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4093 if (property != NULL) { | 4093 if (property != NULL) { |
4094 VisitForStackValue(property->obj()); | 4094 VisitForStackValue(property->obj()); |
4095 VisitForStackValue(property->key()); | 4095 VisitForStackValue(property->key()); |
4096 __ push(Immediate(Smi::FromInt(strict_mode()))); | 4096 __ push(Immediate(Smi::FromInt(strict_mode()))); |
4097 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); | 4097 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); |
4098 context()->Plug(eax); | 4098 context()->Plug(eax); |
4099 } else if (proxy != NULL) { | 4099 } else if (proxy != NULL) { |
4100 Variable* var = proxy->var(); | 4100 Variable* var = proxy->var(); |
4101 // Delete of an unqualified identifier is disallowed in strict mode | 4101 // Delete of an unqualified identifier is disallowed in strict mode |
4102 // but "delete this" is allowed. | 4102 // but "delete this" is allowed. |
4103 ASSERT(strict_mode() == SLOPPY || var->is_this()); | 4103 DCHECK(strict_mode() == SLOPPY || var->is_this()); |
4104 if (var->IsUnallocated()) { | 4104 if (var->IsUnallocated()) { |
4105 __ push(GlobalObjectOperand()); | 4105 __ push(GlobalObjectOperand()); |
4106 __ push(Immediate(var->name())); | 4106 __ push(Immediate(var->name())); |
4107 __ push(Immediate(Smi::FromInt(SLOPPY))); | 4107 __ push(Immediate(Smi::FromInt(SLOPPY))); |
4108 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); | 4108 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); |
4109 context()->Plug(eax); | 4109 context()->Plug(eax); |
4110 } else if (var->IsStackAllocated() || var->IsContextSlot()) { | 4110 } else if (var->IsStackAllocated() || var->IsContextSlot()) { |
4111 // Result of deleting non-global variables is false. 'this' is | 4111 // Result of deleting non-global variables is false. 'this' is |
4112 // not really a variable, though we implement it as one. The | 4112 // not really a variable, though we implement it as one. The |
4113 // subexpression does not have side effects. | 4113 // subexpression does not have side effects. |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4148 VisitForControl(expr->expression(), | 4148 VisitForControl(expr->expression(), |
4149 test->false_label(), | 4149 test->false_label(), |
4150 test->true_label(), | 4150 test->true_label(), |
4151 test->fall_through()); | 4151 test->fall_through()); |
4152 context()->Plug(test->true_label(), test->false_label()); | 4152 context()->Plug(test->true_label(), test->false_label()); |
4153 } else { | 4153 } else { |
4154 // We handle value contexts explicitly rather than simply visiting | 4154 // We handle value contexts explicitly rather than simply visiting |
4155 // for control and plugging the control flow into the context, | 4155 // for control and plugging the control flow into the context, |
4156 // because we need to prepare a pair of extra administrative AST ids | 4156 // because we need to prepare a pair of extra administrative AST ids |
4157 // for the optimizing compiler. | 4157 // for the optimizing compiler. |
4158 ASSERT(context()->IsAccumulatorValue() || context()->IsStackValue()); | 4158 DCHECK(context()->IsAccumulatorValue() || context()->IsStackValue()); |
4159 Label materialize_true, materialize_false, done; | 4159 Label materialize_true, materialize_false, done; |
4160 VisitForControl(expr->expression(), | 4160 VisitForControl(expr->expression(), |
4161 &materialize_false, | 4161 &materialize_false, |
4162 &materialize_true, | 4162 &materialize_true, |
4163 &materialize_true); | 4163 &materialize_true); |
4164 __ bind(&materialize_true); | 4164 __ bind(&materialize_true); |
4165 PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS); | 4165 PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS); |
4166 if (context()->IsAccumulatorValue()) { | 4166 if (context()->IsAccumulatorValue()) { |
4167 __ mov(eax, isolate()->factory()->true_value()); | 4167 __ mov(eax, isolate()->factory()->true_value()); |
4168 } else { | 4168 } else { |
(...skipping 22 matching lines...) Expand all Loading... |
4191 break; | 4191 break; |
4192 } | 4192 } |
4193 | 4193 |
4194 default: | 4194 default: |
4195 UNREACHABLE(); | 4195 UNREACHABLE(); |
4196 } | 4196 } |
4197 } | 4197 } |
4198 | 4198 |
4199 | 4199 |
4200 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { | 4200 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { |
4201 ASSERT(expr->expression()->IsValidReferenceExpression()); | 4201 DCHECK(expr->expression()->IsValidReferenceExpression()); |
4202 | 4202 |
4203 Comment cmnt(masm_, "[ CountOperation"); | 4203 Comment cmnt(masm_, "[ CountOperation"); |
4204 SetSourcePosition(expr->position()); | 4204 SetSourcePosition(expr->position()); |
4205 | 4205 |
4206 // Expression can only be a property, a global or a (parameter or local) | 4206 // Expression can only be a property, a global or a (parameter or local) |
4207 // slot. | 4207 // slot. |
4208 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 4208 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
4209 LhsKind assign_type = VARIABLE; | 4209 LhsKind assign_type = VARIABLE; |
4210 Property* prop = expr->expression()->AsProperty(); | 4210 Property* prop = expr->expression()->AsProperty(); |
4211 // In case of a property we use the uninitialized expression context | 4211 // In case of a property we use the uninitialized expression context |
4212 // of the key to detect a named property. | 4212 // of the key to detect a named property. |
4213 if (prop != NULL) { | 4213 if (prop != NULL) { |
4214 assign_type = | 4214 assign_type = |
4215 (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; | 4215 (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; |
4216 } | 4216 } |
4217 | 4217 |
4218 // Evaluate expression and get value. | 4218 // Evaluate expression and get value. |
4219 if (assign_type == VARIABLE) { | 4219 if (assign_type == VARIABLE) { |
4220 ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); | 4220 DCHECK(expr->expression()->AsVariableProxy()->var() != NULL); |
4221 AccumulatorValueContext context(this); | 4221 AccumulatorValueContext context(this); |
4222 EmitVariableLoad(expr->expression()->AsVariableProxy()); | 4222 EmitVariableLoad(expr->expression()->AsVariableProxy()); |
4223 } else { | 4223 } else { |
4224 // Reserve space for result of postfix operation. | 4224 // Reserve space for result of postfix operation. |
4225 if (expr->is_postfix() && !context()->IsEffect()) { | 4225 if (expr->is_postfix() && !context()->IsEffect()) { |
4226 __ push(Immediate(Smi::FromInt(0))); | 4226 __ push(Immediate(Smi::FromInt(0))); |
4227 } | 4227 } |
4228 if (assign_type == NAMED_PROPERTY) { | 4228 if (assign_type == NAMED_PROPERTY) { |
4229 // Put the object both on the stack and in the register. | 4229 // Put the object both on the stack and in the register. |
4230 VisitForStackValue(prop->obj()); | 4230 VisitForStackValue(prop->obj()); |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4380 context()->Plug(eax); | 4380 context()->Plug(eax); |
4381 } | 4381 } |
4382 break; | 4382 break; |
4383 } | 4383 } |
4384 } | 4384 } |
4385 } | 4385 } |
4386 | 4386 |
4387 | 4387 |
4388 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { | 4388 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { |
4389 VariableProxy* proxy = expr->AsVariableProxy(); | 4389 VariableProxy* proxy = expr->AsVariableProxy(); |
4390 ASSERT(!context()->IsEffect()); | 4390 DCHECK(!context()->IsEffect()); |
4391 ASSERT(!context()->IsTest()); | 4391 DCHECK(!context()->IsTest()); |
4392 | 4392 |
4393 if (proxy != NULL && proxy->var()->IsUnallocated()) { | 4393 if (proxy != NULL && proxy->var()->IsUnallocated()) { |
4394 Comment cmnt(masm_, "[ Global variable"); | 4394 Comment cmnt(masm_, "[ Global variable"); |
4395 __ mov(LoadIC::ReceiverRegister(), GlobalObjectOperand()); | 4395 __ mov(LoadIC::ReceiverRegister(), GlobalObjectOperand()); |
4396 __ mov(LoadIC::NameRegister(), Immediate(proxy->name())); | 4396 __ mov(LoadIC::NameRegister(), Immediate(proxy->name())); |
4397 if (FLAG_vector_ics) { | 4397 if (FLAG_vector_ics) { |
4398 __ mov(LoadIC::SlotRegister(), | 4398 __ mov(LoadIC::SlotRegister(), |
4399 Immediate(Smi::FromInt(proxy->VariableFeedbackSlot()))); | 4399 Immediate(Smi::FromInt(proxy->VariableFeedbackSlot()))); |
4400 } | 4400 } |
4401 // Use a regular load, not a contextual load, to avoid a reference | 4401 // Use a regular load, not a contextual load, to avoid a reference |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4612 return eax; | 4612 return eax; |
4613 } | 4613 } |
4614 | 4614 |
4615 | 4615 |
4616 Register FullCodeGenerator::context_register() { | 4616 Register FullCodeGenerator::context_register() { |
4617 return esi; | 4617 return esi; |
4618 } | 4618 } |
4619 | 4619 |
4620 | 4620 |
4621 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { | 4621 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { |
4622 ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset); | 4622 DCHECK_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset); |
4623 __ mov(Operand(ebp, frame_offset), value); | 4623 __ mov(Operand(ebp, frame_offset), value); |
4624 } | 4624 } |
4625 | 4625 |
4626 | 4626 |
4627 void FullCodeGenerator::LoadContextField(Register dst, int context_index) { | 4627 void FullCodeGenerator::LoadContextField(Register dst, int context_index) { |
4628 __ mov(dst, ContextOperand(esi, context_index)); | 4628 __ mov(dst, ContextOperand(esi, context_index)); |
4629 } | 4629 } |
4630 | 4630 |
4631 | 4631 |
4632 void FullCodeGenerator::PushFunctionArgumentForContextAllocation() { | 4632 void FullCodeGenerator::PushFunctionArgumentForContextAllocation() { |
4633 Scope* declaration_scope = scope()->DeclarationScope(); | 4633 Scope* declaration_scope = scope()->DeclarationScope(); |
4634 if (declaration_scope->is_global_scope() || | 4634 if (declaration_scope->is_global_scope() || |
4635 declaration_scope->is_module_scope()) { | 4635 declaration_scope->is_module_scope()) { |
4636 // Contexts nested in the native context have a canonical empty function | 4636 // Contexts nested in the native context have a canonical empty function |
4637 // as their closure, not the anonymous closure containing the global | 4637 // as their closure, not the anonymous closure containing the global |
4638 // code. Pass a smi sentinel and let the runtime look up the empty | 4638 // code. Pass a smi sentinel and let the runtime look up the empty |
4639 // function. | 4639 // function. |
4640 __ push(Immediate(Smi::FromInt(0))); | 4640 __ push(Immediate(Smi::FromInt(0))); |
4641 } else if (declaration_scope->is_eval_scope()) { | 4641 } else if (declaration_scope->is_eval_scope()) { |
4642 // Contexts nested inside eval code have the same closure as the context | 4642 // Contexts nested inside eval code have the same closure as the context |
4643 // calling eval, not the anonymous closure containing the eval code. | 4643 // calling eval, not the anonymous closure containing the eval code. |
4644 // Fetch it from the context. | 4644 // Fetch it from the context. |
4645 __ push(ContextOperand(esi, Context::CLOSURE_INDEX)); | 4645 __ push(ContextOperand(esi, Context::CLOSURE_INDEX)); |
4646 } else { | 4646 } else { |
4647 ASSERT(declaration_scope->is_function_scope()); | 4647 DCHECK(declaration_scope->is_function_scope()); |
4648 __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 4648 __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
4649 } | 4649 } |
4650 } | 4650 } |
4651 | 4651 |
4652 | 4652 |
4653 // ---------------------------------------------------------------------------- | 4653 // ---------------------------------------------------------------------------- |
4654 // Non-local control flow support. | 4654 // Non-local control flow support. |
4655 | 4655 |
4656 void FullCodeGenerator::EnterFinallyBlock() { | 4656 void FullCodeGenerator::EnterFinallyBlock() { |
4657 // Cook return address on top of stack (smi encoded Code* delta) | 4657 // Cook return address on top of stack (smi encoded Code* delta) |
4658 ASSERT(!result_register().is(edx)); | 4658 DCHECK(!result_register().is(edx)); |
4659 __ pop(edx); | 4659 __ pop(edx); |
4660 __ sub(edx, Immediate(masm_->CodeObject())); | 4660 __ sub(edx, Immediate(masm_->CodeObject())); |
4661 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); | 4661 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); |
4662 STATIC_ASSERT(kSmiTag == 0); | 4662 STATIC_ASSERT(kSmiTag == 0); |
4663 __ SmiTag(edx); | 4663 __ SmiTag(edx); |
4664 __ push(edx); | 4664 __ push(edx); |
4665 | 4665 |
4666 // Store result register while executing finally block. | 4666 // Store result register while executing finally block. |
4667 __ push(result_register()); | 4667 __ push(result_register()); |
4668 | 4668 |
(...skipping 10 matching lines...) Expand all Loading... |
4679 __ push(edx); | 4679 __ push(edx); |
4680 | 4680 |
4681 ExternalReference pending_message_script = | 4681 ExternalReference pending_message_script = |
4682 ExternalReference::address_of_pending_message_script(isolate()); | 4682 ExternalReference::address_of_pending_message_script(isolate()); |
4683 __ mov(edx, Operand::StaticVariable(pending_message_script)); | 4683 __ mov(edx, Operand::StaticVariable(pending_message_script)); |
4684 __ push(edx); | 4684 __ push(edx); |
4685 } | 4685 } |
4686 | 4686 |
4687 | 4687 |
4688 void FullCodeGenerator::ExitFinallyBlock() { | 4688 void FullCodeGenerator::ExitFinallyBlock() { |
4689 ASSERT(!result_register().is(edx)); | 4689 DCHECK(!result_register().is(edx)); |
4690 // Restore pending message from stack. | 4690 // Restore pending message from stack. |
4691 __ pop(edx); | 4691 __ pop(edx); |
4692 ExternalReference pending_message_script = | 4692 ExternalReference pending_message_script = |
4693 ExternalReference::address_of_pending_message_script(isolate()); | 4693 ExternalReference::address_of_pending_message_script(isolate()); |
4694 __ mov(Operand::StaticVariable(pending_message_script), edx); | 4694 __ mov(Operand::StaticVariable(pending_message_script), edx); |
4695 | 4695 |
4696 __ pop(edx); | 4696 __ pop(edx); |
4697 __ SmiUntag(edx); | 4697 __ SmiUntag(edx); |
4698 ExternalReference has_pending_message = | 4698 ExternalReference has_pending_message = |
4699 ExternalReference::address_of_has_pending_message(isolate()); | 4699 ExternalReference::address_of_has_pending_message(isolate()); |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4790 unoptimized_code, call_target_address, replacement_code); | 4790 unoptimized_code, call_target_address, replacement_code); |
4791 } | 4791 } |
4792 | 4792 |
4793 | 4793 |
4794 BackEdgeTable::BackEdgeState BackEdgeTable::GetBackEdgeState( | 4794 BackEdgeTable::BackEdgeState BackEdgeTable::GetBackEdgeState( |
4795 Isolate* isolate, | 4795 Isolate* isolate, |
4796 Code* unoptimized_code, | 4796 Code* unoptimized_code, |
4797 Address pc) { | 4797 Address pc) { |
4798 Address call_target_address = pc - kIntSize; | 4798 Address call_target_address = pc - kIntSize; |
4799 Address jns_instr_address = call_target_address - 3; | 4799 Address jns_instr_address = call_target_address - 3; |
4800 ASSERT_EQ(kCallInstruction, *(call_target_address - 1)); | 4800 DCHECK_EQ(kCallInstruction, *(call_target_address - 1)); |
4801 | 4801 |
4802 if (*jns_instr_address == kJnsInstruction) { | 4802 if (*jns_instr_address == kJnsInstruction) { |
4803 ASSERT_EQ(kJnsOffset, *(call_target_address - 2)); | 4803 DCHECK_EQ(kJnsOffset, *(call_target_address - 2)); |
4804 ASSERT_EQ(isolate->builtins()->InterruptCheck()->entry(), | 4804 DCHECK_EQ(isolate->builtins()->InterruptCheck()->entry(), |
4805 Assembler::target_address_at(call_target_address, | 4805 Assembler::target_address_at(call_target_address, |
4806 unoptimized_code)); | 4806 unoptimized_code)); |
4807 return INTERRUPT; | 4807 return INTERRUPT; |
4808 } | 4808 } |
4809 | 4809 |
4810 ASSERT_EQ(kNopByteOne, *jns_instr_address); | 4810 DCHECK_EQ(kNopByteOne, *jns_instr_address); |
4811 ASSERT_EQ(kNopByteTwo, *(call_target_address - 2)); | 4811 DCHECK_EQ(kNopByteTwo, *(call_target_address - 2)); |
4812 | 4812 |
4813 if (Assembler::target_address_at(call_target_address, unoptimized_code) == | 4813 if (Assembler::target_address_at(call_target_address, unoptimized_code) == |
4814 isolate->builtins()->OnStackReplacement()->entry()) { | 4814 isolate->builtins()->OnStackReplacement()->entry()) { |
4815 return ON_STACK_REPLACEMENT; | 4815 return ON_STACK_REPLACEMENT; |
4816 } | 4816 } |
4817 | 4817 |
4818 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), | 4818 DCHECK_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), |
4819 Assembler::target_address_at(call_target_address, | 4819 Assembler::target_address_at(call_target_address, |
4820 unoptimized_code)); | 4820 unoptimized_code)); |
4821 return OSR_AFTER_STACK_CHECK; | 4821 return OSR_AFTER_STACK_CHECK; |
4822 } | 4822 } |
4823 | 4823 |
4824 | 4824 |
4825 } } // namespace v8::internal | 4825 } } // namespace v8::internal |
4826 | 4826 |
4827 #endif // V8_TARGET_ARCH_X87 | 4827 #endif // V8_TARGET_ARCH_X87 |
OLD | NEW |