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

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

Issue 8386037: Remove the forward-bailout stack from the non-optimizing compiler. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 9 years, 1 month 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/hydrogen.cc ('k') | src/mips/full-codegen-mips.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 366 matching lines...) Expand 10 before | Expand all | Expand 10 after
377 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); 377 ASSERT(var->IsStackAllocated() || var->IsContextSlot());
378 MemOperand operand = codegen()->VarOperand(var, result_register()); 378 MemOperand operand = codegen()->VarOperand(var, result_register());
379 // Memory operands can be pushed directly. 379 // Memory operands can be pushed directly.
380 __ push(operand); 380 __ push(operand);
381 } 381 }
382 382
383 383
384 void FullCodeGenerator::TestContext::Plug(Variable* var) const { 384 void FullCodeGenerator::TestContext::Plug(Variable* var) const {
385 // For simplicity we always test the accumulator register. 385 // For simplicity we always test the accumulator register.
386 codegen()->GetVar(result_register(), var); 386 codegen()->GetVar(result_register(), var);
387 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); 387 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
388 codegen()->DoTest(this); 388 codegen()->DoTest(this);
389 } 389 }
390 390
391 391
392 void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const { 392 void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const {
393 UNREACHABLE(); // Not used on IA32. 393 UNREACHABLE(); // Not used on IA32.
394 } 394 }
395 395
396 396
397 void FullCodeGenerator::AccumulatorValueContext::Plug( 397 void FullCodeGenerator::AccumulatorValueContext::Plug(
(...skipping 30 matching lines...) Expand all
428 void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const { 428 void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const {
429 if (lit->IsSmi()) { 429 if (lit->IsSmi()) {
430 __ SafePush(Immediate(lit)); 430 __ SafePush(Immediate(lit));
431 } else { 431 } else {
432 __ push(Immediate(lit)); 432 __ push(Immediate(lit));
433 } 433 }
434 } 434 }
435 435
436 436
437 void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const { 437 void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const {
438 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, 438 codegen()->PrepareForBailoutBeforeSplit(condition(),
439 true, 439 true,
440 true_label_, 440 true_label_,
441 false_label_); 441 false_label_);
442 ASSERT(!lit->IsUndetectableObject()); // There are no undetectable literals. 442 ASSERT(!lit->IsUndetectableObject()); // There are no undetectable literals.
443 if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) { 443 if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) {
444 if (false_label_ != fall_through_) __ jmp(false_label_); 444 if (false_label_ != fall_through_) __ jmp(false_label_);
445 } else if (lit->IsTrue() || lit->IsJSObject()) { 445 } else if (lit->IsTrue() || lit->IsJSObject()) {
446 if (true_label_ != fall_through_) __ jmp(true_label_); 446 if (true_label_ != fall_through_) __ jmp(true_label_);
447 } else if (lit->IsString()) { 447 } else if (lit->IsString()) {
448 if (String::cast(*lit)->length() == 0) { 448 if (String::cast(*lit)->length() == 0) {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
487 __ mov(Operand(esp, 0), reg); 487 __ mov(Operand(esp, 0), reg);
488 } 488 }
489 489
490 490
491 void FullCodeGenerator::TestContext::DropAndPlug(int count, 491 void FullCodeGenerator::TestContext::DropAndPlug(int count,
492 Register reg) const { 492 Register reg) const {
493 ASSERT(count > 0); 493 ASSERT(count > 0);
494 // For simplicity we always test the accumulator register. 494 // For simplicity we always test the accumulator register.
495 __ Drop(count); 495 __ Drop(count);
496 __ Move(result_register(), reg); 496 __ Move(result_register(), reg);
497 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); 497 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
498 codegen()->DoTest(this); 498 codegen()->DoTest(this);
499 } 499 }
500 500
501 501
502 void FullCodeGenerator::EffectContext::Plug(Label* materialize_true, 502 void FullCodeGenerator::EffectContext::Plug(Label* materialize_true,
503 Label* materialize_false) const { 503 Label* materialize_false) const {
504 ASSERT(materialize_true == materialize_false); 504 ASSERT(materialize_true == materialize_false);
505 __ bind(materialize_true); 505 __ bind(materialize_true);
506 } 506 }
507 507
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
553 553
554 void FullCodeGenerator::StackValueContext::Plug(bool flag) const { 554 void FullCodeGenerator::StackValueContext::Plug(bool flag) const {
555 Handle<Object> value = flag 555 Handle<Object> value = flag
556 ? isolate()->factory()->true_value() 556 ? isolate()->factory()->true_value()
557 : isolate()->factory()->false_value(); 557 : isolate()->factory()->false_value();
558 __ push(Immediate(value)); 558 __ push(Immediate(value));
559 } 559 }
560 560
561 561
562 void FullCodeGenerator::TestContext::Plug(bool flag) const { 562 void FullCodeGenerator::TestContext::Plug(bool flag) const {
563 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, 563 codegen()->PrepareForBailoutBeforeSplit(condition(),
564 true, 564 true,
565 true_label_, 565 true_label_,
566 false_label_); 566 false_label_);
567 if (flag) { 567 if (flag) {
568 if (true_label_ != fall_through_) __ jmp(true_label_); 568 if (true_label_ != fall_through_) __ jmp(true_label_);
569 } else { 569 } else {
570 if (false_label_ != fall_through_) __ jmp(false_label_); 570 if (false_label_ != fall_through_) __ jmp(false_label_);
571 } 571 }
572 } 572 }
573 573
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
646 646
647 // Emit the write barrier code if the location is in the heap. 647 // Emit the write barrier code if the location is in the heap.
648 if (var->IsContextSlot()) { 648 if (var->IsContextSlot()) {
649 int offset = Context::SlotOffset(var->index()); 649 int offset = Context::SlotOffset(var->index());
650 ASSERT(!scratch0.is(esi) && !src.is(esi) && !scratch1.is(esi)); 650 ASSERT(!scratch0.is(esi) && !src.is(esi) && !scratch1.is(esi));
651 __ RecordWriteContextSlot(scratch0, offset, src, scratch1, kDontSaveFPRegs); 651 __ RecordWriteContextSlot(scratch0, offset, src, scratch1, kDontSaveFPRegs);
652 } 652 }
653 } 653 }
654 654
655 655
656 void FullCodeGenerator::PrepareForBailoutBeforeSplit(State state, 656 void FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr,
657 bool should_normalize, 657 bool should_normalize,
658 Label* if_true, 658 Label* if_true,
659 Label* if_false) { 659 Label* if_false) {
660 // Only prepare for bailouts before splits if we're in a test 660 // Only prepare for bailouts before splits if we're in a test
661 // context. Otherwise, we let the Visit function deal with the 661 // context. Otherwise, we let the Visit function deal with the
662 // preparation to avoid preparing with the same AST id twice. 662 // preparation to avoid preparing with the same AST id twice.
663 if (!context()->IsTest() || !info_->IsOptimizable()) return; 663 if (!context()->IsTest() || !info_->IsOptimizable()) return;
664 664
665 Label skip; 665 Label skip;
666 if (should_normalize) __ jmp(&skip, Label::kNear); 666 if (should_normalize) __ jmp(&skip, Label::kNear);
667 667 PrepareForBailout(expr, TOS_REG);
668 ForwardBailoutStack* current = forward_bailout_stack_;
669 while (current != NULL) {
670 PrepareForBailout(current->expr(), state);
671 current = current->parent();
672 }
673
674 if (should_normalize) { 668 if (should_normalize) {
675 __ cmp(eax, isolate()->factory()->true_value()); 669 __ cmp(eax, isolate()->factory()->true_value());
676 Split(equal, if_true, if_false, NULL); 670 Split(equal, if_true, if_false, NULL);
677 __ bind(&skip); 671 __ bind(&skip);
678 } 672 }
679 } 673 }
680 674
681 675
682 void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy, 676 void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy,
683 VariableMode mode, 677 VariableMode mode,
(...skipping 1579 matching lines...) Expand 10 before | Expand all | Expand 10 after
2263 __ SafeSet(eax, Immediate(arg_count)); 2257 __ SafeSet(eax, Immediate(arg_count));
2264 __ mov(edi, Operand(esp, arg_count * kPointerSize)); 2258 __ mov(edi, Operand(esp, arg_count * kPointerSize));
2265 2259
2266 Handle<Code> construct_builtin = 2260 Handle<Code> construct_builtin =
2267 isolate()->builtins()->JSConstructCall(); 2261 isolate()->builtins()->JSConstructCall();
2268 __ call(construct_builtin, RelocInfo::CONSTRUCT_CALL); 2262 __ call(construct_builtin, RelocInfo::CONSTRUCT_CALL);
2269 context()->Plug(eax); 2263 context()->Plug(eax);
2270 } 2264 }
2271 2265
2272 2266
2273 void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) { 2267 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) {
2268 ZoneList<Expression*>* args = expr->arguments();
2274 ASSERT(args->length() == 1); 2269 ASSERT(args->length() == 1);
2275 2270
2276 VisitForAccumulatorValue(args->at(0)); 2271 VisitForAccumulatorValue(args->at(0));
2277 2272
2278 Label materialize_true, materialize_false; 2273 Label materialize_true, materialize_false;
2279 Label* if_true = NULL; 2274 Label* if_true = NULL;
2280 Label* if_false = NULL; 2275 Label* if_false = NULL;
2281 Label* fall_through = NULL; 2276 Label* fall_through = NULL;
2282 context()->PrepareTest(&materialize_true, &materialize_false, 2277 context()->PrepareTest(&materialize_true, &materialize_false,
2283 &if_true, &if_false, &fall_through); 2278 &if_true, &if_false, &fall_through);
2284 2279
2285 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 2280 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2286 __ test(eax, Immediate(kSmiTagMask)); 2281 __ test(eax, Immediate(kSmiTagMask));
2287 Split(zero, if_true, if_false, fall_through); 2282 Split(zero, if_true, if_false, fall_through);
2288 2283
2289 context()->Plug(if_true, if_false); 2284 context()->Plug(if_true, if_false);
2290 } 2285 }
2291 2286
2292 2287
2293 void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) { 2288 void FullCodeGenerator::EmitIsNonNegativeSmi(CallRuntime* expr) {
2289 ZoneList<Expression*>* args = expr->arguments();
2294 ASSERT(args->length() == 1); 2290 ASSERT(args->length() == 1);
2295 2291
2296 VisitForAccumulatorValue(args->at(0)); 2292 VisitForAccumulatorValue(args->at(0));
2297 2293
2298 Label materialize_true, materialize_false; 2294 Label materialize_true, materialize_false;
2299 Label* if_true = NULL; 2295 Label* if_true = NULL;
2300 Label* if_false = NULL; 2296 Label* if_false = NULL;
2301 Label* fall_through = NULL; 2297 Label* fall_through = NULL;
2302 context()->PrepareTest(&materialize_true, &materialize_false, 2298 context()->PrepareTest(&materialize_true, &materialize_false,
2303 &if_true, &if_false, &fall_through); 2299 &if_true, &if_false, &fall_through);
2304 2300
2305 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 2301 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2306 __ test(eax, Immediate(kSmiTagMask | 0x80000000)); 2302 __ test(eax, Immediate(kSmiTagMask | 0x80000000));
2307 Split(zero, if_true, if_false, fall_through); 2303 Split(zero, if_true, if_false, fall_through);
2308 2304
2309 context()->Plug(if_true, if_false); 2305 context()->Plug(if_true, if_false);
2310 } 2306 }
2311 2307
2312 2308
2313 void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) { 2309 void FullCodeGenerator::EmitIsObject(CallRuntime* expr) {
2310 ZoneList<Expression*>* args = expr->arguments();
2314 ASSERT(args->length() == 1); 2311 ASSERT(args->length() == 1);
2315 2312
2316 VisitForAccumulatorValue(args->at(0)); 2313 VisitForAccumulatorValue(args->at(0));
2317 2314
2318 Label materialize_true, materialize_false; 2315 Label materialize_true, materialize_false;
2319 Label* if_true = NULL; 2316 Label* if_true = NULL;
2320 Label* if_false = NULL; 2317 Label* if_false = NULL;
2321 Label* fall_through = NULL; 2318 Label* fall_through = NULL;
2322 context()->PrepareTest(&materialize_true, &materialize_false, 2319 context()->PrepareTest(&materialize_true, &materialize_false,
2323 &if_true, &if_false, &fall_through); 2320 &if_true, &if_false, &fall_through);
2324 2321
2325 __ JumpIfSmi(eax, if_false); 2322 __ JumpIfSmi(eax, if_false);
2326 __ cmp(eax, isolate()->factory()->null_value()); 2323 __ cmp(eax, isolate()->factory()->null_value());
2327 __ j(equal, if_true); 2324 __ j(equal, if_true);
2328 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); 2325 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
2329 // Undetectable objects behave like undefined when tested with typeof. 2326 // Undetectable objects behave like undefined when tested with typeof.
2330 __ movzx_b(ecx, FieldOperand(ebx, Map::kBitFieldOffset)); 2327 __ movzx_b(ecx, FieldOperand(ebx, Map::kBitFieldOffset));
2331 __ test(ecx, Immediate(1 << Map::kIsUndetectable)); 2328 __ test(ecx, Immediate(1 << Map::kIsUndetectable));
2332 __ j(not_zero, if_false); 2329 __ j(not_zero, if_false);
2333 __ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceTypeOffset)); 2330 __ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceTypeOffset));
2334 __ cmp(ecx, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE); 2331 __ cmp(ecx, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE);
2335 __ j(below, if_false); 2332 __ j(below, if_false);
2336 __ cmp(ecx, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); 2333 __ cmp(ecx, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
2337 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 2334 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2338 Split(below_equal, if_true, if_false, fall_through); 2335 Split(below_equal, if_true, if_false, fall_through);
2339 2336
2340 context()->Plug(if_true, if_false); 2337 context()->Plug(if_true, if_false);
2341 } 2338 }
2342 2339
2343 2340
2344 void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) { 2341 void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) {
2342 ZoneList<Expression*>* args = expr->arguments();
2345 ASSERT(args->length() == 1); 2343 ASSERT(args->length() == 1);
2346 2344
2347 VisitForAccumulatorValue(args->at(0)); 2345 VisitForAccumulatorValue(args->at(0));
2348 2346
2349 Label materialize_true, materialize_false; 2347 Label materialize_true, materialize_false;
2350 Label* if_true = NULL; 2348 Label* if_true = NULL;
2351 Label* if_false = NULL; 2349 Label* if_false = NULL;
2352 Label* fall_through = NULL; 2350 Label* fall_through = NULL;
2353 context()->PrepareTest(&materialize_true, &materialize_false, 2351 context()->PrepareTest(&materialize_true, &materialize_false,
2354 &if_true, &if_false, &fall_through); 2352 &if_true, &if_false, &fall_through);
2355 2353
2356 __ JumpIfSmi(eax, if_false); 2354 __ JumpIfSmi(eax, if_false);
2357 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ebx); 2355 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ebx);
2358 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 2356 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2359 Split(above_equal, if_true, if_false, fall_through); 2357 Split(above_equal, if_true, if_false, fall_through);
2360 2358
2361 context()->Plug(if_true, if_false); 2359 context()->Plug(if_true, if_false);
2362 } 2360 }
2363 2361
2364 2362
2365 void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) { 2363 void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) {
2364 ZoneList<Expression*>* args = expr->arguments();
2366 ASSERT(args->length() == 1); 2365 ASSERT(args->length() == 1);
2367 2366
2368 VisitForAccumulatorValue(args->at(0)); 2367 VisitForAccumulatorValue(args->at(0));
2369 2368
2370 Label materialize_true, materialize_false; 2369 Label materialize_true, materialize_false;
2371 Label* if_true = NULL; 2370 Label* if_true = NULL;
2372 Label* if_false = NULL; 2371 Label* if_false = NULL;
2373 Label* fall_through = NULL; 2372 Label* fall_through = NULL;
2374 context()->PrepareTest(&materialize_true, &materialize_false, 2373 context()->PrepareTest(&materialize_true, &materialize_false,
2375 &if_true, &if_false, &fall_through); 2374 &if_true, &if_false, &fall_through);
2376 2375
2377 __ JumpIfSmi(eax, if_false); 2376 __ JumpIfSmi(eax, if_false);
2378 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); 2377 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
2379 __ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset)); 2378 __ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset));
2380 __ test(ebx, Immediate(1 << Map::kIsUndetectable)); 2379 __ test(ebx, Immediate(1 << Map::kIsUndetectable));
2381 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 2380 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2382 Split(not_zero, if_true, if_false, fall_through); 2381 Split(not_zero, if_true, if_false, fall_through);
2383 2382
2384 context()->Plug(if_true, if_false); 2383 context()->Plug(if_true, if_false);
2385 } 2384 }
2386 2385
2387 2386
2388 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( 2387 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
2389 ZoneList<Expression*>* args) { 2388 CallRuntime* expr) {
2389 ZoneList<Expression*>* args = expr->arguments();
2390 ASSERT(args->length() == 1); 2390 ASSERT(args->length() == 1);
2391 2391
2392 VisitForAccumulatorValue(args->at(0)); 2392 VisitForAccumulatorValue(args->at(0));
2393 2393
2394 Label materialize_true, materialize_false; 2394 Label materialize_true, materialize_false;
2395 Label* if_true = NULL; 2395 Label* if_true = NULL;
2396 Label* if_false = NULL; 2396 Label* if_false = NULL;
2397 Label* fall_through = NULL; 2397 Label* fall_through = NULL;
2398 context()->PrepareTest(&materialize_true, &materialize_false, 2398 context()->PrepareTest(&materialize_true, &materialize_false,
2399 &if_true, &if_false, &fall_through); 2399 &if_true, &if_false, &fall_through);
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
2456 __ cmp(ecx, 2456 __ cmp(ecx,
2457 ContextOperand(edx, 2457 ContextOperand(edx,
2458 Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX)); 2458 Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX));
2459 __ j(not_equal, if_false); 2459 __ j(not_equal, if_false);
2460 // Set the bit in the map to indicate that it has been checked safe for 2460 // Set the bit in the map to indicate that it has been checked safe for
2461 // default valueOf and set true result. 2461 // default valueOf and set true result.
2462 __ or_(FieldOperand(ebx, Map::kBitField2Offset), 2462 __ or_(FieldOperand(ebx, Map::kBitField2Offset),
2463 Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf)); 2463 Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf));
2464 __ jmp(if_true); 2464 __ jmp(if_true);
2465 2465
2466 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 2466 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2467 context()->Plug(if_true, if_false); 2467 context()->Plug(if_true, if_false);
2468 } 2468 }
2469 2469
2470 2470
2471 void FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) { 2471 void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) {
2472 ZoneList<Expression*>* args = expr->arguments();
2472 ASSERT(args->length() == 1); 2473 ASSERT(args->length() == 1);
2473 2474
2474 VisitForAccumulatorValue(args->at(0)); 2475 VisitForAccumulatorValue(args->at(0));
2475 2476
2476 Label materialize_true, materialize_false; 2477 Label materialize_true, materialize_false;
2477 Label* if_true = NULL; 2478 Label* if_true = NULL;
2478 Label* if_false = NULL; 2479 Label* if_false = NULL;
2479 Label* fall_through = NULL; 2480 Label* fall_through = NULL;
2480 context()->PrepareTest(&materialize_true, &materialize_false, 2481 context()->PrepareTest(&materialize_true, &materialize_false,
2481 &if_true, &if_false, &fall_through); 2482 &if_true, &if_false, &fall_through);
2482 2483
2483 __ JumpIfSmi(eax, if_false); 2484 __ JumpIfSmi(eax, if_false);
2484 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); 2485 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx);
2485 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 2486 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2486 Split(equal, if_true, if_false, fall_through); 2487 Split(equal, if_true, if_false, fall_through);
2487 2488
2488 context()->Plug(if_true, if_false); 2489 context()->Plug(if_true, if_false);
2489 } 2490 }
2490 2491
2491 2492
2492 void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) { 2493 void FullCodeGenerator::EmitIsArray(CallRuntime* expr) {
2494 ZoneList<Expression*>* args = expr->arguments();
2493 ASSERT(args->length() == 1); 2495 ASSERT(args->length() == 1);
2494 2496
2495 VisitForAccumulatorValue(args->at(0)); 2497 VisitForAccumulatorValue(args->at(0));
2496 2498
2497 Label materialize_true, materialize_false; 2499 Label materialize_true, materialize_false;
2498 Label* if_true = NULL; 2500 Label* if_true = NULL;
2499 Label* if_false = NULL; 2501 Label* if_false = NULL;
2500 Label* fall_through = NULL; 2502 Label* fall_through = NULL;
2501 context()->PrepareTest(&materialize_true, &materialize_false, 2503 context()->PrepareTest(&materialize_true, &materialize_false,
2502 &if_true, &if_false, &fall_through); 2504 &if_true, &if_false, &fall_through);
2503 2505
2504 __ JumpIfSmi(eax, if_false); 2506 __ JumpIfSmi(eax, if_false);
2505 __ CmpObjectType(eax, JS_ARRAY_TYPE, ebx); 2507 __ CmpObjectType(eax, JS_ARRAY_TYPE, ebx);
2506 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 2508 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2507 Split(equal, if_true, if_false, fall_through); 2509 Split(equal, if_true, if_false, fall_through);
2508 2510
2509 context()->Plug(if_true, if_false); 2511 context()->Plug(if_true, if_false);
2510 } 2512 }
2511 2513
2512 2514
2513 void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) { 2515 void FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) {
2516 ZoneList<Expression*>* args = expr->arguments();
2514 ASSERT(args->length() == 1); 2517 ASSERT(args->length() == 1);
2515 2518
2516 VisitForAccumulatorValue(args->at(0)); 2519 VisitForAccumulatorValue(args->at(0));
2517 2520
2518 Label materialize_true, materialize_false; 2521 Label materialize_true, materialize_false;
2519 Label* if_true = NULL; 2522 Label* if_true = NULL;
2520 Label* if_false = NULL; 2523 Label* if_false = NULL;
2521 Label* fall_through = NULL; 2524 Label* fall_through = NULL;
2522 context()->PrepareTest(&materialize_true, &materialize_false, 2525 context()->PrepareTest(&materialize_true, &materialize_false,
2523 &if_true, &if_false, &fall_through); 2526 &if_true, &if_false, &fall_through);
2524 2527
2525 __ JumpIfSmi(eax, if_false); 2528 __ JumpIfSmi(eax, if_false);
2526 __ CmpObjectType(eax, JS_REGEXP_TYPE, ebx); 2529 __ CmpObjectType(eax, JS_REGEXP_TYPE, ebx);
2527 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 2530 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2528 Split(equal, if_true, if_false, fall_through); 2531 Split(equal, if_true, if_false, fall_through);
2529 2532
2530 context()->Plug(if_true, if_false); 2533 context()->Plug(if_true, if_false);
2531 } 2534 }
2532 2535
2533 2536
2534 2537
2535 void FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) { 2538 void FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) {
2536 ASSERT(args->length() == 0); 2539 ASSERT(expr->arguments()->length() == 0);
2537 2540
2538 Label materialize_true, materialize_false; 2541 Label materialize_true, materialize_false;
2539 Label* if_true = NULL; 2542 Label* if_true = NULL;
2540 Label* if_false = NULL; 2543 Label* if_false = NULL;
2541 Label* fall_through = NULL; 2544 Label* fall_through = NULL;
2542 context()->PrepareTest(&materialize_true, &materialize_false, 2545 context()->PrepareTest(&materialize_true, &materialize_false,
2543 &if_true, &if_false, &fall_through); 2546 &if_true, &if_false, &fall_through);
2544 2547
2545 // Get the frame pointer for the calling frame. 2548 // Get the frame pointer for the calling frame.
2546 __ mov(eax, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); 2549 __ mov(eax, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
2547 2550
2548 // Skip the arguments adaptor frame if it exists. 2551 // Skip the arguments adaptor frame if it exists.
2549 Label check_frame_marker; 2552 Label check_frame_marker;
2550 __ cmp(Operand(eax, StandardFrameConstants::kContextOffset), 2553 __ cmp(Operand(eax, StandardFrameConstants::kContextOffset),
2551 Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 2554 Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
2552 __ j(not_equal, &check_frame_marker); 2555 __ j(not_equal, &check_frame_marker);
2553 __ mov(eax, Operand(eax, StandardFrameConstants::kCallerFPOffset)); 2556 __ mov(eax, Operand(eax, StandardFrameConstants::kCallerFPOffset));
2554 2557
2555 // Check the marker in the calling frame. 2558 // Check the marker in the calling frame.
2556 __ bind(&check_frame_marker); 2559 __ bind(&check_frame_marker);
2557 __ cmp(Operand(eax, StandardFrameConstants::kMarkerOffset), 2560 __ cmp(Operand(eax, StandardFrameConstants::kMarkerOffset),
2558 Immediate(Smi::FromInt(StackFrame::CONSTRUCT))); 2561 Immediate(Smi::FromInt(StackFrame::CONSTRUCT)));
2559 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 2562 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2560 Split(equal, if_true, if_false, fall_through); 2563 Split(equal, if_true, if_false, fall_through);
2561 2564
2562 context()->Plug(if_true, if_false); 2565 context()->Plug(if_true, if_false);
2563 } 2566 }
2564 2567
2565 2568
2566 void FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) { 2569 void FullCodeGenerator::EmitObjectEquals(CallRuntime* expr) {
2570 ZoneList<Expression*>* args = expr->arguments();
2567 ASSERT(args->length() == 2); 2571 ASSERT(args->length() == 2);
2568 2572
2569 // Load the two objects into registers and perform the comparison. 2573 // Load the two objects into registers and perform the comparison.
2570 VisitForStackValue(args->at(0)); 2574 VisitForStackValue(args->at(0));
2571 VisitForAccumulatorValue(args->at(1)); 2575 VisitForAccumulatorValue(args->at(1));
2572 2576
2573 Label materialize_true, materialize_false; 2577 Label materialize_true, materialize_false;
2574 Label* if_true = NULL; 2578 Label* if_true = NULL;
2575 Label* if_false = NULL; 2579 Label* if_false = NULL;
2576 Label* fall_through = NULL; 2580 Label* fall_through = NULL;
2577 context()->PrepareTest(&materialize_true, &materialize_false, 2581 context()->PrepareTest(&materialize_true, &materialize_false,
2578 &if_true, &if_false, &fall_through); 2582 &if_true, &if_false, &fall_through);
2579 2583
2580 __ pop(ebx); 2584 __ pop(ebx);
2581 __ cmp(eax, ebx); 2585 __ cmp(eax, ebx);
2582 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 2586 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2583 Split(equal, if_true, if_false, fall_through); 2587 Split(equal, if_true, if_false, fall_through);
2584 2588
2585 context()->Plug(if_true, if_false); 2589 context()->Plug(if_true, if_false);
2586 } 2590 }
2587 2591
2588 2592
2589 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) { 2593 void FullCodeGenerator::EmitArguments(CallRuntime* expr) {
2594 ZoneList<Expression*>* args = expr->arguments();
2590 ASSERT(args->length() == 1); 2595 ASSERT(args->length() == 1);
2591 2596
2592 // ArgumentsAccessStub expects the key in edx and the formal 2597 // ArgumentsAccessStub expects the key in edx and the formal
2593 // parameter count in eax. 2598 // parameter count in eax.
2594 VisitForAccumulatorValue(args->at(0)); 2599 VisitForAccumulatorValue(args->at(0));
2595 __ mov(edx, eax); 2600 __ mov(edx, eax);
2596 __ SafeSet(eax, Immediate(Smi::FromInt(info_->scope()->num_parameters()))); 2601 __ SafeSet(eax, Immediate(Smi::FromInt(info_->scope()->num_parameters())));
2597 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); 2602 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
2598 __ CallStub(&stub); 2603 __ CallStub(&stub);
2599 context()->Plug(eax); 2604 context()->Plug(eax);
2600 } 2605 }
2601 2606
2602 2607
2603 void FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) { 2608 void FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) {
2604 ASSERT(args->length() == 0); 2609 ASSERT(expr->arguments()->length() == 0);
2605 2610
2606 Label exit; 2611 Label exit;
2607 // Get the number of formal parameters. 2612 // Get the number of formal parameters.
2608 __ SafeSet(eax, Immediate(Smi::FromInt(info_->scope()->num_parameters()))); 2613 __ SafeSet(eax, Immediate(Smi::FromInt(info_->scope()->num_parameters())));
2609 2614
2610 // Check if the calling frame is an arguments adaptor frame. 2615 // Check if the calling frame is an arguments adaptor frame.
2611 __ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); 2616 __ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
2612 __ cmp(Operand(ebx, StandardFrameConstants::kContextOffset), 2617 __ cmp(Operand(ebx, StandardFrameConstants::kContextOffset),
2613 Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 2618 Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
2614 __ j(not_equal, &exit); 2619 __ j(not_equal, &exit);
2615 2620
2616 // Arguments adaptor case: Read the arguments length from the 2621 // Arguments adaptor case: Read the arguments length from the
2617 // adaptor frame. 2622 // adaptor frame.
2618 __ mov(eax, Operand(ebx, ArgumentsAdaptorFrameConstants::kLengthOffset)); 2623 __ mov(eax, Operand(ebx, ArgumentsAdaptorFrameConstants::kLengthOffset));
2619 2624
2620 __ bind(&exit); 2625 __ bind(&exit);
2621 if (FLAG_debug_code) __ AbortIfNotSmi(eax); 2626 if (FLAG_debug_code) __ AbortIfNotSmi(eax);
2622 context()->Plug(eax); 2627 context()->Plug(eax);
2623 } 2628 }
2624 2629
2625 2630
2626 void FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) { 2631 void FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
2632 ZoneList<Expression*>* args = expr->arguments();
2627 ASSERT(args->length() == 1); 2633 ASSERT(args->length() == 1);
2628 Label done, null, function, non_function_constructor; 2634 Label done, null, function, non_function_constructor;
2629 2635
2630 VisitForAccumulatorValue(args->at(0)); 2636 VisitForAccumulatorValue(args->at(0));
2631 2637
2632 // If the object is a smi, we return null. 2638 // If the object is a smi, we return null.
2633 __ JumpIfSmi(eax, &null); 2639 __ JumpIfSmi(eax, &null);
2634 2640
2635 // Check that the object is a JS object but take special care of JS 2641 // Check that the object is a JS object but take special care of JS
2636 // functions to make sure they have 'Function' as their class. 2642 // functions to make sure they have 'Function' as their class.
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
2676 __ bind(&null); 2682 __ bind(&null);
2677 __ mov(eax, isolate()->factory()->null_value()); 2683 __ mov(eax, isolate()->factory()->null_value());
2678 2684
2679 // All done. 2685 // All done.
2680 __ bind(&done); 2686 __ bind(&done);
2681 2687
2682 context()->Plug(eax); 2688 context()->Plug(eax);
2683 } 2689 }
2684 2690
2685 2691
2686 void FullCodeGenerator::EmitLog(ZoneList<Expression*>* args) { 2692 void FullCodeGenerator::EmitLog(CallRuntime* expr) {
2687 // Conditionally generate a log call. 2693 // Conditionally generate a log call.
2688 // Args: 2694 // Args:
2689 // 0 (literal string): The type of logging (corresponds to the flags). 2695 // 0 (literal string): The type of logging (corresponds to the flags).
2690 // This is used to determine whether or not to generate the log call. 2696 // This is used to determine whether or not to generate the log call.
2691 // 1 (string): Format string. Access the string at argument index 2 2697 // 1 (string): Format string. Access the string at argument index 2
2692 // with '%2s' (see Logger::LogRuntime for all the formats). 2698 // with '%2s' (see Logger::LogRuntime for all the formats).
2693 // 2 (array): Arguments to the format string. 2699 // 2 (array): Arguments to the format string.
2700 ZoneList<Expression*>* args = expr->arguments();
2694 ASSERT_EQ(args->length(), 3); 2701 ASSERT_EQ(args->length(), 3);
2695 if (CodeGenerator::ShouldGenerateLog(args->at(0))) { 2702 if (CodeGenerator::ShouldGenerateLog(args->at(0))) {
2696 VisitForStackValue(args->at(1)); 2703 VisitForStackValue(args->at(1));
2697 VisitForStackValue(args->at(2)); 2704 VisitForStackValue(args->at(2));
2698 __ CallRuntime(Runtime::kLog, 2); 2705 __ CallRuntime(Runtime::kLog, 2);
2699 } 2706 }
2700 // Finally, we're expected to leave a value on the top of the stack. 2707 // Finally, we're expected to leave a value on the top of the stack.
2701 __ mov(eax, isolate()->factory()->undefined_value()); 2708 __ mov(eax, isolate()->factory()->undefined_value());
2702 context()->Plug(eax); 2709 context()->Plug(eax);
2703 } 2710 }
2704 2711
2705 2712
2706 void FullCodeGenerator::EmitRandomHeapNumber(ZoneList<Expression*>* args) { 2713 void FullCodeGenerator::EmitRandomHeapNumber(CallRuntime* expr) {
2707 ASSERT(args->length() == 0); 2714 ASSERT(expr->arguments()->length() == 0);
2708 2715
2709 Label slow_allocate_heapnumber; 2716 Label slow_allocate_heapnumber;
2710 Label heapnumber_allocated; 2717 Label heapnumber_allocated;
2711 2718
2712 __ AllocateHeapNumber(edi, ebx, ecx, &slow_allocate_heapnumber); 2719 __ AllocateHeapNumber(edi, ebx, ecx, &slow_allocate_heapnumber);
2713 __ jmp(&heapnumber_allocated); 2720 __ jmp(&heapnumber_allocated);
2714 2721
2715 __ bind(&slow_allocate_heapnumber); 2722 __ bind(&slow_allocate_heapnumber);
2716 // Allocate a heap number. 2723 // Allocate a heap number.
2717 __ CallRuntime(Runtime::kNumberAlloc, 0); 2724 __ CallRuntime(Runtime::kNumberAlloc, 0);
(...skipping 29 matching lines...) Expand all
2747 __ mov(FieldOperand(edi, HeapNumber::kMantissaOffset), Immediate(0)); 2754 __ mov(FieldOperand(edi, HeapNumber::kMantissaOffset), Immediate(0));
2748 __ fld_d(FieldOperand(edi, HeapNumber::kValueOffset)); 2755 __ fld_d(FieldOperand(edi, HeapNumber::kValueOffset));
2749 __ fsubp(1); 2756 __ fsubp(1);
2750 __ fstp_d(FieldOperand(edi, HeapNumber::kValueOffset)); 2757 __ fstp_d(FieldOperand(edi, HeapNumber::kValueOffset));
2751 } 2758 }
2752 __ mov(eax, edi); 2759 __ mov(eax, edi);
2753 context()->Plug(eax); 2760 context()->Plug(eax);
2754 } 2761 }
2755 2762
2756 2763
2757 void FullCodeGenerator::EmitSubString(ZoneList<Expression*>* args) { 2764 void FullCodeGenerator::EmitSubString(CallRuntime* expr) {
2758 // Load the arguments on the stack and call the stub. 2765 // Load the arguments on the stack and call the stub.
2759 SubStringStub stub; 2766 SubStringStub stub;
2767 ZoneList<Expression*>* args = expr->arguments();
2760 ASSERT(args->length() == 3); 2768 ASSERT(args->length() == 3);
2761 VisitForStackValue(args->at(0)); 2769 VisitForStackValue(args->at(0));
2762 VisitForStackValue(args->at(1)); 2770 VisitForStackValue(args->at(1));
2763 VisitForStackValue(args->at(2)); 2771 VisitForStackValue(args->at(2));
2764 __ CallStub(&stub); 2772 __ CallStub(&stub);
2765 context()->Plug(eax); 2773 context()->Plug(eax);
2766 } 2774 }
2767 2775
2768 2776
2769 void FullCodeGenerator::EmitRegExpExec(ZoneList<Expression*>* args) { 2777 void FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) {
2770 // Load the arguments on the stack and call the stub. 2778 // Load the arguments on the stack and call the stub.
2771 RegExpExecStub stub; 2779 RegExpExecStub stub;
2780 ZoneList<Expression*>* args = expr->arguments();
2772 ASSERT(args->length() == 4); 2781 ASSERT(args->length() == 4);
2773 VisitForStackValue(args->at(0)); 2782 VisitForStackValue(args->at(0));
2774 VisitForStackValue(args->at(1)); 2783 VisitForStackValue(args->at(1));
2775 VisitForStackValue(args->at(2)); 2784 VisitForStackValue(args->at(2));
2776 VisitForStackValue(args->at(3)); 2785 VisitForStackValue(args->at(3));
2777 __ CallStub(&stub); 2786 __ CallStub(&stub);
2778 context()->Plug(eax); 2787 context()->Plug(eax);
2779 } 2788 }
2780 2789
2781 2790
2782 void FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) { 2791 void FullCodeGenerator::EmitValueOf(CallRuntime* expr) {
2792 ZoneList<Expression*>* args = expr->arguments();
2783 ASSERT(args->length() == 1); 2793 ASSERT(args->length() == 1);
2784 2794
2785 VisitForAccumulatorValue(args->at(0)); // Load the object. 2795 VisitForAccumulatorValue(args->at(0)); // Load the object.
2786 2796
2787 Label done; 2797 Label done;
2788 // If the object is a smi return the object. 2798 // If the object is a smi return the object.
2789 __ JumpIfSmi(eax, &done, Label::kNear); 2799 __ JumpIfSmi(eax, &done, Label::kNear);
2790 // If the object is not a value type, return the object. 2800 // If the object is not a value type, return the object.
2791 __ CmpObjectType(eax, JS_VALUE_TYPE, ebx); 2801 __ CmpObjectType(eax, JS_VALUE_TYPE, ebx);
2792 __ j(not_equal, &done, Label::kNear); 2802 __ j(not_equal, &done, Label::kNear);
2793 __ mov(eax, FieldOperand(eax, JSValue::kValueOffset)); 2803 __ mov(eax, FieldOperand(eax, JSValue::kValueOffset));
2794 2804
2795 __ bind(&done); 2805 __ bind(&done);
2796 context()->Plug(eax); 2806 context()->Plug(eax);
2797 } 2807 }
2798 2808
2799 2809
2800 void FullCodeGenerator::EmitMathPow(ZoneList<Expression*>* args) { 2810 void FullCodeGenerator::EmitMathPow(CallRuntime* expr) {
2801 // Load the arguments on the stack and call the runtime function. 2811 // Load the arguments on the stack and call the runtime function.
2812 ZoneList<Expression*>* args = expr->arguments();
2802 ASSERT(args->length() == 2); 2813 ASSERT(args->length() == 2);
2803 VisitForStackValue(args->at(0)); 2814 VisitForStackValue(args->at(0));
2804 VisitForStackValue(args->at(1)); 2815 VisitForStackValue(args->at(1));
2805 2816
2806 if (CpuFeatures::IsSupported(SSE2)) { 2817 if (CpuFeatures::IsSupported(SSE2)) {
2807 MathPowStub stub; 2818 MathPowStub stub;
2808 __ CallStub(&stub); 2819 __ CallStub(&stub);
2809 } else { 2820 } else {
2810 __ CallRuntime(Runtime::kMath_pow, 2); 2821 __ CallRuntime(Runtime::kMath_pow, 2);
2811 } 2822 }
2812 context()->Plug(eax); 2823 context()->Plug(eax);
2813 } 2824 }
2814 2825
2815 2826
2816 void FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) { 2827 void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) {
2828 ZoneList<Expression*>* args = expr->arguments();
2817 ASSERT(args->length() == 2); 2829 ASSERT(args->length() == 2);
2818 2830
2819 VisitForStackValue(args->at(0)); // Load the object. 2831 VisitForStackValue(args->at(0)); // Load the object.
2820 VisitForAccumulatorValue(args->at(1)); // Load the value. 2832 VisitForAccumulatorValue(args->at(1)); // Load the value.
2821 __ pop(ebx); // eax = value. ebx = object. 2833 __ pop(ebx); // eax = value. ebx = object.
2822 2834
2823 Label done; 2835 Label done;
2824 // If the object is a smi, return the value. 2836 // If the object is a smi, return the value.
2825 __ JumpIfSmi(ebx, &done, Label::kNear); 2837 __ JumpIfSmi(ebx, &done, Label::kNear);
2826 2838
2827 // If the object is not a value type, return the value. 2839 // If the object is not a value type, return the value.
2828 __ CmpObjectType(ebx, JS_VALUE_TYPE, ecx); 2840 __ CmpObjectType(ebx, JS_VALUE_TYPE, ecx);
2829 __ j(not_equal, &done, Label::kNear); 2841 __ j(not_equal, &done, Label::kNear);
2830 2842
2831 // Store the value. 2843 // Store the value.
2832 __ mov(FieldOperand(ebx, JSValue::kValueOffset), eax); 2844 __ mov(FieldOperand(ebx, JSValue::kValueOffset), eax);
2833 2845
2834 // Update the write barrier. Save the value as it will be 2846 // Update the write barrier. Save the value as it will be
2835 // overwritten by the write barrier code and is needed afterward. 2847 // overwritten by the write barrier code and is needed afterward.
2836 __ mov(edx, eax); 2848 __ mov(edx, eax);
2837 __ RecordWriteField(ebx, JSValue::kValueOffset, edx, ecx, kDontSaveFPRegs); 2849 __ RecordWriteField(ebx, JSValue::kValueOffset, edx, ecx, kDontSaveFPRegs);
2838 2850
2839 __ bind(&done); 2851 __ bind(&done);
2840 context()->Plug(eax); 2852 context()->Plug(eax);
2841 } 2853 }
2842 2854
2843 2855
2844 void FullCodeGenerator::EmitNumberToString(ZoneList<Expression*>* args) { 2856 void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
2857 ZoneList<Expression*>* args = expr->arguments();
2845 ASSERT_EQ(args->length(), 1); 2858 ASSERT_EQ(args->length(), 1);
2846 2859
2847 // Load the argument on the stack and call the stub. 2860 // Load the argument on the stack and call the stub.
2848 VisitForStackValue(args->at(0)); 2861 VisitForStackValue(args->at(0));
2849 2862
2850 NumberToStringStub stub; 2863 NumberToStringStub stub;
2851 __ CallStub(&stub); 2864 __ CallStub(&stub);
2852 context()->Plug(eax); 2865 context()->Plug(eax);
2853 } 2866 }
2854 2867
2855 2868
2856 void FullCodeGenerator::EmitStringCharFromCode(ZoneList<Expression*>* args) { 2869 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
2870 ZoneList<Expression*>* args = expr->arguments();
2857 ASSERT(args->length() == 1); 2871 ASSERT(args->length() == 1);
2858 2872
2859 VisitForAccumulatorValue(args->at(0)); 2873 VisitForAccumulatorValue(args->at(0));
2860 2874
2861 Label done; 2875 Label done;
2862 StringCharFromCodeGenerator generator(eax, ebx); 2876 StringCharFromCodeGenerator generator(eax, ebx);
2863 generator.GenerateFast(masm_); 2877 generator.GenerateFast(masm_);
2864 __ jmp(&done); 2878 __ jmp(&done);
2865 2879
2866 NopRuntimeCallHelper call_helper; 2880 NopRuntimeCallHelper call_helper;
2867 generator.GenerateSlow(masm_, call_helper); 2881 generator.GenerateSlow(masm_, call_helper);
2868 2882
2869 __ bind(&done); 2883 __ bind(&done);
2870 context()->Plug(ebx); 2884 context()->Plug(ebx);
2871 } 2885 }
2872 2886
2873 2887
2874 void FullCodeGenerator::EmitStringCharCodeAt(ZoneList<Expression*>* args) { 2888 void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) {
2889 ZoneList<Expression*>* args = expr->arguments();
2875 ASSERT(args->length() == 2); 2890 ASSERT(args->length() == 2);
2876 2891
2877 VisitForStackValue(args->at(0)); 2892 VisitForStackValue(args->at(0));
2878 VisitForAccumulatorValue(args->at(1)); 2893 VisitForAccumulatorValue(args->at(1));
2879 2894
2880 Register object = ebx; 2895 Register object = ebx;
2881 Register index = eax; 2896 Register index = eax;
2882 Register scratch = ecx; 2897 Register scratch = ecx;
2883 Register result = edx; 2898 Register result = edx;
2884 2899
(...skipping 26 matching lines...) Expand all
2911 __ jmp(&done); 2926 __ jmp(&done);
2912 2927
2913 NopRuntimeCallHelper call_helper; 2928 NopRuntimeCallHelper call_helper;
2914 generator.GenerateSlow(masm_, call_helper); 2929 generator.GenerateSlow(masm_, call_helper);
2915 2930
2916 __ bind(&done); 2931 __ bind(&done);
2917 context()->Plug(result); 2932 context()->Plug(result);
2918 } 2933 }
2919 2934
2920 2935
2921 void FullCodeGenerator::EmitStringCharAt(ZoneList<Expression*>* args) { 2936 void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) {
2937 ZoneList<Expression*>* args = expr->arguments();
2922 ASSERT(args->length() == 2); 2938 ASSERT(args->length() == 2);
2923 2939
2924 VisitForStackValue(args->at(0)); 2940 VisitForStackValue(args->at(0));
2925 VisitForAccumulatorValue(args->at(1)); 2941 VisitForAccumulatorValue(args->at(1));
2926 2942
2927 Register object = ebx; 2943 Register object = ebx;
2928 Register index = eax; 2944 Register index = eax;
2929 Register scratch1 = ecx; 2945 Register scratch1 = ecx;
2930 Register scratch2 = edx; 2946 Register scratch2 = edx;
2931 Register result = eax; 2947 Register result = eax;
(...skipping 28 matching lines...) Expand all
2960 __ jmp(&done); 2976 __ jmp(&done);
2961 2977
2962 NopRuntimeCallHelper call_helper; 2978 NopRuntimeCallHelper call_helper;
2963 generator.GenerateSlow(masm_, call_helper); 2979 generator.GenerateSlow(masm_, call_helper);
2964 2980
2965 __ bind(&done); 2981 __ bind(&done);
2966 context()->Plug(result); 2982 context()->Plug(result);
2967 } 2983 }
2968 2984
2969 2985
2970 void FullCodeGenerator::EmitStringAdd(ZoneList<Expression*>* args) { 2986 void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) {
2987 ZoneList<Expression*>* args = expr->arguments();
2971 ASSERT_EQ(2, args->length()); 2988 ASSERT_EQ(2, args->length());
2972 2989
2973 VisitForStackValue(args->at(0)); 2990 VisitForStackValue(args->at(0));
2974 VisitForStackValue(args->at(1)); 2991 VisitForStackValue(args->at(1));
2975 2992
2976 StringAddStub stub(NO_STRING_ADD_FLAGS); 2993 StringAddStub stub(NO_STRING_ADD_FLAGS);
2977 __ CallStub(&stub); 2994 __ CallStub(&stub);
2978 context()->Plug(eax); 2995 context()->Plug(eax);
2979 } 2996 }
2980 2997
2981 2998
2982 void FullCodeGenerator::EmitStringCompare(ZoneList<Expression*>* args) { 2999 void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) {
3000 ZoneList<Expression*>* args = expr->arguments();
2983 ASSERT_EQ(2, args->length()); 3001 ASSERT_EQ(2, args->length());
2984 3002
2985 VisitForStackValue(args->at(0)); 3003 VisitForStackValue(args->at(0));
2986 VisitForStackValue(args->at(1)); 3004 VisitForStackValue(args->at(1));
2987 3005
2988 StringCompareStub stub; 3006 StringCompareStub stub;
2989 __ CallStub(&stub); 3007 __ CallStub(&stub);
2990 context()->Plug(eax); 3008 context()->Plug(eax);
2991 } 3009 }
2992 3010
2993 3011
2994 void FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) { 3012 void FullCodeGenerator::EmitMathSin(CallRuntime* expr) {
2995 // Load the argument on the stack and call the stub. 3013 // Load the argument on the stack and call the stub.
2996 TranscendentalCacheStub stub(TranscendentalCache::SIN, 3014 TranscendentalCacheStub stub(TranscendentalCache::SIN,
2997 TranscendentalCacheStub::TAGGED); 3015 TranscendentalCacheStub::TAGGED);
3016 ZoneList<Expression*>* args = expr->arguments();
2998 ASSERT(args->length() == 1); 3017 ASSERT(args->length() == 1);
2999 VisitForStackValue(args->at(0)); 3018 VisitForStackValue(args->at(0));
3000 __ CallStub(&stub); 3019 __ CallStub(&stub);
3001 context()->Plug(eax); 3020 context()->Plug(eax);
3002 } 3021 }
3003 3022
3004 3023
3005 void FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) { 3024 void FullCodeGenerator::EmitMathCos(CallRuntime* expr) {
3006 // Load the argument on the stack and call the stub. 3025 // Load the argument on the stack and call the stub.
3007 TranscendentalCacheStub stub(TranscendentalCache::COS, 3026 TranscendentalCacheStub stub(TranscendentalCache::COS,
3008 TranscendentalCacheStub::TAGGED); 3027 TranscendentalCacheStub::TAGGED);
3028 ZoneList<Expression*>* args = expr->arguments();
3009 ASSERT(args->length() == 1); 3029 ASSERT(args->length() == 1);
3010 VisitForStackValue(args->at(0)); 3030 VisitForStackValue(args->at(0));
3011 __ CallStub(&stub); 3031 __ CallStub(&stub);
3012 context()->Plug(eax); 3032 context()->Plug(eax);
3013 } 3033 }
3014 3034
3015 3035
3016 void FullCodeGenerator::EmitMathLog(ZoneList<Expression*>* args) { 3036 void FullCodeGenerator::EmitMathLog(CallRuntime* expr) {
3017 // Load the argument on the stack and call the stub. 3037 // Load the argument on the stack and call the stub.
3018 TranscendentalCacheStub stub(TranscendentalCache::LOG, 3038 TranscendentalCacheStub stub(TranscendentalCache::LOG,
3019 TranscendentalCacheStub::TAGGED); 3039 TranscendentalCacheStub::TAGGED);
3040 ZoneList<Expression*>* args = expr->arguments();
3020 ASSERT(args->length() == 1); 3041 ASSERT(args->length() == 1);
3021 VisitForStackValue(args->at(0)); 3042 VisitForStackValue(args->at(0));
3022 __ CallStub(&stub); 3043 __ CallStub(&stub);
3023 context()->Plug(eax); 3044 context()->Plug(eax);
3024 } 3045 }
3025 3046
3026 3047
3027 void FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) { 3048 void FullCodeGenerator::EmitMathSqrt(CallRuntime* expr) {
3028 // Load the argument on the stack and call the runtime function. 3049 // Load the argument on the stack and call the runtime function.
3050 ZoneList<Expression*>* args = expr->arguments();
3029 ASSERT(args->length() == 1); 3051 ASSERT(args->length() == 1);
3030 VisitForStackValue(args->at(0)); 3052 VisitForStackValue(args->at(0));
3031 __ CallRuntime(Runtime::kMath_sqrt, 1); 3053 __ CallRuntime(Runtime::kMath_sqrt, 1);
3032 context()->Plug(eax); 3054 context()->Plug(eax);
3033 } 3055 }
3034 3056
3035 3057
3036 void FullCodeGenerator::EmitCallFunction(ZoneList<Expression*>* args) { 3058 void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
3059 ZoneList<Expression*>* args = expr->arguments();
3037 ASSERT(args->length() >= 2); 3060 ASSERT(args->length() >= 2);
3038 3061
3039 int arg_count = args->length() - 2; // 2 ~ receiver and function. 3062 int arg_count = args->length() - 2; // 2 ~ receiver and function.
3040 for (int i = 0; i < arg_count + 1; ++i) { 3063 for (int i = 0; i < arg_count + 1; ++i) {
3041 VisitForStackValue(args->at(i)); 3064 VisitForStackValue(args->at(i));
3042 } 3065 }
3043 VisitForAccumulatorValue(args->last()); // Function. 3066 VisitForAccumulatorValue(args->last()); // Function.
3044 3067
3045 // InvokeFunction requires the function in edi. Move it in there. 3068 // InvokeFunction requires the function in edi. Move it in there.
3046 __ mov(edi, result_register()); 3069 __ mov(edi, result_register());
3047 ParameterCount count(arg_count); 3070 ParameterCount count(arg_count);
3048 __ InvokeFunction(edi, count, CALL_FUNCTION, 3071 __ InvokeFunction(edi, count, CALL_FUNCTION,
3049 NullCallWrapper(), CALL_AS_METHOD); 3072 NullCallWrapper(), CALL_AS_METHOD);
3050 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 3073 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
3051 context()->Plug(eax); 3074 context()->Plug(eax);
3052 } 3075 }
3053 3076
3054 3077
3055 void FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) { 3078 void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) {
3056 // Load the arguments on the stack and call the stub. 3079 // Load the arguments on the stack and call the stub.
3057 RegExpConstructResultStub stub; 3080 RegExpConstructResultStub stub;
3081 ZoneList<Expression*>* args = expr->arguments();
3058 ASSERT(args->length() == 3); 3082 ASSERT(args->length() == 3);
3059 VisitForStackValue(args->at(0)); 3083 VisitForStackValue(args->at(0));
3060 VisitForStackValue(args->at(1)); 3084 VisitForStackValue(args->at(1));
3061 VisitForStackValue(args->at(2)); 3085 VisitForStackValue(args->at(2));
3062 __ CallStub(&stub); 3086 __ CallStub(&stub);
3063 context()->Plug(eax); 3087 context()->Plug(eax);
3064 } 3088 }
3065 3089
3066 3090
3067 void FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) { 3091 void FullCodeGenerator::EmitSwapElements(CallRuntime* expr) {
3092 ZoneList<Expression*>* args = expr->arguments();
3068 ASSERT(args->length() == 3); 3093 ASSERT(args->length() == 3);
3069 VisitForStackValue(args->at(0)); 3094 VisitForStackValue(args->at(0));
3070 VisitForStackValue(args->at(1)); 3095 VisitForStackValue(args->at(1));
3071 VisitForStackValue(args->at(2)); 3096 VisitForStackValue(args->at(2));
3072 Label done; 3097 Label done;
3073 Label slow_case; 3098 Label slow_case;
3074 Register object = eax; 3099 Register object = eax;
3075 Register index_1 = ebx; 3100 Register index_1 = ebx;
3076 Register index_2 = ecx; 3101 Register index_2 = ecx;
3077 Register elements = edi; 3102 Register elements = edi;
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
3149 __ jmp(&done); 3174 __ jmp(&done);
3150 3175
3151 __ bind(&slow_case); 3176 __ bind(&slow_case);
3152 __ CallRuntime(Runtime::kSwapElements, 3); 3177 __ CallRuntime(Runtime::kSwapElements, 3);
3153 3178
3154 __ bind(&done); 3179 __ bind(&done);
3155 context()->Plug(eax); 3180 context()->Plug(eax);
3156 } 3181 }
3157 3182
3158 3183
3159 void FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) { 3184 void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) {
3185 ZoneList<Expression*>* args = expr->arguments();
3160 ASSERT_EQ(2, args->length()); 3186 ASSERT_EQ(2, args->length());
3161 3187
3162 ASSERT_NE(NULL, args->at(0)->AsLiteral()); 3188 ASSERT_NE(NULL, args->at(0)->AsLiteral());
3163 int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value(); 3189 int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value();
3164 3190
3165 Handle<FixedArray> jsfunction_result_caches( 3191 Handle<FixedArray> jsfunction_result_caches(
3166 isolate()->global_context()->jsfunction_result_caches()); 3192 isolate()->global_context()->jsfunction_result_caches());
3167 if (jsfunction_result_caches->length() <= cache_id) { 3193 if (jsfunction_result_caches->length() <= cache_id) {
3168 __ Abort("Attempt to use undefined cache."); 3194 __ Abort("Attempt to use undefined cache.");
3169 __ mov(eax, isolate()->factory()->undefined_value()); 3195 __ mov(eax, isolate()->factory()->undefined_value());
(...skipping 27 matching lines...) Expand all
3197 // Call runtime to perform the lookup. 3223 // Call runtime to perform the lookup.
3198 __ push(cache); 3224 __ push(cache);
3199 __ push(key); 3225 __ push(key);
3200 __ CallRuntime(Runtime::kGetFromCache, 2); 3226 __ CallRuntime(Runtime::kGetFromCache, 2);
3201 3227
3202 __ bind(&done); 3228 __ bind(&done);
3203 context()->Plug(eax); 3229 context()->Plug(eax);
3204 } 3230 }
3205 3231
3206 3232
3207 void FullCodeGenerator::EmitIsRegExpEquivalent(ZoneList<Expression*>* args) { 3233 void FullCodeGenerator::EmitIsRegExpEquivalent(CallRuntime* expr) {
3234 ZoneList<Expression*>* args = expr->arguments();
3208 ASSERT_EQ(2, args->length()); 3235 ASSERT_EQ(2, args->length());
3209 3236
3210 Register right = eax; 3237 Register right = eax;
3211 Register left = ebx; 3238 Register left = ebx;
3212 Register tmp = ecx; 3239 Register tmp = ecx;
3213 3240
3214 VisitForStackValue(args->at(0)); 3241 VisitForStackValue(args->at(0));
3215 VisitForAccumulatorValue(args->at(1)); 3242 VisitForAccumulatorValue(args->at(1));
3216 __ pop(left); 3243 __ pop(left);
3217 3244
(...skipping 16 matching lines...) Expand all
3234 __ mov(eax, Immediate(isolate()->factory()->false_value())); 3261 __ mov(eax, Immediate(isolate()->factory()->false_value()));
3235 __ jmp(&done); 3262 __ jmp(&done);
3236 __ bind(&ok); 3263 __ bind(&ok);
3237 __ mov(eax, Immediate(isolate()->factory()->true_value())); 3264 __ mov(eax, Immediate(isolate()->factory()->true_value()));
3238 __ bind(&done); 3265 __ bind(&done);
3239 3266
3240 context()->Plug(eax); 3267 context()->Plug(eax);
3241 } 3268 }
3242 3269
3243 3270
3244 void FullCodeGenerator::EmitHasCachedArrayIndex(ZoneList<Expression*>* args) { 3271 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) {
3272 ZoneList<Expression*>* args = expr->arguments();
3245 ASSERT(args->length() == 1); 3273 ASSERT(args->length() == 1);
3246 3274
3247 VisitForAccumulatorValue(args->at(0)); 3275 VisitForAccumulatorValue(args->at(0));
3248 3276
3249 if (FLAG_debug_code) { 3277 if (FLAG_debug_code) {
3250 __ AbortIfNotString(eax); 3278 __ AbortIfNotString(eax);
3251 } 3279 }
3252 3280
3253 Label materialize_true, materialize_false; 3281 Label materialize_true, materialize_false;
3254 Label* if_true = NULL; 3282 Label* if_true = NULL;
3255 Label* if_false = NULL; 3283 Label* if_false = NULL;
3256 Label* fall_through = NULL; 3284 Label* fall_through = NULL;
3257 context()->PrepareTest(&materialize_true, &materialize_false, 3285 context()->PrepareTest(&materialize_true, &materialize_false,
3258 &if_true, &if_false, &fall_through); 3286 &if_true, &if_false, &fall_through);
3259 3287
3260 __ test(FieldOperand(eax, String::kHashFieldOffset), 3288 __ test(FieldOperand(eax, String::kHashFieldOffset),
3261 Immediate(String::kContainsCachedArrayIndexMask)); 3289 Immediate(String::kContainsCachedArrayIndexMask));
3262 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 3290 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3263 Split(zero, if_true, if_false, fall_through); 3291 Split(zero, if_true, if_false, fall_through);
3264 3292
3265 context()->Plug(if_true, if_false); 3293 context()->Plug(if_true, if_false);
3266 } 3294 }
3267 3295
3268 3296
3269 void FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList<Expression*>* args) { 3297 void FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) {
3298 ZoneList<Expression*>* args = expr->arguments();
3270 ASSERT(args->length() == 1); 3299 ASSERT(args->length() == 1);
3271 VisitForAccumulatorValue(args->at(0)); 3300 VisitForAccumulatorValue(args->at(0));
3272 3301
3273 if (FLAG_debug_code) { 3302 if (FLAG_debug_code) {
3274 __ AbortIfNotString(eax); 3303 __ AbortIfNotString(eax);
3275 } 3304 }
3276 3305
3277 __ mov(eax, FieldOperand(eax, String::kHashFieldOffset)); 3306 __ mov(eax, FieldOperand(eax, String::kHashFieldOffset));
3278 __ IndexFromHash(eax, eax); 3307 __ IndexFromHash(eax, eax);
3279 3308
3280 context()->Plug(eax); 3309 context()->Plug(eax);
3281 } 3310 }
3282 3311
3283 3312
3284 void FullCodeGenerator::EmitFastAsciiArrayJoin(ZoneList<Expression*>* args) { 3313 void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) {
3285 Label bailout, done, one_char_separator, long_separator, 3314 Label bailout, done, one_char_separator, long_separator,
3286 non_trivial_array, not_size_one_array, loop, 3315 non_trivial_array, not_size_one_array, loop,
3287 loop_1, loop_1_condition, loop_2, loop_2_entry, loop_3, loop_3_entry; 3316 loop_1, loop_1_condition, loop_2, loop_2_entry, loop_3, loop_3_entry;
3288 3317
3318 ZoneList<Expression*>* args = expr->arguments();
3289 ASSERT(args->length() == 2); 3319 ASSERT(args->length() == 2);
3290 // We will leave the separator on the stack until the end of the function. 3320 // We will leave the separator on the stack until the end of the function.
3291 VisitForStackValue(args->at(1)); 3321 VisitForStackValue(args->at(1));
3292 // Load this to eax (= array) 3322 // Load this to eax (= array)
3293 VisitForAccumulatorValue(args->at(0)); 3323 VisitForAccumulatorValue(args->at(0));
3294 // All aliases of the same register have disjoint lifetimes. 3324 // All aliases of the same register have disjoint lifetimes.
3295 Register array = eax; 3325 Register array = eax;
3296 Register elements = no_reg; // Will be eax. 3326 Register elements = no_reg; // Will be eax.
3297 3327
3298 Register index = edx; 3328 Register index = edx;
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after
3636 context()->Plug(isolate()->factory()->undefined_value()); 3666 context()->Plug(isolate()->factory()->undefined_value());
3637 break; 3667 break;
3638 } 3668 }
3639 3669
3640 case Token::NOT: { 3670 case Token::NOT: {
3641 Comment cmnt(masm_, "[ UnaryOperation (NOT)"); 3671 Comment cmnt(masm_, "[ UnaryOperation (NOT)");
3642 if (context()->IsEffect()) { 3672 if (context()->IsEffect()) {
3643 // Unary NOT has no side effects so it's only necessary to visit the 3673 // Unary NOT has no side effects so it's only necessary to visit the
3644 // subexpression. Match the optimizing compiler by not branching. 3674 // subexpression. Match the optimizing compiler by not branching.
3645 VisitForEffect(expr->expression()); 3675 VisitForEffect(expr->expression());
3676 } else if (context()->IsTest()) {
3677 const TestContext* test = TestContext::cast(context());
3678 // The labels are swapped for the recursive call.
3679 VisitForControl(expr->expression(),
3680 test->false_label(),
3681 test->true_label(),
3682 test->fall_through());
3683 context()->Plug(test->true_label(), test->false_label());
3646 } else { 3684 } else {
3647 Label materialize_true, materialize_false; 3685 // We handle value contexts explicitly rather than simply visiting
3648 Label* if_true = NULL; 3686 // for control and plugging the control flow into the context,
3649 Label* if_false = NULL; 3687 // because we need to prepare a pair of extra administrative AST ids
3650 Label* fall_through = NULL; 3688 // for the optimizing compiler.
3651 3689 ASSERT(context()->IsAccumulatorValue() || context()->IsStackValue());
3652 // Notice that the labels are swapped. 3690 Label materialize_true, materialize_false, done;
3653 context()->PrepareTest(&materialize_true, &materialize_false, 3691 VisitForControl(expr->expression(),
3654 &if_false, &if_true, &fall_through); 3692 &materialize_false,
3655 if (context()->IsTest()) ForwardBailoutToChild(expr); 3693 &materialize_true,
3656 VisitForControl(expr->expression(), if_true, if_false, fall_through); 3694 &materialize_true);
3657 context()->Plug(if_false, if_true); // Labels swapped. 3695 __ bind(&materialize_true);
3696 PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS);
3697 if (context()->IsAccumulatorValue()) {
3698 __ mov(eax, isolate()->factory()->true_value());
3699 } else {
3700 __ push(isolate()->factory()->true_value());
3701 }
3702 __ jmp(&done, Label::kNear);
3703 __ bind(&materialize_false);
3704 PrepareForBailoutForId(expr->MaterializeFalseId(), NO_REGISTERS);
3705 if (context()->IsAccumulatorValue()) {
3706 __ mov(eax, isolate()->factory()->false_value());
3707 } else {
3708 __ push(isolate()->factory()->false_value());
3709 }
3710 __ bind(&done);
3658 } 3711 }
3659 break; 3712 break;
3660 } 3713 }
3661 3714
3662 case Token::TYPEOF: { 3715 case Token::TYPEOF: {
3663 Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); 3716 Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
3664 { StackValueContext context(this); 3717 { StackValueContext context(this);
3665 VisitForTypeofValue(expr->expression()); 3718 VisitForTypeofValue(expr->expression());
3666 } 3719 }
3667 __ CallRuntime(Runtime::kTypeof, 1); 3720 __ CallRuntime(Runtime::kTypeof, 1);
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after
3918 __ bind(&slow); 3971 __ bind(&slow);
3919 __ push(esi); 3972 __ push(esi);
3920 __ push(Immediate(proxy->name())); 3973 __ push(Immediate(proxy->name()));
3921 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); 3974 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
3922 PrepareForBailout(expr, TOS_REG); 3975 PrepareForBailout(expr, TOS_REG);
3923 __ bind(&done); 3976 __ bind(&done);
3924 3977
3925 context()->Plug(eax); 3978 context()->Plug(eax);
3926 } else { 3979 } else {
3927 // This expression cannot throw a reference error at the top level. 3980 // This expression cannot throw a reference error at the top level.
3928 VisitInCurrentContext(expr); 3981 VisitInDuplicateContext(expr);
3929 } 3982 }
3930 } 3983 }
3931 3984
3932 3985
3933 void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr, 3986 void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
3987 Expression* sub_expr,
3934 Handle<String> check) { 3988 Handle<String> check) {
3935 Label materialize_true, materialize_false; 3989 Label materialize_true, materialize_false;
3936 Label* if_true = NULL; 3990 Label* if_true = NULL;
3937 Label* if_false = NULL; 3991 Label* if_false = NULL;
3938 Label* fall_through = NULL; 3992 Label* fall_through = NULL;
3939 context()->PrepareTest(&materialize_true, &materialize_false, 3993 context()->PrepareTest(&materialize_true, &materialize_false,
3940 &if_true, &if_false, &fall_through); 3994 &if_true, &if_false, &fall_through);
3941 3995
3942 { AccumulatorValueContext context(this); 3996 { AccumulatorValueContext context(this);
3943 VisitForTypeofValue(expr); 3997 VisitForTypeofValue(sub_expr);
3944 } 3998 }
3945 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 3999 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3946 4000
3947 if (check->Equals(isolate()->heap()->number_symbol())) { 4001 if (check->Equals(isolate()->heap()->number_symbol())) {
3948 __ JumpIfSmi(eax, if_true); 4002 __ JumpIfSmi(eax, if_true);
3949 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), 4003 __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
3950 isolate()->factory()->heap_number_map()); 4004 isolate()->factory()->heap_number_map());
3951 Split(equal, if_true, if_false, fall_through); 4005 Split(equal, if_true, if_false, fall_through);
3952 } else if (check->Equals(isolate()->heap()->string_symbol())) { 4006 } else if (check->Equals(isolate()->heap()->string_symbol())) {
3953 __ JumpIfSmi(eax, if_false); 4007 __ JumpIfSmi(eax, if_false);
3954 __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, edx); 4008 __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, edx);
3955 __ j(above_equal, if_false); 4009 __ j(above_equal, if_false);
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
4019 Label* fall_through = NULL; 4073 Label* fall_through = NULL;
4020 context()->PrepareTest(&materialize_true, &materialize_false, 4074 context()->PrepareTest(&materialize_true, &materialize_false,
4021 &if_true, &if_false, &fall_through); 4075 &if_true, &if_false, &fall_through);
4022 4076
4023 Token::Value op = expr->op(); 4077 Token::Value op = expr->op();
4024 VisitForStackValue(expr->left()); 4078 VisitForStackValue(expr->left());
4025 switch (op) { 4079 switch (op) {
4026 case Token::IN: 4080 case Token::IN:
4027 VisitForStackValue(expr->right()); 4081 VisitForStackValue(expr->right());
4028 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); 4082 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
4029 PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); 4083 PrepareForBailoutBeforeSplit(expr, false, NULL, NULL);
4030 __ cmp(eax, isolate()->factory()->true_value()); 4084 __ cmp(eax, isolate()->factory()->true_value());
4031 Split(equal, if_true, if_false, fall_through); 4085 Split(equal, if_true, if_false, fall_through);
4032 break; 4086 break;
4033 4087
4034 case Token::INSTANCEOF: { 4088 case Token::INSTANCEOF: {
4035 VisitForStackValue(expr->right()); 4089 VisitForStackValue(expr->right());
4036 InstanceofStub stub(InstanceofStub::kNoFlags); 4090 InstanceofStub stub(InstanceofStub::kNoFlags);
4037 __ CallStub(&stub); 4091 __ CallStub(&stub);
4038 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 4092 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
4039 __ test(eax, eax); 4093 __ test(eax, eax);
4040 // The stub returns 0 for true. 4094 // The stub returns 0 for true.
4041 Split(zero, if_true, if_false, fall_through); 4095 Split(zero, if_true, if_false, fall_through);
4042 break; 4096 break;
4043 } 4097 }
4044 4098
4045 default: { 4099 default: {
4046 VisitForAccumulatorValue(expr->right()); 4100 VisitForAccumulatorValue(expr->right());
4047 Condition cc = no_condition; 4101 Condition cc = no_condition;
4048 switch (op) { 4102 switch (op) {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
4080 Split(cc, if_true, if_false, NULL); 4134 Split(cc, if_true, if_false, NULL);
4081 __ bind(&slow_case); 4135 __ bind(&slow_case);
4082 } 4136 }
4083 4137
4084 // Record position and call the compare IC. 4138 // Record position and call the compare IC.
4085 SetSourcePosition(expr->position()); 4139 SetSourcePosition(expr->position());
4086 Handle<Code> ic = CompareIC::GetUninitialized(op); 4140 Handle<Code> ic = CompareIC::GetUninitialized(op);
4087 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); 4141 __ call(ic, RelocInfo::CODE_TARGET, expr->id());
4088 patch_site.EmitPatchInfo(); 4142 patch_site.EmitPatchInfo();
4089 4143
4090 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 4144 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
4091 __ test(eax, eax); 4145 __ test(eax, eax);
4092 Split(cc, if_true, if_false, fall_through); 4146 Split(cc, if_true, if_false, fall_through);
4093 } 4147 }
4094 } 4148 }
4095 4149
4096 // Convert the result of the comparison into one expected for this 4150 // Convert the result of the comparison into one expected for this
4097 // expression's context. 4151 // expression's context.
4098 context()->Plug(if_true, if_false); 4152 context()->Plug(if_true, if_false);
4099 } 4153 }
4100 4154
4101 4155
4102 void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr, 4156 void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr,
4103 Expression* sub_expr, 4157 Expression* sub_expr,
4104 NilValue nil) { 4158 NilValue nil) {
4105 Label materialize_true, materialize_false; 4159 Label materialize_true, materialize_false;
4106 Label* if_true = NULL; 4160 Label* if_true = NULL;
4107 Label* if_false = NULL; 4161 Label* if_false = NULL;
4108 Label* fall_through = NULL; 4162 Label* fall_through = NULL;
4109 context()->PrepareTest(&materialize_true, &materialize_false, 4163 context()->PrepareTest(&materialize_true, &materialize_false,
4110 &if_true, &if_false, &fall_through); 4164 &if_true, &if_false, &fall_through);
4111 4165
4112 VisitForAccumulatorValue(sub_expr); 4166 VisitForAccumulatorValue(sub_expr);
4113 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 4167 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
4114 Handle<Object> nil_value = nil == kNullValue ? 4168 Handle<Object> nil_value = nil == kNullValue ?
4115 isolate()->factory()->null_value() : 4169 isolate()->factory()->null_value() :
4116 isolate()->factory()->undefined_value(); 4170 isolate()->factory()->undefined_value();
4117 __ cmp(eax, nil_value); 4171 __ cmp(eax, nil_value);
4118 if (expr->op() == Token::EQ_STRICT) { 4172 if (expr->op() == Token::EQ_STRICT) {
4119 Split(equal, if_true, if_false, fall_through); 4173 Split(equal, if_true, if_false, fall_through);
4120 } else { 4174 } else {
4121 Handle<Object> other_nil_value = nil == kNullValue ? 4175 Handle<Object> other_nil_value = nil == kNullValue ?
4122 isolate()->factory()->undefined_value() : 4176 isolate()->factory()->undefined_value() :
4123 isolate()->factory()->null_value(); 4177 isolate()->factory()->null_value();
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
4236 *context_length = 0; 4290 *context_length = 0;
4237 return previous_; 4291 return previous_;
4238 } 4292 }
4239 4293
4240 4294
4241 #undef __ 4295 #undef __
4242 4296
4243 } } // namespace v8::internal 4297 } } // namespace v8::internal
4244 4298
4245 #endif // V8_TARGET_ARCH_IA32 4299 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/hydrogen.cc ('k') | src/mips/full-codegen-mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698