OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |