OLD | NEW |
---|---|
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 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/builtins/builtins-utils.h" | 5 #include "src/builtins/builtins-utils.h" |
6 #include "src/builtins/builtins.h" | 6 #include "src/builtins/builtins.h" |
7 #include "src/code-factory.h" | 7 #include "src/code-factory.h" |
8 #include "src/code-stub-assembler.h" | 8 #include "src/code-stub-assembler.h" |
9 | 9 |
10 namespace v8 { | 10 namespace v8 { |
11 namespace internal { | 11 namespace internal { |
12 | 12 |
13 #define CHECK_IS_SHARED_ARRAY_BUFFER(name, method) \ | |
14 if (!name->is_shared()) { \ | |
15 THROW_NEW_ERROR_RETURN_FAILURE( \ | |
16 isolate, \ | |
17 NewTypeError(MessageTemplate::kIncompatibleMethodReceiver, \ | |
18 isolate->factory()->NewStringFromAsciiChecked(method), \ | |
19 name)); \ | |
20 } | |
21 | |
13 using compiler::Node; | 22 using compiler::Node; |
14 | 23 |
15 class SharedArrayBufferBuiltinsAssembler : public CodeStubAssembler { | 24 class SharedArrayBufferBuiltinsAssembler : public CodeStubAssembler { |
16 public: | 25 public: |
17 explicit SharedArrayBufferBuiltinsAssembler( | 26 explicit SharedArrayBufferBuiltinsAssembler( |
18 compiler::CodeAssemblerState* state) | 27 compiler::CodeAssemblerState* state) |
19 : CodeStubAssembler(state) {} | 28 : CodeStubAssembler(state) {} |
20 | 29 |
21 protected: | 30 protected: |
22 void ValidateSharedTypedArray(Node* tagged, Node* context, | 31 void ValidateSharedTypedArray(Node* tagged, Node* context, |
23 Node** out_instance_type, | 32 Node** out_instance_type, |
24 Node** out_backing_store); | 33 Node** out_backing_store); |
25 Node* ConvertTaggedAtomicIndexToWord32(Node* tagged, Node* context, | 34 Node* ConvertTaggedAtomicIndexToWord32(Node* tagged, Node* context, |
26 Node** number_index); | 35 Node** number_index); |
27 void ValidateAtomicIndex(Node* index_word, Node* array_length_word, | 36 void ValidateAtomicIndex(Node* index_word, Node* array_length_word, |
28 Node* context); | 37 Node* context); |
29 }; | 38 }; |
30 | 39 |
31 // ES7 sharedmem 6.3.4.1 get SharedArrayBuffer.prototype.byteLength | 40 // ES7 sharedmem 6.3.4.1 get SharedArrayBuffer.prototype.byteLength |
32 BUILTIN(SharedArrayBufferPrototypeGetByteLength) { | 41 BUILTIN(SharedArrayBufferPrototypeGetByteLength) { |
42 const char* const kMethodName = "get SharedArrayBuffer.prototype.byteLength"; | |
33 HandleScope scope(isolate); | 43 HandleScope scope(isolate); |
34 CHECK_RECEIVER(JSArrayBuffer, array_buffer, | 44 CHECK_RECEIVER(JSArrayBuffer, array_buffer, |
35 "get SharedArrayBuffer.prototype.byteLength"); | 45 "get SharedArrayBuffer.prototype.byteLength"); |
36 if (!array_buffer->is_shared()) { | 46 CHECK_IS_SHARED_ARRAY_BUFFER(array_buffer, kMethodName); |
37 THROW_NEW_ERROR_RETURN_FAILURE( | |
38 isolate, NewTypeError(MessageTemplate::kIncompatibleMethodReceiver, | |
39 isolate->factory()->NewStringFromAsciiChecked( | |
40 "get SharedArrayBuffer.prototype.byteLength"), | |
41 args.receiver())); | |
42 } | |
43 return array_buffer->byte_length(); | 47 return array_buffer->byte_length(); |
44 } | 48 } |
45 | 49 |
50 // ES #sec-sharedarraybuffer.prototype.slice | |
51 // SharedArrayBuffer.prototype.slice ( start, end ) | |
52 BUILTIN(SharedArrayBufferPrototypeSlice) { | |
Dan Ehrenberg
2017/03/16 07:45:06
Would it be possible to reuse most of the implemen
binji
2017/03/16 16:17:00
I thought so at first, but there are enough differ
Dan Ehrenberg
2017/03/17 10:30:44
Well, I'd still would prefer for it to be de-dupli
| |
53 const char* const kMethodName = "SharedArrayBuffer.prototype.slice"; | |
54 HandleScope scope(isolate); | |
55 Handle<Object> start = args.at(1); | |
56 Handle<Object> end = args.atOrUndefined(isolate, 2); | |
57 | |
58 // 2. If Type(O) is not Object, throw a TypeError exception. | |
59 // 3. If O does not have an [[ArrayBufferData]] internal slot, throw a | |
60 // TypeError exception. | |
61 CHECK_RECEIVER(JSArrayBuffer, array_buffer, kMethodName); | |
62 // 4. If IsSharedArrayBuffer(O) is false, throw a TypeError exception. | |
63 CHECK_IS_SHARED_ARRAY_BUFFER(array_buffer, kMethodName); | |
64 | |
65 // 5. Let len be O.[[ArrayBufferByteLength]]. | |
66 double const len = array_buffer->byte_length()->Number(); | |
67 | |
68 // 6. Let relativeStart be ? ToInteger(start). | |
69 Handle<Object> relative_start; | |
70 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, relative_start, | |
71 Object::ToInteger(isolate, start)); | |
72 | |
73 // 7. If relativeStart < 0, let first be max((len + relativeStart), 0); else | |
74 // let first be min(relativeStart, len). | |
75 double const first = (relative_start->Number() < 0) | |
76 ? Max(len + relative_start->Number(), 0.0) | |
77 : Min(relative_start->Number(), len); | |
78 Handle<Object> first_obj = isolate->factory()->NewNumber(first); | |
79 | |
80 // 8. If end is undefined, let relativeEnd be len; else let relativeEnd be ? | |
81 // ToInteger(end). | |
82 double relative_end; | |
83 if (end->IsUndefined(isolate)) { | |
84 relative_end = len; | |
85 } else { | |
86 Handle<Object> relative_end_obj; | |
87 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, relative_end_obj, | |
88 Object::ToInteger(isolate, end)); | |
89 relative_end = relative_end_obj->Number(); | |
90 } | |
91 | |
92 // 9. If relativeEnd < 0, let final be max((len + relativeEnd), 0); else let | |
93 // final be min(relativeEnd, len). | |
94 double const final_ = (relative_end < 0) ? Max(len + relative_end, 0.0) | |
95 : Min(relative_end, len); | |
96 | |
97 // 10. Let newLen be max(final-first, 0). | |
98 double const new_len = Max(final_ - first, 0.0); | |
99 Handle<Object> new_len_obj = isolate->factory()->NewNumber(new_len); | |
100 | |
101 // 11. Let ctor be ? SpeciesConstructor(O, %SharedArrayBuffer%). | |
102 Handle<JSFunction> sharedarraybuffer_fun = isolate->shared_array_buffer_fun(); | |
103 Handle<Object> ctor; | |
104 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | |
105 isolate, ctor, | |
106 Object::SpeciesConstructor(isolate, | |
107 Handle<JSReceiver>::cast(args.receiver()), | |
108 sharedarraybuffer_fun)); | |
109 | |
110 // 12. Let new be ? Construct(ctor, newLen). | |
111 Handle<JSReceiver> new_; | |
112 { | |
113 const int argc = 1; | |
114 | |
115 ScopedVector<Handle<Object>> argv(argc); | |
116 argv[0] = new_len_obj; | |
117 | |
118 Handle<Object> new_obj; | |
119 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | |
120 isolate, new_obj, | |
121 Execution::New(Handle<JSFunction>::cast(ctor), argc, argv.start())); | |
122 | |
123 new_ = Handle<JSReceiver>::cast(new_obj); | |
124 } | |
125 | |
126 // 13. If new does not have an [[ArrayBufferData]] internal slot, throw a | |
127 // TypeError exception. | |
128 if (!new_->IsJSArrayBuffer()) { | |
129 THROW_NEW_ERROR_RETURN_FAILURE( | |
130 isolate, | |
131 NewTypeError(MessageTemplate::kIncompatibleMethodReceiver, | |
132 isolate->factory()->NewStringFromAsciiChecked(kMethodName), | |
133 new_)); | |
134 } | |
135 | |
136 // 14. If IsSharedArrayBuffer(new) is false, throw a TypeError exception. | |
137 Handle<JSArrayBuffer> new_array_buffer = Handle<JSArrayBuffer>::cast(new_); | |
138 CHECK_IS_SHARED_ARRAY_BUFFER(new_array_buffer, kMethodName); | |
139 | |
140 // 15. If new.[[ArrayBufferData]] and O.[[ArrayBufferData]] are the same | |
141 // Shared Data Block values, throw a TypeError exception. | |
142 if (new_array_buffer->backing_store() == array_buffer->backing_store()) { | |
143 THROW_NEW_ERROR_RETURN_FAILURE( | |
144 isolate, NewTypeError(MessageTemplate::kSharedArrayBufferSpeciesThis)); | |
145 } | |
146 | |
147 // 16. If new.[[ArrayBufferByteLength]] < newLen, throw a TypeError exception. | |
148 if (new_array_buffer->byte_length()->Number() < new_len) { | |
149 THROW_NEW_ERROR_RETURN_FAILURE( | |
150 isolate, NewTypeError(MessageTemplate::kSharedArrayBufferTooShort)); | |
151 } | |
152 | |
153 // 17. Let fromBuf be O.[[ArrayBufferData]]. | |
154 // 18. Let toBuf be new.[[ArrayBufferData]]. | |
155 // 19. Perform CopyDataBlockBytes(toBuf, 0, fromBuf, first, newLen). | |
156 size_t first_size = 0, new_len_size = 0; | |
157 CHECK(TryNumberToSize(*first_obj, &first_size)); | |
158 CHECK(TryNumberToSize(*new_len_obj, &new_len_size)); | |
159 DCHECK(NumberToSize(new_array_buffer->byte_length()) >= new_len_size); | |
160 | |
161 if (new_len_size != 0) { | |
162 size_t from_byte_length = NumberToSize(array_buffer->byte_length()); | |
163 USE(from_byte_length); | |
164 DCHECK(first_size <= from_byte_length); | |
165 DCHECK(from_byte_length - first_size >= new_len_size); | |
166 uint8_t* from_data = | |
167 reinterpret_cast<uint8_t*>(array_buffer->backing_store()); | |
168 uint8_t* to_data = | |
169 reinterpret_cast<uint8_t*>(new_array_buffer->backing_store()); | |
170 CopyBytes(to_data, from_data + first_size, new_len_size); | |
171 } | |
172 | |
173 return *new_; | |
174 } | |
175 | |
46 void SharedArrayBufferBuiltinsAssembler::ValidateSharedTypedArray( | 176 void SharedArrayBufferBuiltinsAssembler::ValidateSharedTypedArray( |
47 Node* tagged, Node* context, Node** out_instance_type, | 177 Node* tagged, Node* context, Node** out_instance_type, |
48 Node** out_backing_store) { | 178 Node** out_backing_store) { |
49 Label not_float_or_clamped(this), invalid(this); | 179 Label not_float_or_clamped(this), invalid(this); |
50 | 180 |
51 // Fail if it is not a heap object. | 181 // Fail if it is not a heap object. |
52 GotoIf(TaggedIsSmi(tagged), &invalid); | 182 GotoIf(TaggedIsSmi(tagged), &invalid); |
53 | 183 |
54 // Fail if the array's instance type is not JSTypedArray. | 184 // Fail if the array's instance type is not JSTypedArray. |
55 GotoIf(Word32NotEqual(LoadInstanceType(tagged), | 185 GotoIf(Word32NotEqual(LoadInstanceType(tagged), |
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
332 | 462 |
333 // This shouldn't happen, we've already validated the type. | 463 // This shouldn't happen, we've already validated the type. |
334 Bind(&other); | 464 Bind(&other); |
335 Unreachable(); | 465 Unreachable(); |
336 #endif // V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64 || V8_TARGET_ARCH_PPC64 | 466 #endif // V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64 || V8_TARGET_ARCH_PPC64 |
337 // || V8_TARGET_ARCH_PPC || V8_TARGET_ARCH_S390 || V8_TARGET_ARCH_S390X | 467 // || V8_TARGET_ARCH_PPC || V8_TARGET_ARCH_S390 || V8_TARGET_ARCH_S390X |
338 } | 468 } |
339 | 469 |
340 } // namespace internal | 470 } // namespace internal |
341 } // namespace v8 | 471 } // namespace v8 |
OLD | NEW |