Chromium Code Reviews| 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 |