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

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

Issue 6597029: [Isolates] Merge r 6300:6500 from bleeding_edge to isolates. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/isolates/
Patch Set: Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ia32/deoptimizer-ia32.cc ('k') | src/ia32/ic-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 749 matching lines...) Expand 10 before | Expand all | Expand 10 after
760 VisitForStackValue(stmt->tag()); 760 VisitForStackValue(stmt->tag());
761 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); 761 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
762 762
763 ZoneList<CaseClause*>* clauses = stmt->cases(); 763 ZoneList<CaseClause*>* clauses = stmt->cases();
764 CaseClause* default_clause = NULL; // Can occur anywhere in the list. 764 CaseClause* default_clause = NULL; // Can occur anywhere in the list.
765 765
766 Label next_test; // Recycled for each test. 766 Label next_test; // Recycled for each test.
767 // Compile all the tests with branches to their bodies. 767 // Compile all the tests with branches to their bodies.
768 for (int i = 0; i < clauses->length(); i++) { 768 for (int i = 0; i < clauses->length(); i++) {
769 CaseClause* clause = clauses->at(i); 769 CaseClause* clause = clauses->at(i);
770 clause->body_target()->entry_label()->Unuse();
771
770 // The default is not a test, but remember it as final fall through. 772 // The default is not a test, but remember it as final fall through.
771 if (clause->is_default()) { 773 if (clause->is_default()) {
772 default_clause = clause; 774 default_clause = clause;
773 continue; 775 continue;
774 } 776 }
775 777
776 Comment cmnt(masm_, "[ Case comparison"); 778 Comment cmnt(masm_, "[ Case comparison");
777 __ bind(&next_test); 779 __ bind(&next_test);
778 next_test.Unuse(); 780 next_test.Unuse();
779 781
(...skipping 1571 matching lines...) Expand 10 before | Expand all | Expand 10 after
2351 Property* prop = fun->AsProperty(); 2353 Property* prop = fun->AsProperty();
2352 Literal* key = prop->key()->AsLiteral(); 2354 Literal* key = prop->key()->AsLiteral();
2353 if (key != NULL && key->handle()->IsSymbol()) { 2355 if (key != NULL && key->handle()->IsSymbol()) {
2354 // Call to a named property, use call IC. 2356 // Call to a named property, use call IC.
2355 VisitForStackValue(prop->obj()); 2357 VisitForStackValue(prop->obj());
2356 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); 2358 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET);
2357 } else { 2359 } else {
2358 // Call to a keyed property. 2360 // Call to a keyed property.
2359 // For a synthetic property use keyed load IC followed by function call, 2361 // For a synthetic property use keyed load IC followed by function call,
2360 // for a regular property use keyed EmitCallIC. 2362 // for a regular property use keyed EmitCallIC.
2361 { PreservePositionScope scope(masm()->positions_recorder());
2362 VisitForStackValue(prop->obj());
2363 }
2364 if (prop->is_synthetic()) { 2363 if (prop->is_synthetic()) {
2365 { PreservePositionScope scope(masm()->positions_recorder()); 2364 // Do not visit the object and key subexpressions (they are shared
2366 VisitForAccumulatorValue(prop->key()); 2365 // by all occurrences of the same rewritten parameter).
2367 } 2366 ASSERT(prop->obj()->AsVariableProxy() != NULL);
2367 ASSERT(prop->obj()->AsVariableProxy()->var()->AsSlot() != NULL);
2368 Slot* slot = prop->obj()->AsVariableProxy()->var()->AsSlot();
2369 MemOperand operand = EmitSlotSearch(slot, edx);
2370 __ mov(edx, operand);
2371
2372 ASSERT(prop->key()->AsLiteral() != NULL);
2373 ASSERT(prop->key()->AsLiteral()->handle()->IsSmi());
2374 __ mov(eax, prop->key()->AsLiteral()->handle());
2375
2368 // Record source code position for IC call. 2376 // Record source code position for IC call.
2369 SetSourcePosition(prop->position()); 2377 SetSourcePosition(prop->position());
2370 __ pop(edx); // We do not need to keep the receiver.
2371 2378
2372 Handle<Code> ic(isolate()->builtins()->builtin( 2379 Handle<Code> ic(isolate()->builtins()->builtin(
2373 Builtins::KeyedLoadIC_Initialize)); 2380 Builtins::KeyedLoadIC_Initialize));
2374 EmitCallIC(ic, RelocInfo::CODE_TARGET); 2381 EmitCallIC(ic, RelocInfo::CODE_TARGET);
2375 // Push result (function). 2382 // Push result (function).
2376 __ push(eax); 2383 __ push(eax);
2377 // Push Global receiver. 2384 // Push Global receiver.
2378 __ mov(ecx, GlobalObjectOperand()); 2385 __ mov(ecx, GlobalObjectOperand());
2379 __ push(FieldOperand(ecx, GlobalObject::kGlobalReceiverOffset)); 2386 __ push(FieldOperand(ecx, GlobalObject::kGlobalReceiverOffset));
2380 EmitCallWithStub(expr); 2387 EmitCallWithStub(expr);
2381 } else { 2388 } else {
2389 { PreservePositionScope scope(masm()->positions_recorder());
2390 VisitForStackValue(prop->obj());
2391 }
2382 EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET); 2392 EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET);
2383 } 2393 }
2384 } 2394 }
2385 } else { 2395 } else {
2386 // Call to some other expression. If the expression is an anonymous 2396 // Call to some other expression. If the expression is an anonymous
2387 // function literal not called in a loop, mark it as one that should 2397 // function literal not called in a loop, mark it as one that should
2388 // also use the full code generator. 2398 // also use the full code generator.
2389 FunctionLiteral* lit = fun->AsFunctionLiteral(); 2399 FunctionLiteral* lit = fun->AsFunctionLiteral();
2390 if (lit != NULL && 2400 if (lit != NULL &&
2391 lit->name()->Equals(isolate()->heap()->empty_string()) && 2401 lit->name()->Equals(isolate()->heap()->empty_string()) &&
(...skipping 974 matching lines...) Expand 10 before | Expand all | Expand 10 after
3366 } 3376 }
3367 3377
3368 __ mov(eax, FieldOperand(eax, String::kHashFieldOffset)); 3378 __ mov(eax, FieldOperand(eax, String::kHashFieldOffset));
3369 __ IndexFromHash(eax, eax); 3379 __ IndexFromHash(eax, eax);
3370 3380
3371 context()->Plug(eax); 3381 context()->Plug(eax);
3372 } 3382 }
3373 3383
3374 3384
3375 void FullCodeGenerator::EmitFastAsciiArrayJoin(ZoneList<Expression*>* args) { 3385 void FullCodeGenerator::EmitFastAsciiArrayJoin(ZoneList<Expression*>* args) {
3376 Label bailout; 3386 Label bailout, done, one_char_separator, long_separator,
3377 Label done; 3387 non_trivial_array, not_size_one_array, loop, loop_condition,
3388 loop_1, loop_1_condition, loop_2, loop_2_entry, loop_3, loop_3_entry;
3378 3389
3379 ASSERT(args->length() == 2); 3390 ASSERT(args->length() == 2);
3380 // We will leave the separator on the stack until the end of the function. 3391 // We will leave the separator on the stack until the end of the function.
3381 VisitForStackValue(args->at(1)); 3392 VisitForStackValue(args->at(1));
3382 // Load this to eax (= array) 3393 // Load this to eax (= array)
3383 VisitForAccumulatorValue(args->at(0)); 3394 VisitForAccumulatorValue(args->at(0));
3384
3385 // All aliases of the same register have disjoint lifetimes. 3395 // All aliases of the same register have disjoint lifetimes.
3386 Register array = eax; 3396 Register array = eax;
3387 Register result_pos = no_reg; 3397 Register elements = no_reg; // Will be eax.
3388 3398
3389 Register index = edi; 3399 Register index = edx;
3390 3400
3391 Register current_string_length = ecx; // Will be ecx when live. 3401 Register string_length = ecx;
3392 3402
3393 Register current_string = edx; 3403 Register string = esi;
3394 3404
3395 Register scratch = ebx; 3405 Register scratch = ebx;
3396 3406
3397 Register scratch_2 = esi; 3407 Register array_length = edi;
3398 Register new_padding_chars = scratch_2; 3408 Register result_pos = no_reg; // Will be edi.
3399 3409
3400 Operand separator = Operand(esp, 4 * kPointerSize); // Already pushed. 3410 // Separator operand is already pushed.
3401 Operand elements = Operand(esp, 3 * kPointerSize); 3411 Operand separator_operand = Operand(esp, 2 * kPointerSize);
3402 Operand result = Operand(esp, 2 * kPointerSize); 3412 Operand result_operand = Operand(esp, 1 * kPointerSize);
3403 Operand padding_chars = Operand(esp, 1 * kPointerSize); 3413 Operand array_length_operand = Operand(esp, 0);
3404 Operand array_length = Operand(esp, 0); 3414 __ sub(Operand(esp), Immediate(2 * kPointerSize));
3405 __ sub(Operand(esp), Immediate(4 * kPointerSize)); 3415 __ cld();
3406 3416 // Check that the array is a JSArray
3407
3408 // Check that eax is a JSArray
3409 __ test(array, Immediate(kSmiTagMask)); 3417 __ test(array, Immediate(kSmiTagMask));
3410 __ j(zero, &bailout); 3418 __ j(zero, &bailout);
3411 __ CmpObjectType(array, JS_ARRAY_TYPE, scratch); 3419 __ CmpObjectType(array, JS_ARRAY_TYPE, scratch);
3412 __ j(not_equal, &bailout); 3420 __ j(not_equal, &bailout);
3413 3421
3414 // Check that the array has fast elements. 3422 // Check that the array has fast elements.
3415 __ test_b(FieldOperand(scratch, Map::kBitField2Offset), 3423 __ test_b(FieldOperand(scratch, Map::kBitField2Offset),
3416 1 << Map::kHasFastElements); 3424 1 << Map::kHasFastElements);
3417 __ j(zero, &bailout); 3425 __ j(zero, &bailout);
3418 3426
3419 // If the array is empty, return the empty string. 3427 // If the array has length zero, return the empty string.
3420 __ mov(scratch, FieldOperand(array, JSArray::kLengthOffset)); 3428 __ mov(array_length, FieldOperand(array, JSArray::kLengthOffset));
3421 __ sar(scratch, 1); 3429 __ sar(array_length, 1);
3422 Label non_trivial; 3430 __ j(not_zero, &non_trivial_array);
3423 __ j(not_zero, &non_trivial); 3431 __ mov(result_operand, FACTORY->empty_string());
3424 __ mov(result, isolate()->factory()->empty_string()); 3432 __ jmp(&done);
3425 __ jmp(&done); 3433
3426 3434 // Save the array length.
3427 __ bind(&non_trivial); 3435 __ bind(&non_trivial_array);
3428 __ mov(array_length, scratch); 3436 __ mov(array_length_operand, array_length);
3429 3437
3430 __ mov(scratch, FieldOperand(array, JSArray::kElementsOffset)); 3438 // Save the FixedArray containing array's elements.
3431 __ mov(elements, scratch);
3432
3433 // End of array's live range. 3439 // End of array's live range.
3434 result_pos = array; 3440 elements = array;
3441 __ mov(elements, FieldOperand(array, JSArray::kElementsOffset));
3435 array = no_reg; 3442 array = no_reg;
3436 3443
3437 3444
3438 // Check that the separator is a flat ascii string. 3445 // Check that all array elements are sequential ASCII strings, and
3439 __ mov(current_string, separator); 3446 // accumulate the sum of their lengths, as a smi-encoded value.
3440 __ test(current_string, Immediate(kSmiTagMask)); 3447 __ Set(index, Immediate(0));
3448 __ Set(string_length, Immediate(0));
3449 // Loop condition: while (index < length).
3450 // Live loop registers: index, array_length, string,
3451 // scratch, string_length, elements.
3452 __ jmp(&loop_condition);
3453 __ bind(&loop);
3454 __ cmp(index, Operand(array_length));
3455 __ j(greater_equal, &done);
3456
3457 __ mov(string, FieldOperand(elements, index,
3458 times_pointer_size,
3459 FixedArray::kHeaderSize));
3460 __ test(string, Immediate(kSmiTagMask));
3441 __ j(zero, &bailout); 3461 __ j(zero, &bailout);
3442 __ mov(scratch, FieldOperand(current_string, HeapObject::kMapOffset)); 3462 __ mov(scratch, FieldOperand(string, HeapObject::kMapOffset));
3443 __ mov_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); 3463 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
3444 __ and_(scratch, Immediate( 3464 __ and_(scratch, Immediate(
3445 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask)); 3465 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask));
3446 __ cmp(scratch, kStringTag | kAsciiStringTag | kSeqStringTag); 3466 __ cmp(scratch, kStringTag | kAsciiStringTag | kSeqStringTag);
3447 __ j(not_equal, &bailout); 3467 __ j(not_equal, &bailout);
3448 // If the separator is the empty string, replace it with NULL. 3468 __ add(string_length,
3449 // The test for NULL is quicker than the empty string test, in a loop. 3469 FieldOperand(string, SeqAsciiString::kLengthOffset));
3450 __ cmp(FieldOperand(current_string, SeqAsciiString::kLengthOffset), 3470 __ j(overflow, &bailout);
3451 Immediate(0)); 3471 __ add(Operand(index), Immediate(1));
3452 Label separator_checked; 3472 __ bind(&loop_condition);
3453 __ j(not_zero, &separator_checked); 3473 __ cmp(index, Operand(array_length));
3454 __ mov(separator, Immediate(0)); 3474 __ j(less, &loop);
3455 __ bind(&separator_checked); 3475
3456 3476 // If array_length is 1, return elements[0], a string.
3457 // Check that elements[0] is a flat ascii string, and copy it in new space. 3477 __ cmp(array_length, 1);
3458 __ mov(scratch, elements); 3478 __ j(not_equal, &not_size_one_array);
3459 __ mov(current_string, FieldOperand(scratch, FixedArray::kHeaderSize)); 3479 __ mov(scratch, FieldOperand(elements, FixedArray::kHeaderSize));
3460 __ test(current_string, Immediate(kSmiTagMask)); 3480 __ mov(result_operand, scratch);
3481 __ jmp(&done);
3482
3483 __ bind(&not_size_one_array);
3484
3485 // End of array_length live range.
3486 result_pos = array_length;
3487 array_length = no_reg;
3488
3489 // Live registers:
3490 // string_length: Sum of string lengths, as a smi.
3491 // elements: FixedArray of strings.
3492
3493 // Check that the separator is a flat ASCII string.
3494 __ mov(string, separator_operand);
3495 __ test(string, Immediate(kSmiTagMask));
3461 __ j(zero, &bailout); 3496 __ j(zero, &bailout);
3462 __ mov(scratch, FieldOperand(current_string, HeapObject::kMapOffset)); 3497 __ mov(scratch, FieldOperand(string, HeapObject::kMapOffset));
3463 __ mov_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); 3498 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
3464 __ and_(scratch, Immediate( 3499 __ and_(scratch, Immediate(
3465 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask)); 3500 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask));
3466 __ cmp(scratch, kStringTag | kAsciiStringTag | kSeqStringTag); 3501 __ cmp(scratch, kStringTag | kAsciiStringTag | kSeqStringTag);
3467 __ j(not_equal, &bailout); 3502 __ j(not_equal, &bailout);
3468 3503
3469 // Allocate space to copy it. Round up the size to the alignment granularity. 3504 // Add (separator length times array_length) - separator length
3470 __ mov(current_string_length, 3505 // to string_length.
3471 FieldOperand(current_string, String::kLengthOffset)); 3506 __ mov(scratch, separator_operand);
3472 __ shr(current_string_length, 1); 3507 __ mov(scratch, FieldOperand(scratch, SeqAsciiString::kLengthOffset));
3473 3508 __ sub(string_length, Operand(scratch)); // May be negative, temporarily.
3509 __ imul(scratch, array_length_operand);
3510 __ j(overflow, &bailout);
3511 __ add(string_length, Operand(scratch));
3512 __ j(overflow, &bailout);
3513
3514 __ shr(string_length, 1);
3474 // Live registers and stack values: 3515 // Live registers and stack values:
3475 // current_string_length: length of elements[0]. 3516 // string_length
3476 3517 // elements
3477 // New string result in new space = elements[0] 3518 __ AllocateAsciiString(result_pos, string_length, scratch,
3478 __ AllocateAsciiString(result_pos, current_string_length, scratch_2, 3519 index, string, &bailout);
3479 index, no_reg, &bailout); 3520 __ mov(result_operand, result_pos);
3480 __ mov(result, result_pos); 3521 __ lea(result_pos, FieldOperand(result_pos, SeqAsciiString::kHeaderSize));
3481 3522
3482 // Adjust current_string_length to include padding bytes at end of string. 3523
3483 // Keep track of the number of padding bytes. 3524 __ mov(string, separator_operand);
3484 __ mov(new_padding_chars, current_string_length); 3525 __ cmp(FieldOperand(string, SeqAsciiString::kLengthOffset),
3485 __ add(Operand(current_string_length), Immediate(kObjectAlignmentMask)); 3526 Immediate(Smi::FromInt(1)));
3486 __ and_(Operand(current_string_length), Immediate(~kObjectAlignmentMask)); 3527 __ j(equal, &one_char_separator);
3487 __ sub(new_padding_chars, Operand(current_string_length)); 3528 __ j(greater, &long_separator);
3488 __ neg(new_padding_chars); 3529
3489 __ mov(padding_chars, new_padding_chars); 3530
3490 3531 // Empty separator case
3491 Label copy_loop_1_done; 3532 __ mov(index, Immediate(0));
3492 Label copy_loop_1; 3533 __ jmp(&loop_1_condition);
3493 __ test(current_string_length, Operand(current_string_length)); 3534 // Loop condition: while (index < length).
3494 __ j(zero, &copy_loop_1_done); 3535 __ bind(&loop_1);
3495 __ bind(&copy_loop_1); 3536 // Each iteration of the loop concatenates one string to the result.
3496 __ sub(Operand(current_string_length), Immediate(kPointerSize)); 3537 // Live values in registers:
3497 __ mov(scratch, FieldOperand(current_string, current_string_length, 3538 // index: which element of the elements array we are adding to the result.
3498 times_1, SeqAsciiString::kHeaderSize)); 3539 // result_pos: the position to which we are currently copying characters.
3499 __ mov(FieldOperand(result_pos, current_string_length, 3540 // elements: the FixedArray of strings we are joining.
3500 times_1, SeqAsciiString::kHeaderSize), 3541
3501 scratch); 3542 // Get string = array[index].
3502 __ j(not_zero, &copy_loop_1); 3543 __ mov(string, FieldOperand(elements, index,
3503 __ bind(&copy_loop_1_done); 3544 times_pointer_size,
3504 3545 FixedArray::kHeaderSize));
3505 __ mov(index, Immediate(1)); 3546 __ mov(string_length,
3506 // Loop condition: while (index < length). 3547 FieldOperand(string, String::kLengthOffset));
3507 Label loop; 3548 __ shr(string_length, 1);
3508 __ bind(&loop); 3549 __ lea(string,
3509 __ cmp(index, array_length); 3550 FieldOperand(string, SeqAsciiString::kHeaderSize));
3510 __ j(greater_equal, &done); 3551 __ CopyBytes(string, result_pos, string_length, scratch);
3511 3552 __ add(Operand(index), Immediate(1));
3512 // If the separator is the empty string, signalled by NULL, skip it. 3553 __ bind(&loop_1_condition);
3513 Label separator_done; 3554 __ cmp(index, array_length_operand);
3514 __ mov(current_string, separator); 3555 __ j(less, &loop_1); // End while (index < length).
3515 __ test(current_string, Operand(current_string)); 3556 __ jmp(&done);
3516 __ j(zero, &separator_done); 3557
3517 3558
3518 // Append separator to result. It is known to be a flat ascii string. 3559
3519 __ AppendStringToTopOfNewSpace(current_string, current_string_length, 3560 // One-character separator case
3520 result_pos, scratch, scratch_2, result, 3561 __ bind(&one_char_separator);
3521 padding_chars, &bailout); 3562 // Replace separator with its ascii character value.
3522 __ bind(&separator_done); 3563 __ mov_b(scratch, FieldOperand(string, SeqAsciiString::kHeaderSize));
3523 3564 __ mov_b(separator_operand, scratch);
3524 // Add next element of array to the end of the result. 3565
3525 // Get current_string = array[index]. 3566 __ Set(index, Immediate(0));
3526 __ mov(scratch, elements); 3567 // Jump into the loop after the code that copies the separator, so the first
3527 __ mov(current_string, FieldOperand(scratch, index, 3568 // element is not preceded by a separator
3528 times_pointer_size, 3569 __ jmp(&loop_2_entry);
3529 FixedArray::kHeaderSize)); 3570 // Loop condition: while (index < length).
3530 // If current != flat ascii string drop result, return undefined. 3571 __ bind(&loop_2);
3531 __ test(current_string, Immediate(kSmiTagMask)); 3572 // Each iteration of the loop concatenates one string to the result.
3532 __ j(zero, &bailout); 3573 // Live values in registers:
3533 __ mov(scratch, FieldOperand(current_string, HeapObject::kMapOffset)); 3574 // index: which element of the elements array we are adding to the result.
3534 __ mov_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); 3575 // result_pos: the position to which we are currently copying characters.
3535 __ and_(scratch, Immediate( 3576
3536 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask)); 3577 // Copy the separator character to the result.
3537 __ cmp(scratch, kStringTag | kAsciiStringTag | kSeqStringTag); 3578 __ mov_b(scratch, separator_operand);
3538 __ j(not_equal, &bailout); 3579 __ mov_b(Operand(result_pos, 0), scratch);
3539 3580 __ inc(result_pos);
3540 // Append current to the result. 3581
3541 __ AppendStringToTopOfNewSpace(current_string, current_string_length, 3582 __ bind(&loop_2_entry);
3542 result_pos, scratch, scratch_2, result, 3583 // Get string = array[index].
3543 padding_chars, &bailout); 3584 __ mov(string, FieldOperand(elements, index,
3544 __ add(Operand(index), Immediate(1)); 3585 times_pointer_size,
3545 __ jmp(&loop); // End while (index < length). 3586 FixedArray::kHeaderSize));
3587 __ mov(string_length,
3588 FieldOperand(string, String::kLengthOffset));
3589 __ shr(string_length, 1);
3590 __ lea(string,
3591 FieldOperand(string, SeqAsciiString::kHeaderSize));
3592 __ CopyBytes(string, result_pos, string_length, scratch);
3593 __ add(Operand(index), Immediate(1));
3594
3595 __ cmp(index, array_length_operand);
3596 __ j(less, &loop_2); // End while (index < length).
3597 __ jmp(&done);
3598
3599
3600 // Long separator case (separator is more than one character).
3601 __ bind(&long_separator);
3602
3603 __ Set(index, Immediate(0));
3604 // Jump into the loop after the code that copies the separator, so the first
3605 // element is not preceded by a separator
3606 __ jmp(&loop_3_entry);
3607 // Loop condition: while (index < length).
3608 __ bind(&loop_3);
3609 // Each iteration of the loop concatenates one string to the result.
3610 // Live values in registers:
3611 // index: which element of the elements array we are adding to the result.
3612 // result_pos: the position to which we are currently copying characters.
3613
3614 // Copy the separator to the result.
3615 __ mov(string, separator_operand);
3616 __ mov(string_length,
3617 FieldOperand(string, String::kLengthOffset));
3618 __ shr(string_length, 1);
3619 __ lea(string,
3620 FieldOperand(string, SeqAsciiString::kHeaderSize));
3621 __ CopyBytes(string, result_pos, string_length, scratch);
3622
3623 __ bind(&loop_3_entry);
3624 // Get string = array[index].
3625 __ mov(string, FieldOperand(elements, index,
3626 times_pointer_size,
3627 FixedArray::kHeaderSize));
3628 __ mov(string_length,
3629 FieldOperand(string, String::kLengthOffset));
3630 __ shr(string_length, 1);
3631 __ lea(string,
3632 FieldOperand(string, SeqAsciiString::kHeaderSize));
3633 __ CopyBytes(string, result_pos, string_length, scratch);
3634 __ add(Operand(index), Immediate(1));
3635
3636 __ cmp(index, array_length_operand);
3637 __ j(less, &loop_3); // End while (index < length).
3638 __ jmp(&done);
3639
3546 3640
3547 __ bind(&bailout); 3641 __ bind(&bailout);
3548 __ mov(result, isolate()->factory()->undefined_value()); 3642 __ mov(result_operand, FACTORY->undefined_value());
3549 __ bind(&done); 3643 __ bind(&done);
3550 __ mov(eax, result); 3644 __ mov(eax, result_operand);
3551 // Drop temp values from the stack, and restore context register. 3645 // Drop temp values from the stack, and restore context register.
3552 __ add(Operand(esp), Immediate(5 * kPointerSize)); 3646 __ add(Operand(esp), Immediate(3 * kPointerSize));
3553 3647
3554 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 3648 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
3555 context()->Plug(eax); 3649 context()->Plug(eax);
3556 } 3650 }
3557 3651
3558 3652
3559 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { 3653 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
3560 Handle<String> name = expr->name(); 3654 Handle<String> name = expr->name();
3561 if (name->length() > 0 && name->Get(0) == '_') { 3655 if (name->length() > 0 && name->Get(0) == '_') {
3562 Comment cmnt(masm_, "[ InlineRuntimeCall"); 3656 Comment cmnt(masm_, "[ InlineRuntimeCall");
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
3613 var->AsSlot()->type() != Slot::LOOKUP) { 3707 var->AsSlot()->type() != Slot::LOOKUP) {
3614 // Result of deleting non-global, non-dynamic variables is false. 3708 // Result of deleting non-global, non-dynamic variables is false.
3615 // The subexpression does not have side effects. 3709 // The subexpression does not have side effects.
3616 context()->Plug(false); 3710 context()->Plug(false);
3617 } else { 3711 } else {
3618 // Property or variable reference. Call the delete builtin with 3712 // Property or variable reference. Call the delete builtin with
3619 // object and property name as arguments. 3713 // object and property name as arguments.
3620 if (prop != NULL) { 3714 if (prop != NULL) {
3621 VisitForStackValue(prop->obj()); 3715 VisitForStackValue(prop->obj());
3622 VisitForStackValue(prop->key()); 3716 VisitForStackValue(prop->key());
3717 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
3623 } else if (var->is_global()) { 3718 } else if (var->is_global()) {
3624 __ push(GlobalObjectOperand()); 3719 __ push(GlobalObjectOperand());
3625 __ push(Immediate(var->name())); 3720 __ push(Immediate(var->name()));
3721 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
3626 } else { 3722 } else {
3627 // Non-global variable. Call the runtime to look up the context 3723 // Non-global variable. Call the runtime to delete from the
3628 // where the variable was introduced. 3724 // context where the variable was introduced.
3629 __ push(context_register()); 3725 __ push(context_register());
3630 __ push(Immediate(var->name())); 3726 __ push(Immediate(var->name()));
3631 __ CallRuntime(Runtime::kLookupContext, 2); 3727 __ CallRuntime(Runtime::kDeleteContextSlot, 2);
3632 __ push(eax);
3633 __ push(Immediate(var->name()));
3634 } 3728 }
3635 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
3636 context()->Plug(eax); 3729 context()->Plug(eax);
3637 } 3730 }
3638 break; 3731 break;
3639 } 3732 }
3640 3733
3641 case Token::VOID: { 3734 case Token::VOID: {
3642 Comment cmnt(masm_, "[ UnaryOperation (VOID)"); 3735 Comment cmnt(masm_, "[ UnaryOperation (VOID)");
3643 VisitForEffect(expr->expression()); 3736 VisitForEffect(expr->expression());
3644 context()->Plug(isolate()->factory()->undefined_value()); 3737 context()->Plug(isolate()->factory()->undefined_value());
3645 break; 3738 break;
(...skipping 653 matching lines...) Expand 10 before | Expand all | Expand 10 after
4299 // And return. 4392 // And return.
4300 __ ret(0); 4393 __ ret(0);
4301 } 4394 }
4302 4395
4303 4396
4304 #undef __ 4397 #undef __
4305 4398
4306 } } // namespace v8::internal 4399 } } // namespace v8::internal
4307 4400
4308 #endif // V8_TARGET_ARCH_IA32 4401 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/deoptimizer-ia32.cc ('k') | src/ia32/ic-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698