Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(264)

Side by Side Diff: src/ia32/full-codegen-ia32.cc

Issue 7060010: Merge bleeding edge into the GC branch up to 7948. The asserts (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: Created 9 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ia32/frames-ia32.h ('k') | src/ia32/ic-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
56 explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm) { 56 explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm) {
57 #ifdef DEBUG 57 #ifdef DEBUG
58 info_emitted_ = false; 58 info_emitted_ = false;
59 #endif 59 #endif
60 } 60 }
61 61
62 ~JumpPatchSite() { 62 ~JumpPatchSite() {
63 ASSERT(patch_site_.is_bound() == info_emitted_); 63 ASSERT(patch_site_.is_bound() == info_emitted_);
64 } 64 }
65 65
66 void EmitJumpIfNotSmi(Register reg, NearLabel* target) { 66 void EmitJumpIfNotSmi(Register reg,
67 Label* target,
68 Label::Distance distance = Label::kFar) {
67 __ test(reg, Immediate(kSmiTagMask)); 69 __ test(reg, Immediate(kSmiTagMask));
68 EmitJump(not_carry, target); // Always taken before patched. 70 EmitJump(not_carry, target, distance); // Always taken before patched.
69 } 71 }
70 72
71 void EmitJumpIfSmi(Register reg, NearLabel* target) { 73 void EmitJumpIfSmi(Register reg,
74 Label* target,
75 Label::Distance distance = Label::kFar) {
72 __ test(reg, Immediate(kSmiTagMask)); 76 __ test(reg, Immediate(kSmiTagMask));
73 EmitJump(carry, target); // Never taken before patched. 77 EmitJump(carry, target, distance); // Never taken before patched.
74 } 78 }
75 79
76 void EmitPatchInfo() { 80 void EmitPatchInfo() {
77 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(&patch_site_); 81 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(&patch_site_);
78 ASSERT(is_int8(delta_to_patch_site)); 82 ASSERT(is_int8(delta_to_patch_site));
79 __ test(eax, Immediate(delta_to_patch_site)); 83 __ test(eax, Immediate(delta_to_patch_site));
80 #ifdef DEBUG 84 #ifdef DEBUG
81 info_emitted_ = true; 85 info_emitted_ = true;
82 #endif 86 #endif
83 } 87 }
84 88
85 bool is_bound() const { return patch_site_.is_bound(); } 89 bool is_bound() const { return patch_site_.is_bound(); }
86 90
87 private: 91 private:
88 // jc will be patched with jz, jnc will become jnz. 92 // jc will be patched with jz, jnc will become jnz.
89 void EmitJump(Condition cc, NearLabel* target) { 93 void EmitJump(Condition cc, Label* target, Label::Distance distance) {
90 ASSERT(!patch_site_.is_bound() && !info_emitted_); 94 ASSERT(!patch_site_.is_bound() && !info_emitted_);
91 ASSERT(cc == carry || cc == not_carry); 95 ASSERT(cc == carry || cc == not_carry);
92 __ bind(&patch_site_); 96 __ bind(&patch_site_);
93 __ j(cc, target); 97 __ j(cc, target, distance);
94 } 98 }
95 99
96 MacroAssembler* masm_; 100 MacroAssembler* masm_;
97 Label patch_site_; 101 Label patch_site_;
98 #ifdef DEBUG 102 #ifdef DEBUG
99 bool info_emitted_; 103 bool info_emitted_;
100 #endif 104 #endif
101 }; 105 };
102 106
103 107
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
192 if (function_in_register) { 196 if (function_in_register) {
193 __ push(edi); 197 __ push(edi);
194 } else { 198 } else {
195 __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 199 __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
196 } 200 }
197 // Receiver is just before the parameters on the caller's stack. 201 // Receiver is just before the parameters on the caller's stack.
198 int offset = scope()->num_parameters() * kPointerSize; 202 int offset = scope()->num_parameters() * kPointerSize;
199 __ lea(edx, 203 __ lea(edx,
200 Operand(ebp, StandardFrameConstants::kCallerSPOffset + offset)); 204 Operand(ebp, StandardFrameConstants::kCallerSPOffset + offset));
201 __ push(edx); 205 __ push(edx);
202 __ push(Immediate(Smi::FromInt(scope()->num_parameters()))); 206 __ SafePush(Immediate(Smi::FromInt(scope()->num_parameters())));
203 // Arguments to ArgumentsAccessStub: 207 // Arguments to ArgumentsAccessStub:
204 // function, receiver address, parameter count. 208 // function, receiver address, parameter count.
205 // The stub will rewrite receiver and parameter count if the previous 209 // The stub will rewrite receiver and parameter count if the previous
206 // stack frame was an arguments adapter frame. 210 // stack frame was an arguments adapter frame.
207 ArgumentsAccessStub stub( 211 ArgumentsAccessStub stub(
208 is_strict_mode() ? ArgumentsAccessStub::NEW_STRICT 212 is_strict_mode() ? ArgumentsAccessStub::NEW_STRICT
209 : ArgumentsAccessStub::NEW_NON_STRICT); 213 : ArgumentsAccessStub::NEW_NON_STRICT);
210 __ CallStub(&stub); 214 __ CallStub(&stub);
211 215
212 Variable* arguments_shadow = scope()->arguments_shadow(); 216 Variable* arguments_shadow = scope()->arguments_shadow();
(...skipping 19 matching lines...) Expand all
232 // For named function expressions, declare the function name as a 236 // For named function expressions, declare the function name as a
233 // constant. 237 // constant.
234 if (scope()->is_function_scope() && scope()->function() != NULL) { 238 if (scope()->is_function_scope() && scope()->function() != NULL) {
235 EmitDeclaration(scope()->function(), Variable::CONST, NULL); 239 EmitDeclaration(scope()->function(), Variable::CONST, NULL);
236 } 240 }
237 VisitDeclarations(scope()->declarations()); 241 VisitDeclarations(scope()->declarations());
238 } 242 }
239 243
240 { Comment cmnt(masm_, "[ Stack check"); 244 { Comment cmnt(masm_, "[ Stack check");
241 PrepareForBailoutForId(AstNode::kFunctionEntryId, NO_REGISTERS); 245 PrepareForBailoutForId(AstNode::kFunctionEntryId, NO_REGISTERS);
242 NearLabel ok; 246 Label ok;
243 ExternalReference stack_limit = 247 ExternalReference stack_limit =
244 ExternalReference::address_of_stack_limit(isolate()); 248 ExternalReference::address_of_stack_limit(isolate());
245 __ cmp(esp, Operand::StaticVariable(stack_limit)); 249 __ cmp(esp, Operand::StaticVariable(stack_limit));
246 __ j(above_equal, &ok, taken); 250 __ j(above_equal, &ok, Label::kNear);
247 StackCheckStub stub; 251 StackCheckStub stub;
248 __ CallStub(&stub); 252 __ CallStub(&stub);
249 __ bind(&ok); 253 __ bind(&ok);
250 } 254 }
251 255
252 { Comment cmnt(masm_, "[ Body"); 256 { Comment cmnt(masm_, "[ Body");
253 ASSERT(loop_depth() == 0); 257 ASSERT(loop_depth() == 0);
254 VisitStatements(function()->body()); 258 VisitStatements(function()->body());
255 ASSERT(loop_depth() == 0); 259 ASSERT(loop_depth() == 0);
256 } 260 }
257 } 261 }
258 262
259 // Always emit a 'return undefined' in case control fell off the end of 263 // Always emit a 'return undefined' in case control fell off the end of
260 // the body. 264 // the body.
261 { Comment cmnt(masm_, "[ return <undefined>;"); 265 { Comment cmnt(masm_, "[ return <undefined>;");
262 __ mov(eax, isolate()->factory()->undefined_value()); 266 __ mov(eax, isolate()->factory()->undefined_value());
263 EmitReturnSequence(); 267 EmitReturnSequence();
264 } 268 }
265 } 269 }
266 270
267 271
268 void FullCodeGenerator::ClearAccumulator() { 272 void FullCodeGenerator::ClearAccumulator() {
269 __ Set(eax, Immediate(Smi::FromInt(0))); 273 __ Set(eax, Immediate(Smi::FromInt(0)));
270 } 274 }
271 275
272 276
273 void FullCodeGenerator::EmitStackCheck(IterationStatement* stmt) { 277 void FullCodeGenerator::EmitStackCheck(IterationStatement* stmt) {
274 Comment cmnt(masm_, "[ Stack check"); 278 Comment cmnt(masm_, "[ Stack check");
275 NearLabel ok; 279 Label ok;
276 ExternalReference stack_limit = 280 ExternalReference stack_limit =
277 ExternalReference::address_of_stack_limit(isolate()); 281 ExternalReference::address_of_stack_limit(isolate());
278 __ cmp(esp, Operand::StaticVariable(stack_limit)); 282 __ cmp(esp, Operand::StaticVariable(stack_limit));
279 __ j(above_equal, &ok, taken); 283 __ j(above_equal, &ok, Label::kNear);
280 StackCheckStub stub; 284 StackCheckStub stub;
281 __ CallStub(&stub); 285 __ CallStub(&stub);
282 // Record a mapping of this PC offset to the OSR id. This is used to find 286 // Record a mapping of this PC offset to the OSR id. This is used to find
283 // the AST id from the unoptimized code in order to use it as a key into 287 // the AST id from the unoptimized code in order to use it as a key into
284 // the deoptimization input data found in the optimized code. 288 // the deoptimization input data found in the optimized code.
285 RecordStackCheck(stmt->OsrEntryId()); 289 RecordStackCheck(stmt->OsrEntryId());
286 290
287 // Loop stack checks can be patched to perform on-stack replacement. In 291 // Loop stack checks can be patched to perform on-stack replacement. In
288 // order to decide whether or not to perform OSR we embed the loop depth 292 // order to decide whether or not to perform OSR we embed the loop depth
289 // in a test instruction after the call so we can extract it from the OSR 293 // in a test instruction after the call so we can extract it from the OSR
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
381 UNREACHABLE(); // Not used on IA32. 385 UNREACHABLE(); // Not used on IA32.
382 } 386 }
383 387
384 388
385 void FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const { 389 void FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const {
386 } 390 }
387 391
388 392
389 void FullCodeGenerator::AccumulatorValueContext::Plug( 393 void FullCodeGenerator::AccumulatorValueContext::Plug(
390 Handle<Object> lit) const { 394 Handle<Object> lit) const {
391 __ Set(result_register(), Immediate(lit)); 395 if (lit->IsSmi()) {
396 __ SafeSet(result_register(), Immediate(lit));
397 } else {
398 __ Set(result_register(), Immediate(lit));
399 }
392 } 400 }
393 401
394 402
395 void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const { 403 void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const {
396 // Immediates can be pushed directly. 404 if (lit->IsSmi()) {
397 __ push(Immediate(lit)); 405 __ SafePush(Immediate(lit));
406 } else {
407 __ push(Immediate(lit));
408 }
398 } 409 }
399 410
400 411
401 void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const { 412 void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const {
402 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, 413 codegen()->PrepareForBailoutBeforeSplit(TOS_REG,
403 true, 414 true,
404 true_label_, 415 true_label_,
405 false_label_); 416 false_label_);
406 ASSERT(!lit->IsUndetectableObject()); // There are no undetectable literals. 417 ASSERT(!lit->IsUndetectableObject()); // There are no undetectable literals.
407 if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) { 418 if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) {
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
466 void FullCodeGenerator::EffectContext::Plug(Label* materialize_true, 477 void FullCodeGenerator::EffectContext::Plug(Label* materialize_true,
467 Label* materialize_false) const { 478 Label* materialize_false) const {
468 ASSERT(materialize_true == materialize_false); 479 ASSERT(materialize_true == materialize_false);
469 __ bind(materialize_true); 480 __ bind(materialize_true);
470 } 481 }
471 482
472 483
473 void FullCodeGenerator::AccumulatorValueContext::Plug( 484 void FullCodeGenerator::AccumulatorValueContext::Plug(
474 Label* materialize_true, 485 Label* materialize_true,
475 Label* materialize_false) const { 486 Label* materialize_false) const {
476 NearLabel done; 487 Label done;
477 __ bind(materialize_true); 488 __ bind(materialize_true);
478 __ mov(result_register(), isolate()->factory()->true_value()); 489 __ mov(result_register(), isolate()->factory()->true_value());
479 __ jmp(&done); 490 __ jmp(&done, Label::kNear);
480 __ bind(materialize_false); 491 __ bind(materialize_false);
481 __ mov(result_register(), isolate()->factory()->false_value()); 492 __ mov(result_register(), isolate()->factory()->false_value());
482 __ bind(&done); 493 __ bind(&done);
483 } 494 }
484 495
485 496
486 void FullCodeGenerator::StackValueContext::Plug( 497 void FullCodeGenerator::StackValueContext::Plug(
487 Label* materialize_true, 498 Label* materialize_true,
488 Label* materialize_false) const { 499 Label* materialize_false) const {
489 NearLabel done; 500 Label done;
490 __ bind(materialize_true); 501 __ bind(materialize_true);
491 __ push(Immediate(isolate()->factory()->true_value())); 502 __ push(Immediate(isolate()->factory()->true_value()));
492 __ jmp(&done); 503 __ jmp(&done, Label::kNear);
493 __ bind(materialize_false); 504 __ bind(materialize_false);
494 __ push(Immediate(isolate()->factory()->false_value())); 505 __ push(Immediate(isolate()->factory()->false_value()));
495 __ bind(&done); 506 __ bind(&done);
496 } 507 }
497 508
498 509
499 void FullCodeGenerator::TestContext::Plug(Label* materialize_true, 510 void FullCodeGenerator::TestContext::Plug(Label* materialize_true,
500 Label* materialize_false) const { 511 Label* materialize_false) const {
501 ASSERT(materialize_true == true_label_); 512 ASSERT(materialize_true == true_label_);
502 ASSERT(materialize_false == false_label_); 513 ASSERT(materialize_false == false_label_);
(...skipping 29 matching lines...) Expand all
532 if (true_label_ != fall_through_) __ jmp(true_label_); 543 if (true_label_ != fall_through_) __ jmp(true_label_);
533 } else { 544 } else {
534 if (false_label_ != fall_through_) __ jmp(false_label_); 545 if (false_label_ != fall_through_) __ jmp(false_label_);
535 } 546 }
536 } 547 }
537 548
538 549
539 void FullCodeGenerator::DoTest(Label* if_true, 550 void FullCodeGenerator::DoTest(Label* if_true,
540 Label* if_false, 551 Label* if_false,
541 Label* fall_through) { 552 Label* fall_through) {
542 // Emit the inlined tests assumed by the stub.
543 __ cmp(result_register(), isolate()->factory()->undefined_value());
544 __ j(equal, if_false);
545 __ cmp(result_register(), isolate()->factory()->true_value());
546 __ j(equal, if_true);
547 __ cmp(result_register(), isolate()->factory()->false_value());
548 __ j(equal, if_false);
549 STATIC_ASSERT(kSmiTag == 0);
550 __ test(result_register(), Operand(result_register()));
551 __ j(zero, if_false);
552 __ test(result_register(), Immediate(kSmiTagMask));
553 __ j(zero, if_true);
554
555 // Call the ToBoolean stub for all other cases.
556 ToBooleanStub stub; 553 ToBooleanStub stub;
557 __ push(result_register()); 554 __ push(result_register());
558 __ CallStub(&stub); 555 __ CallStub(&stub);
559 __ test(eax, Operand(eax)); 556 __ test(eax, Operand(eax));
560
561 // The stub returns nonzero for true. 557 // The stub returns nonzero for true.
562 Split(not_zero, if_true, if_false, fall_through); 558 Split(not_zero, if_true, if_false, fall_through);
563 } 559 }
564 560
565 561
566 void FullCodeGenerator::Split(Condition cc, 562 void FullCodeGenerator::Split(Condition cc,
567 Label* if_true, 563 Label* if_true,
568 Label* if_false, 564 Label* if_false,
569 Label* fall_through) { 565 Label* fall_through) {
570 if (if_false == fall_through) { 566 if (if_false == fall_through) {
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
623 619
624 void FullCodeGenerator::PrepareForBailoutBeforeSplit(State state, 620 void FullCodeGenerator::PrepareForBailoutBeforeSplit(State state,
625 bool should_normalize, 621 bool should_normalize,
626 Label* if_true, 622 Label* if_true,
627 Label* if_false) { 623 Label* if_false) {
628 // Only prepare for bailouts before splits if we're in a test 624 // Only prepare for bailouts before splits if we're in a test
629 // context. Otherwise, we let the Visit function deal with the 625 // context. Otherwise, we let the Visit function deal with the
630 // preparation to avoid preparing with the same AST id twice. 626 // preparation to avoid preparing with the same AST id twice.
631 if (!context()->IsTest() || !info_->IsOptimizable()) return; 627 if (!context()->IsTest() || !info_->IsOptimizable()) return;
632 628
633 NearLabel skip; 629 Label skip;
634 if (should_normalize) __ jmp(&skip); 630 if (should_normalize) __ jmp(&skip, Label::kNear);
635 631
636 ForwardBailoutStack* current = forward_bailout_stack_; 632 ForwardBailoutStack* current = forward_bailout_stack_;
637 while (current != NULL) { 633 while (current != NULL) {
638 PrepareForBailout(current->expr(), state); 634 PrepareForBailout(current->expr(), state);
639 current = current->parent(); 635 current = current->parent();
640 } 636 }
641 637
642 if (should_normalize) { 638 if (should_normalize) {
643 __ cmp(eax, isolate()->factory()->true_value()); 639 __ cmp(eax, isolate()->factory()->true_value());
644 Split(equal, if_true, if_false, NULL); 640 Split(equal, if_true, if_false, NULL);
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
734 if (function != NULL) { 730 if (function != NULL) {
735 __ push(eax); 731 __ push(eax);
736 VisitForAccumulatorValue(function); 732 VisitForAccumulatorValue(function);
737 __ pop(edx); 733 __ pop(edx);
738 } else { 734 } else {
739 __ mov(edx, eax); 735 __ mov(edx, eax);
740 __ mov(eax, isolate()->factory()->the_hole_value()); 736 __ mov(eax, isolate()->factory()->the_hole_value());
741 } 737 }
742 ASSERT(prop->key()->AsLiteral() != NULL && 738 ASSERT(prop->key()->AsLiteral() != NULL &&
743 prop->key()->AsLiteral()->handle()->IsSmi()); 739 prop->key()->AsLiteral()->handle()->IsSmi());
744 __ Set(ecx, Immediate(prop->key()->AsLiteral()->handle())); 740 __ SafeSet(ecx, Immediate(prop->key()->AsLiteral()->handle()));
745 741
746 Handle<Code> ic = is_strict_mode() 742 Handle<Code> ic = is_strict_mode()
747 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() 743 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
748 : isolate()->builtins()->KeyedStoreIC_Initialize(); 744 : isolate()->builtins()->KeyedStoreIC_Initialize();
749 EmitCallIC(ic, RelocInfo::CODE_TARGET, AstNode::kNoNumber); 745 EmitCallIC(ic, RelocInfo::CODE_TARGET, AstNode::kNoNumber);
750 } 746 }
751 } 747 }
752 } 748 }
753 749
754 750
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
797 next_test.Unuse(); 793 next_test.Unuse();
798 794
799 // Compile the label expression. 795 // Compile the label expression.
800 VisitForAccumulatorValue(clause->label()); 796 VisitForAccumulatorValue(clause->label());
801 797
802 // Perform the comparison as if via '==='. 798 // Perform the comparison as if via '==='.
803 __ mov(edx, Operand(esp, 0)); // Switch value. 799 __ mov(edx, Operand(esp, 0)); // Switch value.
804 bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT); 800 bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT);
805 JumpPatchSite patch_site(masm_); 801 JumpPatchSite patch_site(masm_);
806 if (inline_smi_code) { 802 if (inline_smi_code) {
807 NearLabel slow_case; 803 Label slow_case;
808 __ mov(ecx, edx); 804 __ mov(ecx, edx);
809 __ or_(ecx, Operand(eax)); 805 __ or_(ecx, Operand(eax));
810 patch_site.EmitJumpIfNotSmi(ecx, &slow_case); 806 patch_site.EmitJumpIfNotSmi(ecx, &slow_case, Label::kNear);
811 807
812 __ cmp(edx, Operand(eax)); 808 __ cmp(edx, Operand(eax));
813 __ j(not_equal, &next_test); 809 __ j(not_equal, &next_test);
814 __ Drop(1); // Switch value is no longer needed. 810 __ Drop(1); // Switch value is no longer needed.
815 __ jmp(clause->body_target()); 811 __ jmp(clause->body_target());
816 __ bind(&slow_case); 812 __ bind(&slow_case);
817 } 813 }
818 814
819 // Record position before stub call for type feedback. 815 // Record position before stub call for type feedback.
820 SetSourcePosition(clause->position()); 816 SetSourcePosition(clause->position());
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
861 // Get the object to enumerate over. Both SpiderMonkey and JSC 857 // Get the object to enumerate over. Both SpiderMonkey and JSC
862 // ignore null and undefined in contrast to the specification; see 858 // ignore null and undefined in contrast to the specification; see
863 // ECMA-262 section 12.6.4. 859 // ECMA-262 section 12.6.4.
864 VisitForAccumulatorValue(stmt->enumerable()); 860 VisitForAccumulatorValue(stmt->enumerable());
865 __ cmp(eax, isolate()->factory()->undefined_value()); 861 __ cmp(eax, isolate()->factory()->undefined_value());
866 __ j(equal, &exit); 862 __ j(equal, &exit);
867 __ cmp(eax, isolate()->factory()->null_value()); 863 __ cmp(eax, isolate()->factory()->null_value());
868 __ j(equal, &exit); 864 __ j(equal, &exit);
869 865
870 // Convert the object to a JS object. 866 // Convert the object to a JS object.
871 NearLabel convert, done_convert; 867 Label convert, done_convert;
872 __ test(eax, Immediate(kSmiTagMask)); 868 __ test(eax, Immediate(kSmiTagMask));
873 __ j(zero, &convert); 869 __ j(zero, &convert, Label::kNear);
874 __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx); 870 __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx);
875 __ j(above_equal, &done_convert); 871 __ j(above_equal, &done_convert, Label::kNear);
876 __ bind(&convert); 872 __ bind(&convert);
877 __ push(eax); 873 __ push(eax);
878 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); 874 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
879 __ bind(&done_convert); 875 __ bind(&done_convert);
880 __ push(eax); 876 __ push(eax);
881 877
882 // Check cache validity in generated code. This is a fast case for 878 // Check cache validity in generated code. This is a fast case for
883 // the JSObject::IsSimpleEnum cache validity checks. If we cannot 879 // the JSObject::IsSimpleEnum cache validity checks. If we cannot
884 // guarantee cache validity, call the runtime system to check cache 880 // guarantee cache validity, call the runtime system to check cache
885 // validity or get the property names in a fixed array. 881 // validity or get the property names in a fixed array.
(...skipping 16 matching lines...) Expand all
902 __ j(equal, &call_runtime); 898 __ j(equal, &call_runtime);
903 899
904 // Check that there is an enum cache in the non-empty instance 900 // Check that there is an enum cache in the non-empty instance
905 // descriptors (edx). This is the case if the next enumeration 901 // descriptors (edx). This is the case if the next enumeration
906 // index field does not contain a smi. 902 // index field does not contain a smi.
907 __ mov(edx, FieldOperand(edx, DescriptorArray::kEnumerationIndexOffset)); 903 __ mov(edx, FieldOperand(edx, DescriptorArray::kEnumerationIndexOffset));
908 __ test(edx, Immediate(kSmiTagMask)); 904 __ test(edx, Immediate(kSmiTagMask));
909 __ j(zero, &call_runtime); 905 __ j(zero, &call_runtime);
910 906
911 // For all objects but the receiver, check that the cache is empty. 907 // For all objects but the receiver, check that the cache is empty.
912 NearLabel check_prototype; 908 Label check_prototype;
913 __ cmp(ecx, Operand(eax)); 909 __ cmp(ecx, Operand(eax));
914 __ j(equal, &check_prototype); 910 __ j(equal, &check_prototype, Label::kNear);
915 __ mov(edx, FieldOperand(edx, DescriptorArray::kEnumCacheBridgeCacheOffset)); 911 __ mov(edx, FieldOperand(edx, DescriptorArray::kEnumCacheBridgeCacheOffset));
916 __ cmp(edx, isolate()->factory()->empty_fixed_array()); 912 __ cmp(edx, isolate()->factory()->empty_fixed_array());
917 __ j(not_equal, &call_runtime); 913 __ j(not_equal, &call_runtime);
918 914
919 // Load the prototype from the map and loop if non-null. 915 // Load the prototype from the map and loop if non-null.
920 __ bind(&check_prototype); 916 __ bind(&check_prototype);
921 __ mov(ecx, FieldOperand(ebx, Map::kPrototypeOffset)); 917 __ mov(ecx, FieldOperand(ebx, Map::kPrototypeOffset));
922 __ cmp(ecx, isolate()->factory()->null_value()); 918 __ cmp(ecx, isolate()->factory()->null_value());
923 __ j(not_equal, &next); 919 __ j(not_equal, &next);
924 920
925 // The enum cache is valid. Load the map of the object being 921 // The enum cache is valid. Load the map of the object being
926 // iterated over and use the cache for the iteration. 922 // iterated over and use the cache for the iteration.
927 NearLabel use_cache; 923 Label use_cache;
928 __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset)); 924 __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset));
929 __ jmp(&use_cache); 925 __ jmp(&use_cache, Label::kNear);
930 926
931 // Get the set of properties to enumerate. 927 // Get the set of properties to enumerate.
932 __ bind(&call_runtime); 928 __ bind(&call_runtime);
933 __ push(eax); // Duplicate the enumerable object on the stack. 929 __ push(eax); // Duplicate the enumerable object on the stack.
934 __ CallRuntime(Runtime::kGetPropertyNamesFast, 1); 930 __ CallRuntime(Runtime::kGetPropertyNamesFast, 1);
935 931
936 // If we got a map from the runtime call, we can do a fast 932 // If we got a map from the runtime call, we can do a fast
937 // modification check. Otherwise, we got a fixed array, and we have 933 // modification check. Otherwise, we got a fixed array, and we have
938 // to do a slow check. 934 // to do a slow check.
939 NearLabel fixed_array; 935 Label fixed_array;
940 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), 936 __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
941 isolate()->factory()->meta_map()); 937 isolate()->factory()->meta_map());
942 __ j(not_equal, &fixed_array); 938 __ j(not_equal, &fixed_array, Label::kNear);
943 939
944 // We got a map in register eax. Get the enumeration cache from it. 940 // We got a map in register eax. Get the enumeration cache from it.
945 __ bind(&use_cache); 941 __ bind(&use_cache);
946 __ mov(ecx, FieldOperand(eax, Map::kInstanceDescriptorsOffset)); 942 __ mov(ecx, FieldOperand(eax, Map::kInstanceDescriptorsOffset));
947 __ mov(ecx, FieldOperand(ecx, DescriptorArray::kEnumerationIndexOffset)); 943 __ mov(ecx, FieldOperand(ecx, DescriptorArray::kEnumerationIndexOffset));
948 __ mov(edx, FieldOperand(ecx, DescriptorArray::kEnumCacheBridgeCacheOffset)); 944 __ mov(edx, FieldOperand(ecx, DescriptorArray::kEnumCacheBridgeCacheOffset));
949 945
950 // Setup the four remaining stack slots. 946 // Setup the four remaining stack slots.
951 __ push(eax); // Map. 947 __ push(eax); // Map.
952 __ push(edx); // Enumeration cache. 948 __ push(edx); // Enumeration cache.
(...skipping 19 matching lines...) Expand all
972 // Get the current entry of the array into register ebx. 968 // Get the current entry of the array into register ebx.
973 __ mov(ebx, Operand(esp, 2 * kPointerSize)); 969 __ mov(ebx, Operand(esp, 2 * kPointerSize));
974 __ mov(ebx, FieldOperand(ebx, eax, times_2, FixedArray::kHeaderSize)); 970 __ mov(ebx, FieldOperand(ebx, eax, times_2, FixedArray::kHeaderSize));
975 971
976 // Get the expected map from the stack or a zero map in the 972 // Get the expected map from the stack or a zero map in the
977 // permanent slow case into register edx. 973 // permanent slow case into register edx.
978 __ mov(edx, Operand(esp, 3 * kPointerSize)); 974 __ mov(edx, Operand(esp, 3 * kPointerSize));
979 975
980 // Check if the expected map still matches that of the enumerable. 976 // Check if the expected map still matches that of the enumerable.
981 // If not, we have to filter the key. 977 // If not, we have to filter the key.
982 NearLabel update_each; 978 Label update_each;
983 __ mov(ecx, Operand(esp, 4 * kPointerSize)); 979 __ mov(ecx, Operand(esp, 4 * kPointerSize));
984 __ cmp(edx, FieldOperand(ecx, HeapObject::kMapOffset)); 980 __ cmp(edx, FieldOperand(ecx, HeapObject::kMapOffset));
985 __ j(equal, &update_each); 981 __ j(equal, &update_each, Label::kNear);
986 982
987 // Convert the entry to a string or null if it isn't a property 983 // Convert the entry to a string or null if it isn't a property
988 // anymore. If the property has been removed while iterating, we 984 // anymore. If the property has been removed while iterating, we
989 // just skip it. 985 // just skip it.
990 __ push(ecx); // Enumerable. 986 __ push(ecx); // Enumerable.
991 __ push(ebx); // Current entry. 987 __ push(ebx); // Current entry.
992 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION); 988 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION);
993 __ test(eax, Operand(eax)); 989 __ test(eax, Operand(eax));
994 __ j(equal, loop_statement.continue_target()); 990 __ j(equal, loop_statement.continue_target());
995 __ mov(ebx, Operand(eax)); 991 __ mov(ebx, Operand(eax));
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
1083 // If no outer scope calls eval, we do not need to check more 1079 // If no outer scope calls eval, we do not need to check more
1084 // context extensions. If we have reached an eval scope, we check 1080 // context extensions. If we have reached an eval scope, we check
1085 // all extensions from this point. 1081 // all extensions from this point.
1086 if (!s->outer_scope_calls_eval() || s->is_eval_scope()) break; 1082 if (!s->outer_scope_calls_eval() || s->is_eval_scope()) break;
1087 s = s->outer_scope(); 1083 s = s->outer_scope();
1088 } 1084 }
1089 1085
1090 if (s != NULL && s->is_eval_scope()) { 1086 if (s != NULL && s->is_eval_scope()) {
1091 // Loop up the context chain. There is no frame effect so it is 1087 // Loop up the context chain. There is no frame effect so it is
1092 // safe to use raw labels here. 1088 // safe to use raw labels here.
1093 NearLabel next, fast; 1089 Label next, fast;
1094 if (!context.is(temp)) { 1090 if (!context.is(temp)) {
1095 __ mov(temp, context); 1091 __ mov(temp, context);
1096 } 1092 }
1097 __ bind(&next); 1093 __ bind(&next);
1098 // Terminate at global context. 1094 // Terminate at global context.
1099 __ cmp(FieldOperand(temp, HeapObject::kMapOffset), 1095 __ cmp(FieldOperand(temp, HeapObject::kMapOffset),
1100 Immediate(isolate()->factory()->global_context_map())); 1096 Immediate(isolate()->factory()->global_context_map()));
1101 __ j(equal, &fast); 1097 __ j(equal, &fast, Label::kNear);
1102 // Check that extension is NULL. 1098 // Check that extension is NULL.
1103 __ cmp(ContextOperand(temp, Context::EXTENSION_INDEX), Immediate(0)); 1099 __ cmp(ContextOperand(temp, Context::EXTENSION_INDEX), Immediate(0));
1104 __ j(not_equal, slow); 1100 __ j(not_equal, slow);
1105 // Load next context in chain. 1101 // Load next context in chain.
1106 __ mov(temp, ContextOperand(temp, Context::CLOSURE_INDEX)); 1102 __ mov(temp, ContextOperand(temp, Context::CLOSURE_INDEX));
1107 __ mov(temp, FieldOperand(temp, JSFunction::kContextOffset)); 1103 __ mov(temp, FieldOperand(temp, JSFunction::kContextOffset));
1108 __ jmp(&next); 1104 __ jmp(&next);
1109 __ bind(&fast); 1105 __ bind(&fast);
1110 } 1106 }
1111 1107
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
1188 if (obj_proxy != NULL && 1184 if (obj_proxy != NULL &&
1189 key_literal != NULL && 1185 key_literal != NULL &&
1190 obj_proxy->IsArguments() && 1186 obj_proxy->IsArguments() &&
1191 key_literal->handle()->IsSmi()) { 1187 key_literal->handle()->IsSmi()) {
1192 // Load arguments object if there are no eval-introduced 1188 // Load arguments object if there are no eval-introduced
1193 // variables. Then load the argument from the arguments 1189 // variables. Then load the argument from the arguments
1194 // object using keyed load. 1190 // object using keyed load.
1195 __ mov(edx, 1191 __ mov(edx,
1196 ContextSlotOperandCheckExtensions(obj_proxy->var()->AsSlot(), 1192 ContextSlotOperandCheckExtensions(obj_proxy->var()->AsSlot(),
1197 slow)); 1193 slow));
1198 __ mov(eax, Immediate(key_literal->handle())); 1194 __ SafeSet(eax, Immediate(key_literal->handle()));
1199 Handle<Code> ic = 1195 Handle<Code> ic =
1200 isolate()->builtins()->KeyedLoadIC_Initialize(); 1196 isolate()->builtins()->KeyedLoadIC_Initialize();
1201 EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(property)); 1197 EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(property));
1202 __ jmp(done); 1198 __ jmp(done);
1203 } 1199 }
1204 } 1200 }
1205 } 1201 }
1206 } 1202 }
1207 } 1203 }
1208 1204
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1240 1236
1241 context()->Plug(eax); 1237 context()->Plug(eax);
1242 1238
1243 } else if (slot != NULL) { 1239 } else if (slot != NULL) {
1244 Comment cmnt(masm_, (slot->type() == Slot::CONTEXT) 1240 Comment cmnt(masm_, (slot->type() == Slot::CONTEXT)
1245 ? "Context slot" 1241 ? "Context slot"
1246 : "Stack slot"); 1242 : "Stack slot");
1247 if (var->mode() == Variable::CONST) { 1243 if (var->mode() == Variable::CONST) {
1248 // Constants may be the hole value if they have not been initialized. 1244 // Constants may be the hole value if they have not been initialized.
1249 // Unhole them. 1245 // Unhole them.
1250 NearLabel done; 1246 Label done;
1251 MemOperand slot_operand = EmitSlotSearch(slot, eax); 1247 MemOperand slot_operand = EmitSlotSearch(slot, eax);
1252 __ mov(eax, slot_operand); 1248 __ mov(eax, slot_operand);
1253 __ cmp(eax, isolate()->factory()->the_hole_value()); 1249 __ cmp(eax, isolate()->factory()->the_hole_value());
1254 __ j(not_equal, &done); 1250 __ j(not_equal, &done, Label::kNear);
1255 __ mov(eax, isolate()->factory()->undefined_value()); 1251 __ mov(eax, isolate()->factory()->undefined_value());
1256 __ bind(&done); 1252 __ bind(&done);
1257 context()->Plug(eax); 1253 context()->Plug(eax);
1258 } else { 1254 } else {
1259 context()->Plug(slot); 1255 context()->Plug(slot);
1260 } 1256 }
1261 1257
1262 } else { 1258 } else {
1263 Comment cmnt(masm_, "Rewritten parameter"); 1259 Comment cmnt(masm_, "Rewritten parameter");
1264 ASSERT_NOT_NULL(property); 1260 ASSERT_NOT_NULL(property);
1265 // Rewritten parameter accesses are of the form "slot[literal]". 1261 // Rewritten parameter accesses are of the form "slot[literal]".
1266 1262
1267 // Assert that the object is in a slot. 1263 // Assert that the object is in a slot.
1268 Variable* object_var = property->obj()->AsVariableProxy()->AsVariable(); 1264 Variable* object_var = property->obj()->AsVariableProxy()->AsVariable();
1269 ASSERT_NOT_NULL(object_var); 1265 ASSERT_NOT_NULL(object_var);
1270 Slot* object_slot = object_var->AsSlot(); 1266 Slot* object_slot = object_var->AsSlot();
1271 ASSERT_NOT_NULL(object_slot); 1267 ASSERT_NOT_NULL(object_slot);
1272 1268
1273 // Load the object. 1269 // Load the object.
1274 MemOperand object_loc = EmitSlotSearch(object_slot, eax); 1270 MemOperand object_loc = EmitSlotSearch(object_slot, eax);
1275 __ mov(edx, object_loc); 1271 __ mov(edx, object_loc);
1276 1272
1277 // Assert that the key is a smi. 1273 // Assert that the key is a smi.
1278 Literal* key_literal = property->key()->AsLiteral(); 1274 Literal* key_literal = property->key()->AsLiteral();
1279 ASSERT_NOT_NULL(key_literal); 1275 ASSERT_NOT_NULL(key_literal);
1280 ASSERT(key_literal->handle()->IsSmi()); 1276 ASSERT(key_literal->handle()->IsSmi());
1281 1277
1282 // Load the key. 1278 // Load the key.
1283 __ mov(eax, Immediate(key_literal->handle())); 1279 __ SafeSet(eax, Immediate(key_literal->handle()));
1284 1280
1285 // Do a keyed property load. 1281 // Do a keyed property load.
1286 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); 1282 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
1287 EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(property)); 1283 EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(property));
1288 1284
1289 // Drop key and object left on the stack by IC. 1285 // Drop key and object left on the stack by IC.
1290 context()->Plug(eax); 1286 context()->Plug(eax);
1291 } 1287 }
1292 } 1288 }
1293 1289
1294 1290
1295 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { 1291 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
1296 Comment cmnt(masm_, "[ RegExpLiteral"); 1292 Comment cmnt(masm_, "[ RegExpLiteral");
1297 NearLabel materialized; 1293 Label materialized;
1298 // Registers will be used as follows: 1294 // Registers will be used as follows:
1299 // edi = JS function. 1295 // edi = JS function.
1300 // ecx = literals array. 1296 // ecx = literals array.
1301 // ebx = regexp literal. 1297 // ebx = regexp literal.
1302 // eax = regexp literal clone. 1298 // eax = regexp literal clone.
1303 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 1299 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1304 __ mov(ecx, FieldOperand(edi, JSFunction::kLiteralsOffset)); 1300 __ mov(ecx, FieldOperand(edi, JSFunction::kLiteralsOffset));
1305 int literal_offset = 1301 int literal_offset =
1306 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; 1302 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
1307 __ mov(ebx, FieldOperand(ecx, literal_offset)); 1303 __ mov(ebx, FieldOperand(ecx, literal_offset));
1308 __ cmp(ebx, isolate()->factory()->undefined_value()); 1304 __ cmp(ebx, isolate()->factory()->undefined_value());
1309 __ j(not_equal, &materialized); 1305 __ j(not_equal, &materialized, Label::kNear);
1310 1306
1311 // Create regexp literal using runtime function 1307 // Create regexp literal using runtime function
1312 // Result will be in eax. 1308 // Result will be in eax.
1313 __ push(ecx); 1309 __ push(ecx);
1314 __ push(Immediate(Smi::FromInt(expr->literal_index()))); 1310 __ push(Immediate(Smi::FromInt(expr->literal_index())));
1315 __ push(Immediate(expr->pattern())); 1311 __ push(Immediate(expr->pattern()));
1316 __ push(Immediate(expr->flags())); 1312 __ push(Immediate(expr->flags()));
1317 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); 1313 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
1318 __ mov(ebx, eax); 1314 __ mov(ebx, eax);
1319 1315
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after
1544 VisitForStackValue(property->obj()); 1540 VisitForStackValue(property->obj());
1545 } 1541 }
1546 break; 1542 break;
1547 case KEYED_PROPERTY: { 1543 case KEYED_PROPERTY: {
1548 if (expr->is_compound()) { 1544 if (expr->is_compound()) {
1549 if (property->is_arguments_access()) { 1545 if (property->is_arguments_access()) {
1550 VariableProxy* obj_proxy = property->obj()->AsVariableProxy(); 1546 VariableProxy* obj_proxy = property->obj()->AsVariableProxy();
1551 MemOperand slot_operand = 1547 MemOperand slot_operand =
1552 EmitSlotSearch(obj_proxy->var()->AsSlot(), ecx); 1548 EmitSlotSearch(obj_proxy->var()->AsSlot(), ecx);
1553 __ push(slot_operand); 1549 __ push(slot_operand);
1554 __ mov(eax, Immediate(property->key()->AsLiteral()->handle())); 1550 __ SafeSet(eax, Immediate(property->key()->AsLiteral()->handle()));
1555 } else { 1551 } else {
1556 VisitForStackValue(property->obj()); 1552 VisitForStackValue(property->obj());
1557 VisitForAccumulatorValue(property->key()); 1553 VisitForAccumulatorValue(property->key());
1558 } 1554 }
1559 __ mov(edx, Operand(esp, 0)); 1555 __ mov(edx, Operand(esp, 0));
1560 __ push(eax); 1556 __ push(eax);
1561 } else { 1557 } else {
1562 if (property->is_arguments_access()) { 1558 if (property->is_arguments_access()) {
1563 VariableProxy* obj_proxy = property->obj()->AsVariableProxy(); 1559 VariableProxy* obj_proxy = property->obj()->AsVariableProxy();
1564 MemOperand slot_operand = 1560 MemOperand slot_operand =
1565 EmitSlotSearch(obj_proxy->var()->AsSlot(), ecx); 1561 EmitSlotSearch(obj_proxy->var()->AsSlot(), ecx);
1566 __ push(slot_operand); 1562 __ push(slot_operand);
1567 __ push(Immediate(property->key()->AsLiteral()->handle())); 1563 __ SafePush(Immediate(property->key()->AsLiteral()->handle()));
1568 } else { 1564 } else {
1569 VisitForStackValue(property->obj()); 1565 VisitForStackValue(property->obj());
1570 VisitForStackValue(property->key()); 1566 VisitForStackValue(property->key());
1571 } 1567 }
1572 } 1568 }
1573 break; 1569 break;
1574 } 1570 }
1575 } 1571 }
1576 1572
1577 // For compound assignments we need another deoptimization point after the 1573 // For compound assignments we need another deoptimization point after the
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1636 case KEYED_PROPERTY: 1632 case KEYED_PROPERTY:
1637 EmitKeyedPropertyAssignment(expr); 1633 EmitKeyedPropertyAssignment(expr);
1638 break; 1634 break;
1639 } 1635 }
1640 } 1636 }
1641 1637
1642 1638
1643 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { 1639 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
1644 SetSourcePosition(prop->position()); 1640 SetSourcePosition(prop->position());
1645 Literal* key = prop->key()->AsLiteral(); 1641 Literal* key = prop->key()->AsLiteral();
1642 ASSERT(!key->handle()->IsSmi());
1646 __ mov(ecx, Immediate(key->handle())); 1643 __ mov(ecx, Immediate(key->handle()));
1647 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 1644 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
1648 EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(prop)); 1645 EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(prop));
1649 } 1646 }
1650 1647
1651 1648
1652 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { 1649 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
1653 SetSourcePosition(prop->position()); 1650 SetSourcePosition(prop->position());
1654 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); 1651 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
1655 EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(prop)); 1652 EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(prop));
1656 } 1653 }
1657 1654
1658 1655
1659 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, 1656 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
1660 Token::Value op, 1657 Token::Value op,
1661 OverwriteMode mode, 1658 OverwriteMode mode,
1662 Expression* left, 1659 Expression* left,
1663 Expression* right) { 1660 Expression* right) {
1664 // Do combined smi check of the operands. Left operand is on the 1661 // Do combined smi check of the operands. Left operand is on the
1665 // stack. Right operand is in eax. 1662 // stack. Right operand is in eax.
1666 NearLabel done, smi_case, stub_call; 1663 Label smi_case, done, stub_call;
1667 __ pop(edx); 1664 __ pop(edx);
1668 __ mov(ecx, eax); 1665 __ mov(ecx, eax);
1669 __ or_(eax, Operand(edx)); 1666 __ or_(eax, Operand(edx));
1670 JumpPatchSite patch_site(masm_); 1667 JumpPatchSite patch_site(masm_);
1671 patch_site.EmitJumpIfSmi(eax, &smi_case); 1668 patch_site.EmitJumpIfSmi(eax, &smi_case, Label::kNear);
1672 1669
1673 __ bind(&stub_call); 1670 __ bind(&stub_call);
1674 __ mov(eax, ecx); 1671 __ mov(eax, ecx);
1675 TypeRecordingBinaryOpStub stub(op, mode); 1672 TypeRecordingBinaryOpStub stub(op, mode);
1676 EmitCallIC(stub.GetCode(), &patch_site, expr->id()); 1673 EmitCallIC(stub.GetCode(), &patch_site, expr->id());
1677 __ jmp(&done); 1674 __ jmp(&done, Label::kNear);
1678 1675
1679 // Smi case. 1676 // Smi case.
1680 __ bind(&smi_case); 1677 __ bind(&smi_case);
1681 __ mov(eax, edx); // Copy left operand in case of a stub call. 1678 __ mov(eax, edx); // Copy left operand in case of a stub call.
1682 1679
1683 switch (op) { 1680 switch (op) {
1684 case Token::SAR: 1681 case Token::SAR:
1685 __ SmiUntag(eax); 1682 __ SmiUntag(eax);
1686 __ SmiUntag(ecx); 1683 __ SmiUntag(ecx);
1687 __ sar_cl(eax); // No checks of result necessary 1684 __ sar_cl(eax); // No checks of result necessary
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1720 break; 1717 break;
1721 case Token::SUB: 1718 case Token::SUB:
1722 __ sub(eax, Operand(ecx)); 1719 __ sub(eax, Operand(ecx));
1723 __ j(overflow, &stub_call); 1720 __ j(overflow, &stub_call);
1724 break; 1721 break;
1725 case Token::MUL: { 1722 case Token::MUL: {
1726 __ SmiUntag(eax); 1723 __ SmiUntag(eax);
1727 __ imul(eax, Operand(ecx)); 1724 __ imul(eax, Operand(ecx));
1728 __ j(overflow, &stub_call); 1725 __ j(overflow, &stub_call);
1729 __ test(eax, Operand(eax)); 1726 __ test(eax, Operand(eax));
1730 __ j(not_zero, &done, taken); 1727 __ j(not_zero, &done, Label::kNear);
1731 __ mov(ebx, edx); 1728 __ mov(ebx, edx);
1732 __ or_(ebx, Operand(ecx)); 1729 __ or_(ebx, Operand(ecx));
1733 __ j(negative, &stub_call); 1730 __ j(negative, &stub_call);
1734 break; 1731 break;
1735 } 1732 }
1736 case Token::BIT_OR: 1733 case Token::BIT_OR:
1737 __ or_(eax, Operand(ecx)); 1734 __ or_(eax, Operand(ecx));
1738 break; 1735 break;
1739 case Token::BIT_AND: 1736 case Token::BIT_AND:
1740 __ and_(eax, Operand(ecx)); 1737 __ and_(eax, Operand(ecx));
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
1802 } 1799 }
1803 case KEYED_PROPERTY: { 1800 case KEYED_PROPERTY: {
1804 __ push(eax); // Preserve value. 1801 __ push(eax); // Preserve value.
1805 if (prop->is_synthetic()) { 1802 if (prop->is_synthetic()) {
1806 ASSERT(prop->obj()->AsVariableProxy() != NULL); 1803 ASSERT(prop->obj()->AsVariableProxy() != NULL);
1807 ASSERT(prop->key()->AsLiteral() != NULL); 1804 ASSERT(prop->key()->AsLiteral() != NULL);
1808 { AccumulatorValueContext for_object(this); 1805 { AccumulatorValueContext for_object(this);
1809 EmitVariableLoad(prop->obj()->AsVariableProxy()->var()); 1806 EmitVariableLoad(prop->obj()->AsVariableProxy()->var());
1810 } 1807 }
1811 __ mov(edx, eax); 1808 __ mov(edx, eax);
1812 __ Set(ecx, Immediate(prop->key()->AsLiteral()->handle())); 1809 __ SafeSet(ecx, Immediate(prop->key()->AsLiteral()->handle()));
1813 } else { 1810 } else {
1814 VisitForStackValue(prop->obj()); 1811 VisitForStackValue(prop->obj());
1815 VisitForAccumulatorValue(prop->key()); 1812 VisitForAccumulatorValue(prop->key());
1816 __ mov(ecx, eax); 1813 __ mov(ecx, eax);
1817 __ pop(edx); 1814 __ pop(edx);
1818 } 1815 }
1819 __ pop(eax); // Restore value. 1816 __ pop(eax); // Restore value.
1820 Handle<Code> ic = is_strict_mode() 1817 Handle<Code> ic = is_strict_mode()
1821 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() 1818 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
1822 : isolate()->builtins()->KeyedStoreIC_Initialize(); 1819 : isolate()->builtins()->KeyedStoreIC_Initialize();
(...skipping 493 matching lines...) Expand 10 before | Expand all | Expand 10 after
2316 int arg_count = args->length(); 2313 int arg_count = args->length();
2317 for (int i = 0; i < arg_count; i++) { 2314 for (int i = 0; i < arg_count; i++) {
2318 VisitForStackValue(args->at(i)); 2315 VisitForStackValue(args->at(i));
2319 } 2316 }
2320 2317
2321 // Call the construct call builtin that handles allocation and 2318 // Call the construct call builtin that handles allocation and
2322 // constructor invocation. 2319 // constructor invocation.
2323 SetSourcePosition(expr->position()); 2320 SetSourcePosition(expr->position());
2324 2321
2325 // Load function and argument count into edi and eax. 2322 // Load function and argument count into edi and eax.
2326 __ Set(eax, Immediate(arg_count)); 2323 __ SafeSet(eax, Immediate(arg_count));
2327 __ mov(edi, Operand(esp, arg_count * kPointerSize)); 2324 __ mov(edi, Operand(esp, arg_count * kPointerSize));
2328 2325
2329 Handle<Code> construct_builtin = 2326 Handle<Code> construct_builtin =
2330 isolate()->builtins()->JSConstructCall(); 2327 isolate()->builtins()->JSConstructCall();
2331 __ call(construct_builtin, RelocInfo::CONSTRUCT_CALL); 2328 __ call(construct_builtin, RelocInfo::CONSTRUCT_CALL);
2332 context()->Plug(eax); 2329 context()->Plug(eax);
2333 } 2330 }
2334 2331
2335 2332
2336 void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) { 2333 void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) {
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after
2656 } 2653 }
2657 2654
2658 2655
2659 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) { 2656 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) {
2660 ASSERT(args->length() == 1); 2657 ASSERT(args->length() == 1);
2661 2658
2662 // ArgumentsAccessStub expects the key in edx and the formal 2659 // ArgumentsAccessStub expects the key in edx and the formal
2663 // parameter count in eax. 2660 // parameter count in eax.
2664 VisitForAccumulatorValue(args->at(0)); 2661 VisitForAccumulatorValue(args->at(0));
2665 __ mov(edx, eax); 2662 __ mov(edx, eax);
2666 __ mov(eax, Immediate(Smi::FromInt(scope()->num_parameters()))); 2663 __ SafeSet(eax, Immediate(Smi::FromInt(scope()->num_parameters())));
2667 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); 2664 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
2668 __ CallStub(&stub); 2665 __ CallStub(&stub);
2669 context()->Plug(eax); 2666 context()->Plug(eax);
2670 } 2667 }
2671 2668
2672 2669
2673 void FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) { 2670 void FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) {
2674 ASSERT(args->length() == 0); 2671 ASSERT(args->length() == 0);
2675 2672
2676 Label exit; 2673 Label exit;
2677 // Get the number of formal parameters. 2674 // Get the number of formal parameters.
2678 __ Set(eax, Immediate(Smi::FromInt(scope()->num_parameters()))); 2675 __ SafeSet(eax, Immediate(Smi::FromInt(scope()->num_parameters())));
2679 2676
2680 // Check if the calling frame is an arguments adaptor frame. 2677 // Check if the calling frame is an arguments adaptor frame.
2681 __ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); 2678 __ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
2682 __ cmp(Operand(ebx, StandardFrameConstants::kContextOffset), 2679 __ cmp(Operand(ebx, StandardFrameConstants::kContextOffset),
2683 Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 2680 Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
2684 __ j(not_equal, &exit); 2681 __ j(not_equal, &exit);
2685 2682
2686 // Arguments adaptor case: Read the arguments length from the 2683 // Arguments adaptor case: Read the arguments length from the
2687 // adaptor frame. 2684 // adaptor frame.
2688 __ mov(eax, Operand(ebx, ArgumentsAdaptorFrameConstants::kLengthOffset)); 2685 __ mov(eax, Operand(ebx, ArgumentsAdaptorFrameConstants::kLengthOffset));
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
2843 __ CallStub(&stub); 2840 __ CallStub(&stub);
2844 context()->Plug(eax); 2841 context()->Plug(eax);
2845 } 2842 }
2846 2843
2847 2844
2848 void FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) { 2845 void FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) {
2849 ASSERT(args->length() == 1); 2846 ASSERT(args->length() == 1);
2850 2847
2851 VisitForAccumulatorValue(args->at(0)); // Load the object. 2848 VisitForAccumulatorValue(args->at(0)); // Load the object.
2852 2849
2853 NearLabel done; 2850 Label done;
2854 // If the object is a smi return the object. 2851 // If the object is a smi return the object.
2855 __ test(eax, Immediate(kSmiTagMask)); 2852 __ test(eax, Immediate(kSmiTagMask));
2856 __ j(zero, &done); 2853 __ j(zero, &done, Label::kNear);
2857 // If the object is not a value type, return the object. 2854 // If the object is not a value type, return the object.
2858 __ CmpObjectType(eax, JS_VALUE_TYPE, ebx); 2855 __ CmpObjectType(eax, JS_VALUE_TYPE, ebx);
2859 __ j(not_equal, &done); 2856 __ j(not_equal, &done, Label::kNear);
2860 __ mov(eax, FieldOperand(eax, JSValue::kValueOffset)); 2857 __ mov(eax, FieldOperand(eax, JSValue::kValueOffset));
2861 2858
2862 __ bind(&done); 2859 __ bind(&done);
2863 context()->Plug(eax); 2860 context()->Plug(eax);
2864 } 2861 }
2865 2862
2866 2863
2867 void FullCodeGenerator::EmitMathPow(ZoneList<Expression*>* args) { 2864 void FullCodeGenerator::EmitMathPow(ZoneList<Expression*>* args) {
2868 // Load the arguments on the stack and call the runtime function. 2865 // Load the arguments on the stack and call the runtime function.
2869 ASSERT(args->length() == 2); 2866 ASSERT(args->length() == 2);
(...skipping 13 matching lines...) Expand all
2883 void FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) { 2880 void FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) {
2884 ASSERT(args->length() == 2); 2881 ASSERT(args->length() == 2);
2885 2882
2886 VisitForStackValue(args->at(0)); // Load the object. 2883 VisitForStackValue(args->at(0)); // Load the object.
2887 VisitForAccumulatorValue(args->at(1)); // Load the value. 2884 VisitForAccumulatorValue(args->at(1)); // Load the value.
2888 __ pop(ebx); // eax = value. ebx = object. 2885 __ pop(ebx); // eax = value. ebx = object.
2889 2886
2890 Label done; 2887 Label done;
2891 // If the object is a smi, return the value. 2888 // If the object is a smi, return the value.
2892 __ test(ebx, Immediate(kSmiTagMask)); 2889 __ test(ebx, Immediate(kSmiTagMask));
2893 __ j(zero, &done); 2890 __ j(zero, &done, Label::kNear);
2894 2891
2895 // If the object is not a value type, return the value. 2892 // If the object is not a value type, return the value.
2896 __ CmpObjectType(ebx, JS_VALUE_TYPE, ecx); 2893 __ CmpObjectType(ebx, JS_VALUE_TYPE, ecx);
2897 __ j(not_equal, &done); 2894 __ j(not_equal, &done, Label::kNear);
2898 2895
2899 // Store the value. 2896 // Store the value.
2900 __ mov(FieldOperand(ebx, JSValue::kValueOffset), eax); 2897 __ mov(FieldOperand(ebx, JSValue::kValueOffset), eax);
2901 2898
2902 // Update the write barrier. Save the value as it will be 2899 // Update the write barrier. Save the value as it will be
2903 // overwritten by the write barrier code and is needed afterward. 2900 // overwritten by the write barrier code and is needed afterward.
2904 __ mov(edx, eax); 2901 __ mov(edx, eax);
2905 __ RecordWriteField(ebx, JSValue::kValueOffset, edx, ecx, kDontSaveFPRegs); 2902 __ RecordWriteField(ebx, JSValue::kValueOffset, edx, ecx, kDontSaveFPRegs);
2906 2903
2907 __ bind(&done); 2904 __ bind(&done);
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after
3177 // Bring addresses into index1 and index2. 3174 // Bring addresses into index1 and index2.
3178 __ lea(index_1, CodeGenerator::FixedArrayElementOperand(elements, index_1)); 3175 __ lea(index_1, CodeGenerator::FixedArrayElementOperand(elements, index_1));
3179 __ lea(index_2, CodeGenerator::FixedArrayElementOperand(elements, index_2)); 3176 __ lea(index_2, CodeGenerator::FixedArrayElementOperand(elements, index_2));
3180 3177
3181 // Swap elements. Use object and temp as scratch registers. 3178 // Swap elements. Use object and temp as scratch registers.
3182 __ mov(object, Operand(index_1, 0)); 3179 __ mov(object, Operand(index_1, 0));
3183 __ mov(temp, Operand(index_2, 0)); 3180 __ mov(temp, Operand(index_2, 0));
3184 __ mov(Operand(index_2, 0), object); 3181 __ mov(Operand(index_2, 0), object);
3185 __ mov(Operand(index_1, 0), temp); 3182 __ mov(Operand(index_1, 0), temp);
3186 3183
3187 NearLabel no_remembered_set; 3184 Label no_remembered_set;
3188 __ InNewSpace(elements, temp, equal, &no_remembered_set); 3185 __ InNewSpace(elements, temp, equal, &no_remembered_set, Label::kNear);
3189 __ CheckPageFlag(elements, 3186 __ CheckPageFlag(elements,
3190 temp, 3187 temp,
3191 MemoryChunk::SCAN_ON_SCAVENGE, 3188 MemoryChunk::SCAN_ON_SCAVENGE,
3192 not_zero, 3189 not_zero,
3193 &no_remembered_set); 3190 &no_remembered_set,
3191 Label::kNear);
3194 3192
3195 __ mov(object, elements); 3193 __ mov(object, elements);
3196 // Since we are swapping two objects, the incremental marker is not disturbed, 3194 // Since we are swapping two objects, the incremental marker is not disturbed,
3197 // so we don't call the stub that handles this. TODO(gc): Optimize by 3195 // so we don't call the stub that handles this. TODO(gc): Optimize by
3198 // checking the scan_on_scavenge flag, probably by calling the stub. 3196 // checking the scan_on_scavenge flag, probably by calling the stub.
3199 __ RememberedSetHelper(index_1, temp, kDontSaveFPRegs); 3197 __ RememberedSetHelper(index_1, temp, kDontSaveFPRegs);
3200 __ RememberedSetHelper(index_2, temp, kDontSaveFPRegs); 3198 __ RememberedSetHelper(index_2, temp, kDontSaveFPRegs);
3201 3199
3202 __ bind(&no_remembered_set); 3200 __ bind(&no_remembered_set);
3203 3201
(...skipping 615 matching lines...) Expand 10 before | Expand all | Expand 10 after
3819 // Put the object both on the stack and in the accumulator. 3817 // Put the object both on the stack and in the accumulator.
3820 VisitForAccumulatorValue(prop->obj()); 3818 VisitForAccumulatorValue(prop->obj());
3821 __ push(eax); 3819 __ push(eax);
3822 EmitNamedPropertyLoad(prop); 3820 EmitNamedPropertyLoad(prop);
3823 } else { 3821 } else {
3824 if (prop->is_arguments_access()) { 3822 if (prop->is_arguments_access()) {
3825 VariableProxy* obj_proxy = prop->obj()->AsVariableProxy(); 3823 VariableProxy* obj_proxy = prop->obj()->AsVariableProxy();
3826 MemOperand slot_operand = 3824 MemOperand slot_operand =
3827 EmitSlotSearch(obj_proxy->var()->AsSlot(), ecx); 3825 EmitSlotSearch(obj_proxy->var()->AsSlot(), ecx);
3828 __ push(slot_operand); 3826 __ push(slot_operand);
3829 __ mov(eax, Immediate(prop->key()->AsLiteral()->handle())); 3827 __ SafeSet(eax, Immediate(prop->key()->AsLiteral()->handle()));
3830 } else { 3828 } else {
3831 VisitForStackValue(prop->obj()); 3829 VisitForStackValue(prop->obj());
3832 VisitForAccumulatorValue(prop->key()); 3830 VisitForAccumulatorValue(prop->key());
3833 } 3831 }
3834 __ mov(edx, Operand(esp, 0)); 3832 __ mov(edx, Operand(esp, 0));
3835 __ push(eax); 3833 __ push(eax);
3836 EmitKeyedPropertyLoad(prop); 3834 EmitKeyedPropertyLoad(prop);
3837 } 3835 }
3838 } 3836 }
3839 3837
3840 // We need a second deoptimization point after loading the value 3838 // We need a second deoptimization point after loading the value
3841 // in case evaluating the property load my have a side effect. 3839 // in case evaluating the property load my have a side effect.
3842 if (assign_type == VARIABLE) { 3840 if (assign_type == VARIABLE) {
3843 PrepareForBailout(expr->expression(), TOS_REG); 3841 PrepareForBailout(expr->expression(), TOS_REG);
3844 } else { 3842 } else {
3845 PrepareForBailoutForId(expr->CountId(), TOS_REG); 3843 PrepareForBailoutForId(expr->CountId(), TOS_REG);
3846 } 3844 }
3847 3845
3848 // Call ToNumber only if operand is not a smi. 3846 // Call ToNumber only if operand is not a smi.
3849 NearLabel no_conversion; 3847 Label no_conversion;
3850 if (ShouldInlineSmiCase(expr->op())) { 3848 if (ShouldInlineSmiCase(expr->op())) {
3851 __ test(eax, Immediate(kSmiTagMask)); 3849 __ test(eax, Immediate(kSmiTagMask));
3852 __ j(zero, &no_conversion); 3850 __ j(zero, &no_conversion, Label::kNear);
3853 } 3851 }
3854 ToNumberStub convert_stub; 3852 ToNumberStub convert_stub;
3855 __ CallStub(&convert_stub); 3853 __ CallStub(&convert_stub);
3856 __ bind(&no_conversion); 3854 __ bind(&no_conversion);
3857 3855
3858 // Save result for postfix expressions. 3856 // Save result for postfix expressions.
3859 if (expr->is_postfix()) { 3857 if (expr->is_postfix()) {
3860 if (!context()->IsEffect()) { 3858 if (!context()->IsEffect()) {
3861 // Save the result on the stack. If we have a named or keyed property 3859 // Save the result on the stack. If we have a named or keyed property
3862 // we store the result under the receiver that is currently on top 3860 // we store the result under the receiver that is currently on top
3863 // of the stack. 3861 // of the stack.
3864 switch (assign_type) { 3862 switch (assign_type) {
3865 case VARIABLE: 3863 case VARIABLE:
3866 __ push(eax); 3864 __ push(eax);
3867 break; 3865 break;
3868 case NAMED_PROPERTY: 3866 case NAMED_PROPERTY:
3869 __ mov(Operand(esp, kPointerSize), eax); 3867 __ mov(Operand(esp, kPointerSize), eax);
3870 break; 3868 break;
3871 case KEYED_PROPERTY: 3869 case KEYED_PROPERTY:
3872 __ mov(Operand(esp, 2 * kPointerSize), eax); 3870 __ mov(Operand(esp, 2 * kPointerSize), eax);
3873 break; 3871 break;
3874 } 3872 }
3875 } 3873 }
3876 } 3874 }
3877 3875
3878 // Inline smi case if we are in a loop. 3876 // Inline smi case if we are in a loop.
3879 NearLabel stub_call, done; 3877 Label done, stub_call;
3880 JumpPatchSite patch_site(masm_); 3878 JumpPatchSite patch_site(masm_);
3881 3879
3882 if (ShouldInlineSmiCase(expr->op())) { 3880 if (ShouldInlineSmiCase(expr->op())) {
3883 if (expr->op() == Token::INC) { 3881 if (expr->op() == Token::INC) {
3884 __ add(Operand(eax), Immediate(Smi::FromInt(1))); 3882 __ add(Operand(eax), Immediate(Smi::FromInt(1)));
3885 } else { 3883 } else {
3886 __ sub(Operand(eax), Immediate(Smi::FromInt(1))); 3884 __ sub(Operand(eax), Immediate(Smi::FromInt(1)));
3887 } 3885 }
3888 __ j(overflow, &stub_call); 3886 __ j(overflow, &stub_call, Label::kNear);
3889 // We could eliminate this smi check if we split the code at 3887 // We could eliminate this smi check if we split the code at
3890 // the first smi check before calling ToNumber. 3888 // the first smi check before calling ToNumber.
3891 patch_site.EmitJumpIfSmi(eax, &done); 3889 patch_site.EmitJumpIfSmi(eax, &done, Label::kNear);
3892 3890
3893 __ bind(&stub_call); 3891 __ bind(&stub_call);
3894 // Call stub. Undo operation first. 3892 // Call stub. Undo operation first.
3895 if (expr->op() == Token::INC) { 3893 if (expr->op() == Token::INC) {
3896 __ sub(Operand(eax), Immediate(Smi::FromInt(1))); 3894 __ sub(Operand(eax), Immediate(Smi::FromInt(1)));
3897 } else { 3895 } else {
3898 __ add(Operand(eax), Immediate(Smi::FromInt(1))); 3896 __ add(Operand(eax), Immediate(Smi::FromInt(1)));
3899 } 3897 }
3900 } 3898 }
3901 3899
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after
4164 break; 4162 break;
4165 case Token::IN: 4163 case Token::IN:
4166 case Token::INSTANCEOF: 4164 case Token::INSTANCEOF:
4167 default: 4165 default:
4168 UNREACHABLE(); 4166 UNREACHABLE();
4169 } 4167 }
4170 4168
4171 bool inline_smi_code = ShouldInlineSmiCase(op); 4169 bool inline_smi_code = ShouldInlineSmiCase(op);
4172 JumpPatchSite patch_site(masm_); 4170 JumpPatchSite patch_site(masm_);
4173 if (inline_smi_code) { 4171 if (inline_smi_code) {
4174 NearLabel slow_case; 4172 Label slow_case;
4175 __ mov(ecx, Operand(edx)); 4173 __ mov(ecx, Operand(edx));
4176 __ or_(ecx, Operand(eax)); 4174 __ or_(ecx, Operand(eax));
4177 patch_site.EmitJumpIfNotSmi(ecx, &slow_case); 4175 patch_site.EmitJumpIfNotSmi(ecx, &slow_case, Label::kNear);
4178 __ cmp(edx, Operand(eax)); 4176 __ cmp(edx, Operand(eax));
4179 Split(cc, if_true, if_false, NULL); 4177 Split(cc, if_true, if_false, NULL);
4180 __ bind(&slow_case); 4178 __ bind(&slow_case);
4181 } 4179 }
4182 4180
4183 // Record position and call the compare IC. 4181 // Record position and call the compare IC.
4184 SetSourcePosition(expr->position()); 4182 SetSourcePosition(expr->position());
4185 Handle<Code> ic = CompareIC::GetUninitialized(op); 4183 Handle<Code> ic = CompareIC::GetUninitialized(op);
4186 EmitCallIC(ic, &patch_site, expr->id()); 4184 EmitCallIC(ic, &patch_site, expr->id());
4187 4185
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
4335 // And return. 4333 // And return.
4336 __ ret(0); 4334 __ ret(0);
4337 } 4335 }
4338 4336
4339 4337
4340 #undef __ 4338 #undef __
4341 4339
4342 } } // namespace v8::internal 4340 } } // namespace v8::internal
4343 4341
4344 #endif // V8_TARGET_ARCH_IA32 4342 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/frames-ia32.h ('k') | src/ia32/ic-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698