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

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

Issue 1250733005: SIMD.js Add the other SIMD Phase 1 types. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Make _IsSimdObject an assembly intrinsic in fullcodegen. Created 5 years, 4 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
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/v8.h" 5 #include "src/v8.h"
6 6
7 #if V8_TARGET_ARCH_ARM64 7 #if V8_TARGET_ARCH_ARM64
8 8
9 #include "src/bootstrapper.h" 9 #include "src/bootstrapper.h"
10 #include "src/code-stubs.h" 10 #include "src/code-stubs.h"
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
214 214
215 __ Cmp(right, left); 215 __ Cmp(right, left);
216 __ B(ne, &not_identical); 216 __ B(ne, &not_identical);
217 217
218 // Test for NaN. Sadly, we can't just compare to factory::nan_value(), 218 // Test for NaN. Sadly, we can't just compare to factory::nan_value(),
219 // so we do the second best thing - test it ourselves. 219 // so we do the second best thing - test it ourselves.
220 // They are both equal and they are not both Smis so both of them are not 220 // They are both equal and they are not both Smis so both of them are not
221 // Smis. If it's not a heap number, then return equal. 221 // Smis. If it's not a heap number, then return equal.
222 Register right_type = scratch; 222 Register right_type = scratch;
223 if ((cond == lt) || (cond == gt)) { 223 if ((cond == lt) || (cond == gt)) {
224 Label not_simd;
224 // Call runtime on identical JSObjects. Otherwise return equal. 225 // Call runtime on identical JSObjects. Otherwise return equal.
225 __ JumpIfObjectType(right, right_type, right_type, FIRST_SPEC_OBJECT_TYPE, 226 __ JumpIfObjectType(right, right_type, right_type, FIRST_SPEC_OBJECT_TYPE,
226 slow, ge); 227 slow, ge);
227 // Call runtime on identical symbols since we need to throw a TypeError. 228 // Call runtime on identical symbols since we need to throw a TypeError.
228 __ Cmp(right_type, SYMBOL_TYPE); 229 __ Cmp(right_type, SYMBOL_TYPE);
229 __ B(eq, slow); 230 __ B(eq, slow);
230 // Call runtime on identical SIMD values since we must throw a TypeError. 231 // Call runtime on identical SIMD values since we must throw a TypeError.
231 __ Cmp(right_type, FLOAT32X4_TYPE); 232 __ Cmp(right_type, FIRST_SIMD_VALUE_TYPE);
232 __ B(eq, slow); 233 __ B(lt, &not_simd);
234 __ Cmp(right_type, LAST_SIMD_VALUE_TYPE);
235 __ B(le, slow);
236 __ Bind(&not_simd);
233 if (is_strong(strength)) { 237 if (is_strong(strength)) {
234 // Call the runtime on anything that is converted in the semantics, since 238 // Call the runtime on anything that is converted in the semantics, since
235 // we need to throw a TypeError. Smis have already been ruled out. 239 // we need to throw a TypeError. Smis have already been ruled out.
236 __ Cmp(right_type, Operand(HEAP_NUMBER_TYPE)); 240 __ Cmp(right_type, Operand(HEAP_NUMBER_TYPE));
237 __ B(eq, &return_equal); 241 __ B(eq, &return_equal);
238 __ Tst(right_type, Operand(kIsNotStringMask)); 242 __ Tst(right_type, Operand(kIsNotStringMask));
239 __ B(ne, slow); 243 __ B(ne, slow);
240 } 244 }
241 } else if (cond == eq) { 245 } else if (cond == eq) {
242 __ JumpIfHeapNumber(right, &heap_number); 246 __ JumpIfHeapNumber(right, &heap_number);
243 } else { 247 } else {
248 Label not_simd;
244 __ JumpIfObjectType(right, right_type, right_type, HEAP_NUMBER_TYPE, 249 __ JumpIfObjectType(right, right_type, right_type, HEAP_NUMBER_TYPE,
245 &heap_number); 250 &heap_number);
246 // Comparing JS objects with <=, >= is complicated. 251 // Comparing JS objects with <=, >= is complicated.
247 __ Cmp(right_type, FIRST_SPEC_OBJECT_TYPE); 252 __ Cmp(right_type, FIRST_SPEC_OBJECT_TYPE);
248 __ B(ge, slow); 253 __ B(ge, slow);
249 // Call runtime on identical symbols since we need to throw a TypeError. 254 // Call runtime on identical symbols since we need to throw a TypeError.
250 __ Cmp(right_type, SYMBOL_TYPE); 255 __ Cmp(right_type, SYMBOL_TYPE);
251 __ B(eq, slow); 256 __ B(eq, slow);
252 // Call runtime on identical SIMD values since we must throw a TypeError. 257 // Call runtime on identical SIMD values since we must throw a TypeError.
253 __ Cmp(right_type, FLOAT32X4_TYPE); 258 __ Cmp(right_type, FIRST_SIMD_VALUE_TYPE);
254 __ B(eq, slow); 259 __ B(lt, &not_simd);
260 __ Cmp(right_type, LAST_SIMD_VALUE_TYPE);
261 __ B(le, slow);
262 __ Bind(&not_simd);
255 if (is_strong(strength)) { 263 if (is_strong(strength)) {
256 // Call the runtime on anything that is converted in the semantics, 264 // Call the runtime on anything that is converted in the semantics,
257 // since we need to throw a TypeError. Smis and heap numbers have 265 // since we need to throw a TypeError. Smis and heap numbers have
258 // already been ruled out. 266 // already been ruled out.
259 __ Tst(right_type, Operand(kIsNotStringMask)); 267 __ Tst(right_type, Operand(kIsNotStringMask));
260 __ B(ne, slow); 268 __ B(ne, slow);
261 } 269 }
262 // Normally here we fall through to return_equal, but undefined is 270 // Normally here we fall through to return_equal, but undefined is
263 // special: (undefined == undefined) == true, but 271 // special: (undefined == undefined) == true, but
264 // (undefined <= undefined) == false! See ECMAScript 11.8.5. 272 // (undefined <= undefined) == false! See ECMAScript 11.8.5.
(...skipping 5226 matching lines...) Expand 10 before | Expand all | Expand 10 after
5491 5499
5492 __ Bind(&fast_elements_case); 5500 __ Bind(&fast_elements_case);
5493 GenerateCase(masm, FAST_ELEMENTS); 5501 GenerateCase(masm, FAST_ELEMENTS);
5494 } 5502 }
5495 5503
5496 5504
5497 void LoadGlobalViaContextStub::Generate(MacroAssembler* masm) { 5505 void LoadGlobalViaContextStub::Generate(MacroAssembler* masm) {
5498 Register context = cp; 5506 Register context = cp;
5499 Register result = x0; 5507 Register result = x0;
5500 Register slot = x2; 5508 Register slot = x2;
5509 Register name = x3;
5501 Label slow_case; 5510 Label slow_case;
5502 5511
5503 // Go up the context chain to the script context. 5512 // Go up the context chain to the script context.
5504 for (int i = 0; i < depth(); ++i) { 5513 for (int i = 0; i < depth(); ++i) {
5505 __ Ldr(result, ContextMemOperand(context, Context::PREVIOUS_INDEX)); 5514 __ Ldr(result, ContextMemOperand(context, Context::PREVIOUS_INDEX));
5506 context = result; 5515 context = result;
5507 } 5516 }
5508 5517
5509 // Load the PropertyCell value at the specified slot. 5518 // Load the PropertyCell value at the specified slot.
5510 __ Add(result, context, Operand(slot, LSL, kPointerSizeLog2)); 5519 __ Add(result, context, Operand(slot, LSL, kPointerSizeLog2));
5511 __ Ldr(result, ContextMemOperand(result)); 5520 __ Ldr(result, ContextMemOperand(result));
5512 __ Ldr(result, FieldMemOperand(result, PropertyCell::kValueOffset)); 5521 __ Ldr(result, FieldMemOperand(result, PropertyCell::kValueOffset));
5513 5522
5514 // If the result is not the_hole, return. Otherwise, handle in the runtime. 5523 // If the result is not the_hole, return. Otherwise, handle in the runtime.
5515 __ JumpIfRoot(result, Heap::kTheHoleValueRootIndex, &slow_case); 5524 __ JumpIfRoot(result, Heap::kTheHoleValueRootIndex, &slow_case);
5516 __ Ret(); 5525 __ Ret();
5517 5526
5518 // Fallback to runtime. 5527 // Fallback to runtime.
5519 __ Bind(&slow_case); 5528 __ Bind(&slow_case);
5520 __ SmiTag(slot); 5529 __ SmiTag(slot);
5521 __ Push(slot); 5530 __ Push(slot, name);
5522 __ TailCallRuntime(Runtime::kLoadGlobalViaContext, 1, 1); 5531 __ TailCallRuntime(Runtime::kLoadGlobalViaContext, 2, 1);
5523 } 5532 }
5524 5533
5525 5534
5526 void StoreGlobalViaContextStub::Generate(MacroAssembler* masm) { 5535 void StoreGlobalViaContextStub::Generate(MacroAssembler* masm) {
5527 Register context = cp; 5536 Register context = cp;
5528 Register value = x0; 5537 Register value = x0;
5529 Register slot = x2; 5538 Register slot = x2;
5539 Register name = x3;
5530 Register context_temp = x10; 5540 Register context_temp = x10;
5531 Register cell = x10; 5541 Register cell = x10;
5532 Register cell_details = x11; 5542 Register cell_details = x11;
5533 Register cell_value = x12; 5543 Register cell_value = x12;
5534 Register cell_value_map = x13; 5544 Register cell_value_map = x13;
5535 Register value_map = x14; 5545 Register value_map = x14;
5536 Label fast_heapobject_case, fast_smi_case, slow_case; 5546 Label fast_heapobject_case, fast_smi_case, slow_case;
5537 5547
5538 if (FLAG_debug_code) { 5548 if (FLAG_debug_code) {
5539 __ CompareRoot(value, Heap::kTheHoleValueRootIndex); 5549 __ CompareRoot(value, Heap::kTheHoleValueRootIndex);
5540 __ Check(ne, kUnexpectedValue); 5550 __ Check(ne, kUnexpectedValue);
5551 __ AssertName(name);
5541 } 5552 }
5542 5553
5543 // Go up the context chain to the script context. 5554 // Go up the context chain to the script context.
5544 for (int i = 0; i < depth(); i++) { 5555 for (int i = 0; i < depth(); i++) {
5545 __ Ldr(context_temp, ContextMemOperand(context, Context::PREVIOUS_INDEX)); 5556 __ Ldr(context_temp, ContextMemOperand(context, Context::PREVIOUS_INDEX));
5546 context = context_temp; 5557 context = context_temp;
5547 } 5558 }
5548 5559
5549 // Load the PropertyCell at the specified slot. 5560 // Load the PropertyCell at the specified slot.
5550 __ Add(cell, context, Operand(slot, LSL, kPointerSizeLog2)); 5561 __ Add(cell, context, Operand(slot, LSL, kPointerSizeLog2));
5551 __ Ldr(cell, ContextMemOperand(cell)); 5562 __ Ldr(cell, ContextMemOperand(cell));
5552 5563
5553 // Load PropertyDetails for the cell (actually only the cell_type and kind). 5564 // Load PropertyDetails for the cell (actually only the cell_type and kind).
5554 __ Ldr(cell_details, 5565 __ Ldr(cell_details,
5555 UntagSmiFieldMemOperand(cell, PropertyCell::kDetailsOffset)); 5566 UntagSmiFieldMemOperand(cell, PropertyCell::kDetailsOffset));
5556 __ And(cell_details, cell_details, 5567 __ And(cell_details, cell_details,
5557 PropertyDetails::PropertyCellTypeField::kMask | 5568 PropertyDetails::PropertyCellTypeField::kMask |
5558 PropertyDetails::KindField::kMask | 5569 PropertyDetails::KindField::kMask);
5559 PropertyDetails::kAttributesReadOnlyMask);
5560 5570
5561 // Check if PropertyCell holds mutable data. 5571 // Check if PropertyCell holds mutable data.
5562 Label not_mutable_data; 5572 Label not_mutable_data;
5563 __ Cmp(cell_details, PropertyDetails::PropertyCellTypeField::encode( 5573 __ Cmp(cell_details, PropertyDetails::PropertyCellTypeField::encode(
5564 PropertyCellType::kMutable) | 5574 PropertyCellType::kMutable) |
5565 PropertyDetails::KindField::encode(kData)); 5575 PropertyDetails::KindField::encode(kData));
5566 __ B(ne, &not_mutable_data); 5576 __ B(ne, &not_mutable_data);
5567 __ JumpIfSmi(value, &fast_smi_case); 5577 __ JumpIfSmi(value, &fast_smi_case);
5568 __ Bind(&fast_heapobject_case); 5578 __ Bind(&fast_heapobject_case);
5569 __ Str(value, FieldMemOperand(cell, PropertyCell::kValueOffset)); 5579 __ Str(value, FieldMemOperand(cell, PropertyCell::kValueOffset));
5570 // RecordWriteField clobbers the value register, so we copy it before the 5580 // RecordWriteField clobbers the value register, so we copy it before the
5571 // call. 5581 // call.
5572 __ Mov(x11, value); 5582 __ Mov(x11, value);
5573 __ RecordWriteField(cell, PropertyCell::kValueOffset, x11, x12, 5583 __ RecordWriteField(cell, PropertyCell::kValueOffset, x11, x12,
5574 kLRHasNotBeenSaved, kDontSaveFPRegs, EMIT_REMEMBERED_SET, 5584 kLRHasNotBeenSaved, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
5575 OMIT_SMI_CHECK); 5585 OMIT_SMI_CHECK);
5576 __ Ret(); 5586 __ Ret();
5577 5587
5578 __ Bind(&not_mutable_data); 5588 __ Bind(&not_mutable_data);
5579 // Check if PropertyCell value matches the new value (relevant for Constant, 5589 // Check if PropertyCell value matches the new value (relevant for Constant,
5580 // ConstantType and Undefined cells). 5590 // ConstantType and Undefined cells).
5581 Label not_same_value; 5591 Label not_same_value;
5582 __ Ldr(cell_value, FieldMemOperand(cell, PropertyCell::kValueOffset)); 5592 __ Ldr(cell_value, FieldMemOperand(cell, PropertyCell::kValueOffset));
5583 __ Cmp(cell_value, value); 5593 __ Cmp(cell_value, value);
5584 __ B(ne, &not_same_value); 5594 __ B(ne, &not_same_value);
5585 5595
5586 // Make sure the PropertyCell is not marked READ_ONLY.
5587 __ Tst(cell_details, PropertyDetails::kAttributesReadOnlyMask);
5588 __ B(ne, &slow_case);
5589
5590 if (FLAG_debug_code) { 5596 if (FLAG_debug_code) {
5591 Label done; 5597 Label done;
5592 // This can only be true for Constant, ConstantType and Undefined cells, 5598 // This can only be true for Constant, ConstantType and Undefined cells,
5593 // because we never store the_hole via this stub. 5599 // because we never store the_hole via this stub.
5594 __ Cmp(cell_details, PropertyDetails::PropertyCellTypeField::encode( 5600 __ Cmp(cell_details, PropertyDetails::PropertyCellTypeField::encode(
5595 PropertyCellType::kConstant) | 5601 PropertyCellType::kConstant) |
5596 PropertyDetails::KindField::encode(kData)); 5602 PropertyDetails::KindField::encode(kData));
5597 __ B(eq, &done); 5603 __ B(eq, &done);
5598 __ Cmp(cell_details, PropertyDetails::PropertyCellTypeField::encode( 5604 __ Cmp(cell_details, PropertyDetails::PropertyCellTypeField::encode(
5599 PropertyCellType::kConstantType) | 5605 PropertyCellType::kConstantType) |
5600 PropertyDetails::KindField::encode(kData)); 5606 PropertyDetails::KindField::encode(kData));
5601 __ B(eq, &done); 5607 __ B(eq, &done);
5602 __ Cmp(cell_details, PropertyDetails::PropertyCellTypeField::encode( 5608 __ Cmp(cell_details, PropertyDetails::PropertyCellTypeField::encode(
5603 PropertyCellType::kUndefined) | 5609 PropertyCellType::kUndefined) |
5604 PropertyDetails::KindField::encode(kData)); 5610 PropertyDetails::KindField::encode(kData));
5605 __ Check(eq, kUnexpectedValue); 5611 __ Check(eq, kUnexpectedValue);
5606 __ Bind(&done); 5612 __ Bind(&done);
5607 } 5613 }
5608 __ Ret(); 5614 __ Ret();
5609 __ Bind(&not_same_value); 5615 __ Bind(&not_same_value);
5610 5616
5611 // Check if PropertyCell contains data with constant type (and is not 5617 // Check if PropertyCell contains data with constant type.
5612 // READ_ONLY).
5613 __ Cmp(cell_details, PropertyDetails::PropertyCellTypeField::encode( 5618 __ Cmp(cell_details, PropertyDetails::PropertyCellTypeField::encode(
5614 PropertyCellType::kConstantType) | 5619 PropertyCellType::kConstantType) |
5615 PropertyDetails::KindField::encode(kData)); 5620 PropertyDetails::KindField::encode(kData));
5616 __ B(ne, &slow_case); 5621 __ B(ne, &slow_case);
5617 5622
5618 // Now either both old and new values must be smis or both must be heap 5623 // Now either both old and new values must be smis or both must be heap
5619 // objects with same map. 5624 // objects with same map.
5620 Label value_is_heap_object; 5625 Label value_is_heap_object;
5621 __ JumpIfNotSmi(value, &value_is_heap_object); 5626 __ JumpIfNotSmi(value, &value_is_heap_object);
5622 __ JumpIfNotSmi(cell_value, &slow_case); 5627 __ JumpIfNotSmi(cell_value, &slow_case);
5623 // Old and new values are smis, no need for a write barrier here. 5628 // Old and new values are smis, no need for a write barrier here.
5624 __ Bind(&fast_smi_case); 5629 __ Bind(&fast_smi_case);
5625 __ Str(value, FieldMemOperand(cell, PropertyCell::kValueOffset)); 5630 __ Str(value, FieldMemOperand(cell, PropertyCell::kValueOffset));
5626 __ Ret(); 5631 __ Ret();
5627 5632
5628 __ Bind(&value_is_heap_object); 5633 __ Bind(&value_is_heap_object);
5629 __ JumpIfSmi(cell_value, &slow_case); 5634 __ JumpIfSmi(cell_value, &slow_case);
5630 5635
5631 __ Ldr(cell_value_map, FieldMemOperand(cell_value, HeapObject::kMapOffset)); 5636 __ Ldr(cell_value_map, FieldMemOperand(cell_value, HeapObject::kMapOffset));
5632 __ Ldr(value_map, FieldMemOperand(value, HeapObject::kMapOffset)); 5637 __ Ldr(value_map, FieldMemOperand(value, HeapObject::kMapOffset));
5633 __ Cmp(cell_value_map, value_map); 5638 __ Cmp(cell_value_map, value_map);
5634 __ B(eq, &fast_heapobject_case); 5639 __ B(eq, &fast_heapobject_case);
5635 5640
5636 // Fall back to the runtime. 5641 // Fall back to the runtime.
5637 __ Bind(&slow_case); 5642 __ Bind(&slow_case);
5638 __ SmiTag(slot); 5643 __ SmiTag(slot);
5639 __ Push(slot, value); 5644 __ Push(slot, name, value);
5640 __ TailCallRuntime(is_strict(language_mode()) 5645 __ TailCallRuntime(is_strict(language_mode())
5641 ? Runtime::kStoreGlobalViaContext_Strict 5646 ? Runtime::kStoreGlobalViaContext_Strict
5642 : Runtime::kStoreGlobalViaContext_Sloppy, 5647 : Runtime::kStoreGlobalViaContext_Sloppy,
5643 2, 1); 5648 3, 1);
5644 } 5649 }
5645 5650
5646 5651
5647 // The number of register that CallApiFunctionAndReturn will need to save on 5652 // The number of register that CallApiFunctionAndReturn will need to save on
5648 // the stack. The space for these registers need to be allocated in the 5653 // the stack. The space for these registers need to be allocated in the
5649 // ExitFrame before calling CallApiFunctionAndReturn. 5654 // ExitFrame before calling CallApiFunctionAndReturn.
5650 static const int kCallApiFunctionSpillSpace = 4; 5655 static const int kCallApiFunctionSpillSpace = 4;
5651 5656
5652 5657
5653 static int AddressOffset(ExternalReference ref0, ExternalReference ref1) { 5658 static int AddressOffset(ExternalReference ref0, ExternalReference ref1) {
(...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after
5987 MemOperand(fp, 6 * kPointerSize), NULL); 5992 MemOperand(fp, 6 * kPointerSize), NULL);
5988 } 5993 }
5989 5994
5990 5995
5991 #undef __ 5996 #undef __
5992 5997
5993 } // namespace internal 5998 } // namespace internal
5994 } // namespace v8 5999 } // namespace v8
5995 6000
5996 #endif // V8_TARGET_ARCH_ARM64 6001 #endif // V8_TARGET_ARCH_ARM64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698