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

Side by Side Diff: src/arm/code-stubs-arm.cc

Issue 151163005: A64: Synchronize with r16356. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 10 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/arm/code-stubs-arm.h ('k') | src/arm/cpu-arm.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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 20 matching lines...) Expand all
31 31
32 #include "bootstrapper.h" 32 #include "bootstrapper.h"
33 #include "code-stubs.h" 33 #include "code-stubs.h"
34 #include "regexp-macro-assembler.h" 34 #include "regexp-macro-assembler.h"
35 #include "stub-cache.h" 35 #include "stub-cache.h"
36 36
37 namespace v8 { 37 namespace v8 {
38 namespace internal { 38 namespace internal {
39 39
40 40
41 void FastNewClosureStub::InitializeInterfaceDescriptor(
42 Isolate* isolate,
43 CodeStubInterfaceDescriptor* descriptor) {
44 static Register registers[] = { r2 };
45 descriptor->register_param_count_ = 1;
46 descriptor->register_params_ = registers;
47 descriptor->deoptimization_handler_ =
48 Runtime::FunctionForId(Runtime::kNewClosureFromStubFailure)->entry;
49 }
50
51
41 void ToNumberStub::InitializeInterfaceDescriptor( 52 void ToNumberStub::InitializeInterfaceDescriptor(
42 Isolate* isolate, 53 Isolate* isolate,
43 CodeStubInterfaceDescriptor* descriptor) { 54 CodeStubInterfaceDescriptor* descriptor) {
44 static Register registers[] = { r0 }; 55 static Register registers[] = { r0 };
45 descriptor->register_param_count_ = 1; 56 descriptor->register_param_count_ = 1;
46 descriptor->register_params_ = registers; 57 descriptor->register_params_ = registers;
47 descriptor->deoptimization_handler_ = NULL; 58 descriptor->deoptimization_handler_ = NULL;
48 } 59 }
49 60
50 61
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after
302 __ push(descriptor->register_params_[i]); 313 __ push(descriptor->register_params_[i]);
303 } 314 }
304 ExternalReference miss = descriptor->miss_handler(); 315 ExternalReference miss = descriptor->miss_handler();
305 __ CallExternalReference(miss, descriptor->register_param_count_); 316 __ CallExternalReference(miss, descriptor->register_param_count_);
306 } 317 }
307 318
308 __ Ret(); 319 __ Ret();
309 } 320 }
310 321
311 322
312 void FastNewClosureStub::Generate(MacroAssembler* masm) {
313 // Create a new closure from the given function info in new
314 // space. Set the context to the current context in cp.
315 Counters* counters = masm->isolate()->counters();
316
317 Label gc;
318
319 // Pop the function info from the stack.
320 __ pop(r3);
321
322 // Attempt to allocate new JSFunction in new space.
323 __ Allocate(JSFunction::kSize, r0, r1, r2, &gc, TAG_OBJECT);
324
325 __ IncrementCounter(counters->fast_new_closure_total(), 1, r6, r7);
326
327 int map_index = Context::FunctionMapIndex(language_mode_, is_generator_);
328
329 // Compute the function map in the current native context and set that
330 // as the map of the allocated object.
331 __ ldr(r2, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
332 __ ldr(r2, FieldMemOperand(r2, GlobalObject::kNativeContextOffset));
333 __ ldr(r5, MemOperand(r2, Context::SlotOffset(map_index)));
334 __ str(r5, FieldMemOperand(r0, HeapObject::kMapOffset));
335
336 // Initialize the rest of the function. We don't have to update the
337 // write barrier because the allocated object is in new space.
338 __ LoadRoot(r1, Heap::kEmptyFixedArrayRootIndex);
339 __ LoadRoot(r5, Heap::kTheHoleValueRootIndex);
340 __ str(r1, FieldMemOperand(r0, JSObject::kPropertiesOffset));
341 __ str(r1, FieldMemOperand(r0, JSObject::kElementsOffset));
342 __ str(r5, FieldMemOperand(r0, JSFunction::kPrototypeOrInitialMapOffset));
343 __ str(r3, FieldMemOperand(r0, JSFunction::kSharedFunctionInfoOffset));
344 __ str(cp, FieldMemOperand(r0, JSFunction::kContextOffset));
345 __ str(r1, FieldMemOperand(r0, JSFunction::kLiteralsOffset));
346
347 // Initialize the code pointer in the function to be the one
348 // found in the shared function info object.
349 // But first check if there is an optimized version for our context.
350 Label check_optimized;
351 Label install_unoptimized;
352 if (FLAG_cache_optimized_code) {
353 __ ldr(r1,
354 FieldMemOperand(r3, SharedFunctionInfo::kOptimizedCodeMapOffset));
355 __ tst(r1, r1);
356 __ b(ne, &check_optimized);
357 }
358 __ bind(&install_unoptimized);
359 __ LoadRoot(r4, Heap::kUndefinedValueRootIndex);
360 __ str(r4, FieldMemOperand(r0, JSFunction::kNextFunctionLinkOffset));
361 __ ldr(r3, FieldMemOperand(r3, SharedFunctionInfo::kCodeOffset));
362 __ add(r3, r3, Operand(Code::kHeaderSize - kHeapObjectTag));
363 __ str(r3, FieldMemOperand(r0, JSFunction::kCodeEntryOffset));
364
365 // Return result. The argument function info has been popped already.
366 __ Ret();
367
368 __ bind(&check_optimized);
369
370 __ IncrementCounter(counters->fast_new_closure_try_optimized(), 1, r6, r7);
371
372 // r2 holds native context, r1 points to fixed array of 3-element entries
373 // (native context, optimized code, literals).
374 // The optimized code map must never be empty, so check the first elements.
375 Label install_optimized;
376 // Speculatively move code object into r4.
377 __ ldr(r4, FieldMemOperand(r1, SharedFunctionInfo::kFirstCodeSlot));
378 __ ldr(r5, FieldMemOperand(r1, SharedFunctionInfo::kFirstContextSlot));
379 __ cmp(r2, r5);
380 __ b(eq, &install_optimized);
381
382 // Iterate through the rest of map backwards. r4 holds an index as a Smi.
383 Label loop;
384 __ ldr(r4, FieldMemOperand(r1, FixedArray::kLengthOffset));
385 __ bind(&loop);
386 // Do not double check first entry.
387 __ cmp(r4, Operand(Smi::FromInt(SharedFunctionInfo::kSecondEntryIndex)));
388 __ b(eq, &install_unoptimized);
389 __ sub(r4, r4, Operand(Smi::FromInt(SharedFunctionInfo::kEntryLength)));
390 __ add(r5, r1, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
391 __ add(r5, r5, Operand::PointerOffsetFromSmiKey(r4));
392 __ ldr(r5, MemOperand(r5));
393 __ cmp(r2, r5);
394 __ b(ne, &loop);
395 // Hit: fetch the optimized code.
396 __ add(r5, r1, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
397 __ add(r5, r5, Operand::PointerOffsetFromSmiKey(r4));
398 __ add(r5, r5, Operand(kPointerSize));
399 __ ldr(r4, MemOperand(r5));
400
401 __ bind(&install_optimized);
402 __ IncrementCounter(counters->fast_new_closure_install_optimized(),
403 1, r6, r7);
404
405 // TODO(fschneider): Idea: store proper code pointers in the map and either
406 // unmangle them on marking or do nothing as the whole map is discarded on
407 // major GC anyway.
408 __ add(r4, r4, Operand(Code::kHeaderSize - kHeapObjectTag));
409 __ str(r4, FieldMemOperand(r0, JSFunction::kCodeEntryOffset));
410
411 // Now link a function into a list of optimized functions.
412 __ ldr(r4, ContextOperand(r2, Context::OPTIMIZED_FUNCTIONS_LIST));
413
414 __ str(r4, FieldMemOperand(r0, JSFunction::kNextFunctionLinkOffset));
415 // No need for write barrier as JSFunction (eax) is in the new space.
416
417 __ str(r0, ContextOperand(r2, Context::OPTIMIZED_FUNCTIONS_LIST));
418 // Store JSFunction (eax) into edx before issuing write barrier as
419 // it clobbers all the registers passed.
420 __ mov(r4, r0);
421 __ RecordWriteContextSlot(
422 r2,
423 Context::SlotOffset(Context::OPTIMIZED_FUNCTIONS_LIST),
424 r4,
425 r1,
426 kLRHasNotBeenSaved,
427 kDontSaveFPRegs);
428
429 // Return result. The argument function info has been popped already.
430 __ Ret();
431
432 // Create a new closure through the slower runtime call.
433 __ bind(&gc);
434 __ LoadRoot(r4, Heap::kFalseValueRootIndex);
435 __ Push(cp, r3, r4);
436 __ TailCallRuntime(Runtime::kNewClosure, 3, 1);
437 }
438
439
440 void FastNewContextStub::Generate(MacroAssembler* masm) { 323 void FastNewContextStub::Generate(MacroAssembler* masm) {
441 // Try to allocate the context in new space. 324 // Try to allocate the context in new space.
442 Label gc; 325 Label gc;
443 int length = slots_ + Context::MIN_CONTEXT_SLOTS; 326 int length = slots_ + Context::MIN_CONTEXT_SLOTS;
444 327
445 // Attempt to allocate the context in new space. 328 // Attempt to allocate the context in new space.
446 __ Allocate(FixedArray::SizeFor(length), r0, r1, r2, &gc, TAG_OBJECT); 329 __ Allocate(FixedArray::SizeFor(length), r0, r1, r2, &gc, TAG_OBJECT);
447 330
448 // Load the function from the stack. 331 // Load the function from the stack.
449 __ ldr(r3, MemOperand(sp, 0)); 332 __ ldr(r3, MemOperand(sp, 0));
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
627 // Compute lower part of fraction (last 12 bits). 510 // Compute lower part of fraction (last 12 bits).
628 __ mov(mantissa, Operand(source_, LSL, HeapNumber::kMantissaBitsInTopWord)); 511 __ mov(mantissa, Operand(source_, LSL, HeapNumber::kMantissaBitsInTopWord));
629 // And the top (top 20 bits). 512 // And the top (top 20 bits).
630 __ orr(exponent, 513 __ orr(exponent,
631 exponent, 514 exponent,
632 Operand(source_, LSR, 32 - HeapNumber::kMantissaBitsInTopWord)); 515 Operand(source_, LSR, 32 - HeapNumber::kMantissaBitsInTopWord));
633 __ Ret(); 516 __ Ret();
634 } 517 }
635 518
636 519
520 void DoubleToIStub::Generate(MacroAssembler* masm) {
521 Label out_of_range, only_low, negate, done;
522 Register input_reg = source();
523 Register result_reg = destination();
524
525 int double_offset = offset();
526 // Account for saved regs if input is sp.
527 if (input_reg.is(sp)) double_offset += 2 * kPointerSize;
528
529 // Immediate values for this stub fit in instructions, so it's safe to use ip.
530 Register scratch = ip;
531 Register scratch_low =
532 GetRegisterThatIsNotOneOf(input_reg, result_reg, scratch);
533 Register scratch_high =
534 GetRegisterThatIsNotOneOf(input_reg, result_reg, scratch, scratch_low);
535 LowDwVfpRegister double_scratch = kScratchDoubleReg;
536
537 __ Push(scratch_high, scratch_low);
538
539 if (!skip_fastpath()) {
540 // Load double input.
541 __ vldr(double_scratch, MemOperand(input_reg, double_offset));
542 __ vmov(scratch_low, scratch_high, double_scratch);
543
544 // Do fast-path convert from double to int.
545 __ vcvt_s32_f64(double_scratch.low(), double_scratch);
546 __ vmov(result_reg, double_scratch.low());
547
548 // If result is not saturated (0x7fffffff or 0x80000000), we are done.
549 __ sub(scratch, result_reg, Operand(1));
550 __ cmp(scratch, Operand(0x7ffffffe));
551 __ b(lt, &done);
552 } else {
553 // We've already done MacroAssembler::TryFastTruncatedDoubleToILoad, so we
554 // know exponent > 31, so we can skip the vcvt_s32_f64 which will saturate.
555 if (double_offset == 0) {
556 __ ldm(ia, input_reg, scratch_low.bit() | scratch_high.bit());
557 } else {
558 __ ldr(scratch_low, MemOperand(input_reg, double_offset));
559 __ ldr(scratch_high, MemOperand(input_reg, double_offset + kIntSize));
560 }
561 }
562
563 __ Ubfx(scratch, scratch_high,
564 HeapNumber::kExponentShift, HeapNumber::kExponentBits);
565 // Load scratch with exponent - 1. This is faster than loading
566 // with exponent because Bias + 1 = 1024 which is an *ARM* immediate value.
567 STATIC_ASSERT(HeapNumber::kExponentBias + 1 == 1024);
568 __ sub(scratch, scratch, Operand(HeapNumber::kExponentBias + 1));
569 // If exponent is greater than or equal to 84, the 32 less significant
570 // bits are 0s (2^84 = 1, 52 significant bits, 32 uncoded bits),
571 // the result is 0.
572 // Compare exponent with 84 (compare exponent - 1 with 83).
573 __ cmp(scratch, Operand(83));
574 __ b(ge, &out_of_range);
575
576 // If we reach this code, 31 <= exponent <= 83.
577 // So, we don't have to handle cases where 0 <= exponent <= 20 for
578 // which we would need to shift right the high part of the mantissa.
579 // Scratch contains exponent - 1.
580 // Load scratch with 52 - exponent (load with 51 - (exponent - 1)).
581 __ rsb(scratch, scratch, Operand(51), SetCC);
582 __ b(ls, &only_low);
583 // 21 <= exponent <= 51, shift scratch_low and scratch_high
584 // to generate the result.
585 __ mov(scratch_low, Operand(scratch_low, LSR, scratch));
586 // Scratch contains: 52 - exponent.
587 // We needs: exponent - 20.
588 // So we use: 32 - scratch = 32 - 52 + exponent = exponent - 20.
589 __ rsb(scratch, scratch, Operand(32));
590 __ Ubfx(result_reg, scratch_high,
591 0, HeapNumber::kMantissaBitsInTopWord);
592 // Set the implicit 1 before the mantissa part in scratch_high.
593 __ orr(result_reg, result_reg,
594 Operand(1 << HeapNumber::kMantissaBitsInTopWord));
595 __ orr(result_reg, scratch_low, Operand(result_reg, LSL, scratch));
596 __ b(&negate);
597
598 __ bind(&out_of_range);
599 __ mov(result_reg, Operand::Zero());
600 __ b(&done);
601
602 __ bind(&only_low);
603 // 52 <= exponent <= 83, shift only scratch_low.
604 // On entry, scratch contains: 52 - exponent.
605 __ rsb(scratch, scratch, Operand::Zero());
606 __ mov(result_reg, Operand(scratch_low, LSL, scratch));
607
608 __ bind(&negate);
609 // If input was positive, scratch_high ASR 31 equals 0 and
610 // scratch_high LSR 31 equals zero.
611 // New result = (result eor 0) + 0 = result.
612 // If the input was negative, we have to negate the result.
613 // Input_high ASR 31 equals 0xffffffff and scratch_high LSR 31 equals 1.
614 // New result = (result eor 0xffffffff) + 1 = 0 - result.
615 __ eor(result_reg, result_reg, Operand(scratch_high, ASR, 31));
616 __ add(result_reg, result_reg, Operand(scratch_high, LSR, 31));
617
618 __ bind(&done);
619
620 __ Pop(scratch_high, scratch_low);
621 __ Ret();
622 }
623
624
637 bool WriteInt32ToHeapNumberStub::IsPregenerated() { 625 bool WriteInt32ToHeapNumberStub::IsPregenerated() {
638 // These variants are compiled ahead of time. See next method. 626 // These variants are compiled ahead of time. See next method.
639 if (the_int_.is(r1) && the_heap_number_.is(r0) && scratch_.is(r2)) { 627 if (the_int_.is(r1) && the_heap_number_.is(r0) && scratch_.is(r2)) {
640 return true; 628 return true;
641 } 629 }
642 if (the_int_.is(r2) && the_heap_number_.is(r0) && scratch_.is(r3)) { 630 if (the_int_.is(r2) && the_heap_number_.is(r0) && scratch_.is(r3)) {
643 return true; 631 return true;
644 } 632 }
645 // Other register combinations are generated as and when they are needed, 633 // Other register combinations are generated as and when they are needed,
646 // so it is unsafe to call them from stubs (we can't generate a stub while 634 // so it is unsafe to call them from stubs (we can't generate a stub while
(...skipping 937 matching lines...) Expand 10 before | Expand all | Expand 10 after
1584 bool smi_operands, 1572 bool smi_operands,
1585 Label* not_numbers, 1573 Label* not_numbers,
1586 Label* gc_required, 1574 Label* gc_required,
1587 Label* miss, 1575 Label* miss,
1588 Token::Value op, 1576 Token::Value op,
1589 OverwriteMode mode) { 1577 OverwriteMode mode) {
1590 Register left = r1; 1578 Register left = r1;
1591 Register right = r0; 1579 Register right = r0;
1592 Register scratch1 = r6; 1580 Register scratch1 = r6;
1593 Register scratch2 = r7; 1581 Register scratch2 = r7;
1594 Register scratch3 = r4;
1595 1582
1596 ASSERT(smi_operands || (not_numbers != NULL)); 1583 ASSERT(smi_operands || (not_numbers != NULL));
1597 if (smi_operands) { 1584 if (smi_operands) {
1598 __ AssertSmi(left); 1585 __ AssertSmi(left);
1599 __ AssertSmi(right); 1586 __ AssertSmi(right);
1600 } 1587 }
1601 if (left_type == BinaryOpIC::SMI) { 1588 if (left_type == BinaryOpIC::SMI) {
1602 __ JumpIfNotSmi(left, miss); 1589 __ JumpIfNotSmi(left, miss);
1603 } 1590 }
1604 if (right_type == BinaryOpIC::SMI) { 1591 if (right_type == BinaryOpIC::SMI) {
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
1682 case Token::BIT_XOR: 1669 case Token::BIT_XOR:
1683 case Token::BIT_AND: 1670 case Token::BIT_AND:
1684 case Token::SAR: 1671 case Token::SAR:
1685 case Token::SHR: 1672 case Token::SHR:
1686 case Token::SHL: { 1673 case Token::SHL: {
1687 if (smi_operands) { 1674 if (smi_operands) {
1688 __ SmiUntag(r3, left); 1675 __ SmiUntag(r3, left);
1689 __ SmiUntag(r2, right); 1676 __ SmiUntag(r2, right);
1690 } else { 1677 } else {
1691 // Convert operands to 32-bit integers. Right in r2 and left in r3. 1678 // Convert operands to 32-bit integers. Right in r2 and left in r3.
1692 __ ConvertNumberToInt32( 1679 __ TruncateNumberToI(left, r3, heap_number_map, scratch1, not_numbers);
1693 left, r3, heap_number_map, 1680 __ TruncateNumberToI(right, r2, heap_number_map, scratch1, not_numbers);
1694 scratch1, scratch2, scratch3, d0, d1, not_numbers);
1695 __ ConvertNumberToInt32(
1696 right, r2, heap_number_map,
1697 scratch1, scratch2, scratch3, d0, d1, not_numbers);
1698 } 1681 }
1699 1682
1700 Label result_not_a_smi; 1683 Label result_not_a_smi;
1701 switch (op) { 1684 switch (op) {
1702 case Token::BIT_OR: 1685 case Token::BIT_OR:
1703 __ orr(r2, r3, Operand(r2)); 1686 __ orr(r2, r3, Operand(r2));
1704 break; 1687 break;
1705 case Token::BIT_XOR: 1688 case Token::BIT_XOR:
1706 __ eor(r2, r3, Operand(r2)); 1689 __ eor(r2, r3, Operand(r2));
1707 break; 1690 break;
(...skipping 5455 matching lines...) Expand 10 before | Expand all | Expand 10 after
7163 __ bind(&fast_elements_case); 7146 __ bind(&fast_elements_case);
7164 GenerateCase(masm, FAST_ELEMENTS); 7147 GenerateCase(masm, FAST_ELEMENTS);
7165 } 7148 }
7166 7149
7167 7150
7168 #undef __ 7151 #undef __
7169 7152
7170 } } // namespace v8::internal 7153 } } // namespace v8::internal
7171 7154
7172 #endif // V8_TARGET_ARCH_ARM 7155 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « src/arm/code-stubs-arm.h ('k') | src/arm/cpu-arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698