| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 7bd6a2c commit faee973
8 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -36,7 +36,7 @@ | |||
| 36 | 36 | ||
| 37 | 37 | # Reset this number to 0 on major V8 upgrades. | |
| 38 | 38 | # Increment by one for each non-official patch applied to deps/v8. | |
| 39 | - 'v8_embedder_string': '-node.9', | ||
| 39 | + 'v8_embedder_string': '-node.10', | ||
| 40 | 40 | ||
| 41 | 41 | ##### V8 defaults for Node.js ##### | |
| 42 | 42 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -248,6 +248,7 @@ class CTypeInfo { | |||
| 248 | 248 | kFloat32, | |
| 249 | 249 | kFloat64, | |
| 250 | 250 | kV8Value, | |
| 251 | + kSeqOneByteString, | ||
| 251 | 252 | kApiObject, // This will be deprecated once all users have | |
| 252 | 253 | // migrated from v8::ApiObject to v8::Local<v8::Value>. | |
| 253 | 254 | kAny, // This is added to enable untyped representation of fast | |
@@ -379,6 +380,11 @@ struct FastApiArrayBuffer { | |||
| 379 | 380 | size_t byte_length; | |
| 380 | 381 | }; | |
| 381 | 382 | ||
| 383 | + struct FastOneByteString { | ||
| 384 | + const char* data; | ||
| 385 | + uint32_t length; | ||
| 386 | + }; | ||
| 387 | + | ||
| 382 | 388 | class V8_EXPORT CFunctionInfo { | |
| 383 | 389 | public: | |
| 384 | 390 | // Construct a struct to hold a CFunction's type information. | |
@@ -438,6 +444,7 @@ struct AnyCType { | |||
| 438 | 444 | const FastApiTypedArray<uint64_t>* uint64_ta_value; | |
| 439 | 445 | const FastApiTypedArray<float>* float_ta_value; | |
| 440 | 446 | const FastApiTypedArray<double>* double_ta_value; | |
| 447 | + const FastOneByteString* string_value; | ||
| 441 | 448 | FastApiCallbackOptions* options_value; | |
| 442 | 449 | }; | |
| 443 | 450 | }; | |
@@ -614,7 +621,7 @@ class CFunctionInfoImpl : public CFunctionInfo { | |||
| 614 | 621 | kReturnType == CTypeInfo::Type::kFloat32 || | |
| 615 | 622 | kReturnType == CTypeInfo::Type::kFloat64 || | |
| 616 | 623 | kReturnType == CTypeInfo::Type::kAny, | |
| 617 | - "64-bit int and api object values are not currently " | ||
| 624 | + "64-bit int, string and api object values are not currently " | ||
| 618 | 625 | "supported return types."); | |
| 619 | 626 | } | |
| 620 | 627 | ||
@@ -735,6 +742,18 @@ struct TypeInfoHelper<FastApiCallbackOptions&> { | |||
| 735 | 742 | } | |
| 736 | 743 | }; | |
| 737 | 744 | ||
| 745 | + template <> | ||
| 746 | + struct TypeInfoHelper<const FastOneByteString&> { | ||
| 747 | + static constexpr CTypeInfo::Flags Flags() { return CTypeInfo::Flags::kNone; } | ||
| 748 | + | ||
| 749 | + static constexpr CTypeInfo::Type Type() { | ||
| 750 | + return CTypeInfo::Type::kSeqOneByteString; | ||
| 751 | + } | ||
| 752 | + static constexpr CTypeInfo::SequenceType SequenceType() { | ||
| 753 | + return CTypeInfo::SequenceType::kScalar; | ||
| 754 | + } | ||
| 755 | + }; | ||
| 756 | + | ||
| 738 | 757 | #define STATIC_ASSERT_IMPLIES(COND, ASSERTION, MSG) \ | |
| 739 | 758 | static_assert(((COND) == 0) || (ASSERTION), MSG) | |
| 740 | 759 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -315,6 +315,7 @@ class MachineType { | |||
| 315 | 315 | case CTypeInfo::Type::kFloat64: | |
| 316 | 316 | return MachineType::Float64(); | |
| 317 | 317 | case CTypeInfo::Type::kV8Value: | |
| 318 | + case CTypeInfo::Type::kSeqOneByteString: | ||
| 318 | 319 | case CTypeInfo::Type::kApiObject: | |
| 319 | 320 | return MachineType::AnyTagged(); | |
| 320 | 321 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -5246,6 +5246,50 @@ Node* EffectControlLinearizer::AdaptFastCallArgument( | |||
| 5246 | 5246 | case CTypeInfo::Type::kFloat32: { | |
| 5247 | 5247 | return __ TruncateFloat64ToFloat32(node); | |
| 5248 | 5248 | } | |
| 5249 | + case CTypeInfo::Type::kSeqOneByteString: { | ||
| 5250 | + // Check that the value is a HeapObject. | ||
| 5251 | + Node* value_is_smi = ObjectIsSmi(node); | ||
| 5252 | + __ GotoIf(value_is_smi, if_error); | ||
| 5253 | + | ||
| 5254 | + Node* map = __ LoadField(AccessBuilder::ForMap(), node); | ||
| 5255 | + Node* instance_type = | ||
| 5256 | + __ LoadField(AccessBuilder::ForMapInstanceType(), map); | ||
| 5257 | + | ||
| 5258 | + Node* encoding = __ Word32And( | ||
| 5259 | + instance_type, | ||
| 5260 | + __ Int32Constant(kStringRepresentationAndEncodingMask)); | ||
| 5261 | + | ||
| 5262 | + Node* is_onebytestring = __ Word32Equal( | ||
| 5263 | + encoding, __ Int32Constant(kSeqOneByteStringTag)); | ||
| 5264 | + __ GotoIfNot(is_onebytestring, if_error); | ||
| 5265 | + | ||
| 5266 | + Node* length_in_bytes = | ||
| 5267 | + __ LoadField(AccessBuilder::ForStringLength(), node); | ||
| 5268 | + Node* data_ptr = __ IntPtrAdd( | ||
| 5269 | + node, __ IntPtrConstant(SeqOneByteString::kHeaderSize - | ||
| 5270 | + kHeapObjectTag)); | ||
| 5271 | + | ||
| 5272 | + constexpr int kAlign = alignof(FastOneByteString); | ||
| 5273 | + constexpr int kSize = sizeof(FastOneByteString); | ||
| 5274 | + static_assert(kSize == sizeof(uintptr_t) + sizeof(size_t), | ||
| 5275 | + "The size of " | ||
| 5276 | + "FastOneByteString isn't equal to the sum of its " | ||
| 5277 | + "expected members."); | ||
| 5278 | + Node* stack_slot = __ StackSlot(kSize, kAlign); | ||
| 5279 | + | ||
| 5280 | + __ Store(StoreRepresentation(MachineType::PointerRepresentation(), | ||
| 5281 | + kNoWriteBarrier), | ||
| 5282 | + stack_slot, 0, data_ptr); | ||
| 5283 | + __ Store(StoreRepresentation(MachineRepresentation::kWord32, | ||
| 5284 | + kNoWriteBarrier), | ||
| 5285 | + stack_slot, sizeof(size_t), length_in_bytes); | ||
| 5286 | + | ||
| 5287 | + static_assert(sizeof(uintptr_t) == sizeof(size_t), | ||
| 5288 | + "The string length can't " | ||
| 5289 | + "fit the PointerRepresentation used to store it."); | ||
| 5290 | + | ||
| 5291 | + return stack_slot; | ||
| 5292 | + } | ||
| 5249 | 5293 | default: { | |
| 5250 | 5294 | return node; | |
| 5251 | 5295 | } | |
@@ -5451,6 +5495,7 @@ Node* EffectControlLinearizer::LowerFastApiCall(Node* node) { | |||
| 5451 | 5495 | case CTypeInfo::Type::kFloat64: | |
| 5452 | 5496 | return ChangeFloat64ToTagged( | |
| 5453 | 5497 | c_call_result, CheckForMinusZeroMode::kCheckForMinusZero); | |
| 5498 | + case CTypeInfo::Type::kSeqOneByteString: | ||
| 5454 | 5499 | case CTypeInfo::Type::kV8Value: | |
| 5455 | 5500 | case CTypeInfo::Type::kApiObject: | |
| 5456 | 5501 | case CTypeInfo::Type::kUint8: | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -28,6 +28,7 @@ ElementsKind GetTypedArrayElementsKind(CTypeInfo::Type type) { | |||
| 28 | 28 | case CTypeInfo::Type::kFloat64: | |
| 29 | 29 | return FLOAT64_ELEMENTS; | |
| 30 | 30 | case CTypeInfo::Type::kVoid: | |
| 31 | + case CTypeInfo::Type::kSeqOneByteString: | ||
| 31 | 32 | case CTypeInfo::Type::kBool: | |
| 32 | 33 | case CTypeInfo::Type::kV8Value: | |
| 33 | 34 | case CTypeInfo::Type::kApiObject: | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1924,6 +1924,7 @@ class RepresentationSelector { | |||
| 1924 | 1924 | case CTypeInfo::Type::kFloat64: | |
| 1925 | 1925 | return UseInfo::CheckedNumberAsFloat64(kDistinguishZeros, feedback); | |
| 1926 | 1926 | case CTypeInfo::Type::kV8Value: | |
| 1927 | + case CTypeInfo::Type::kSeqOneByteString: | ||
| 1927 | 1928 | case CTypeInfo::Type::kApiObject: | |
| 1928 | 1929 | return UseInfo::AnyTagged(); | |
| 1929 | 1930 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -42,6 +42,43 @@ class FastCApiObject { | |||
| 42 | 42 | public: | |
| 43 | 43 | static FastCApiObject& instance(); | |
| 44 | 44 | ||
| 45 | + #ifdef V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS | ||
| 46 | + static AnyCType CopyStringFastCallbackPatch(AnyCType receiver, | ||
| 47 | + AnyCType should_fallback, | ||
| 48 | + AnyCType source, AnyCType out, | ||
| 49 | + AnyCType options) { | ||
| 50 | + AnyCType ret; | ||
| 51 | + CopyStringFastCallback(receiver.object_value, should_fallback.bool_value, | ||
| 52 | + *source.string_value, *out.uint8_ta_value, | ||
| 53 | + *options.options_value); | ||
| 54 | + return ret; | ||
| 55 | + } | ||
| 56 | + | ||
| 57 | + #endif // V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS | ||
| 58 | + static void CopyStringFastCallback(Local<Object> receiver, | ||
| 59 | + bool should_fallback, | ||
| 60 | + const FastOneByteString& source, | ||
| 61 | + const FastApiTypedArray<uint8_t>& out, | ||
| 62 | + FastApiCallbackOptions& options) { | ||
| 63 | + FastCApiObject* self = UnwrapObject(receiver); | ||
| 64 | + self->fast_call_count_++; | ||
| 65 | + | ||
| 66 | + if (should_fallback) { | ||
| 67 | + options.fallback = true; | ||
| 68 | + } else { | ||
| 69 | + options.fallback = false; | ||
| 70 | + } | ||
| 71 | + | ||
| 72 | + uint8_t* memory = nullptr; | ||
| 73 | + CHECK(out.getStorageIfAligned(&memory)); | ||
| 74 | + memcpy(memory, source.data, source.length); | ||
| 75 | + } | ||
| 76 | + | ||
| 77 | + static void CopyStringSlowCallback(const FunctionCallbackInfo<Value>& args) { | ||
| 78 | + FastCApiObject* self = UnwrapObject(args.This()); | ||
| 79 | + CHECK_SELF_OR_THROW(); | ||
| 80 | + self->slow_call_count_++; | ||
| 81 | + } | ||
| 45 | 82 | #ifdef V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS | |
| 46 | 83 | static AnyCType AddAllFastCallbackPatch(AnyCType receiver, | |
| 47 | 84 | AnyCType should_fallback, | |
@@ -1072,6 +1109,16 @@ Local<FunctionTemplate> Shell::CreateTestFastCApiTemplate(Isolate* isolate) { | |||
| 1072 | 1109 | PerIsolateData::Get(isolate)->SetTestApiObjectCtor(api_obj_ctor); | |
| 1073 | 1110 | Local<Signature> signature = Signature::New(isolate, api_obj_ctor); | |
| 1074 | 1111 | { | |
| 1112 | + CFunction copy_str_func = CFunction::Make( | ||
| 1113 | + FastCApiObject::CopyStringFastCallback V8_IF_USE_SIMULATOR( | ||
| 1114 | + FastCApiObject::CopyStringFastCallbackPatch)); | ||
| 1115 | + api_obj_ctor->PrototypeTemplate()->Set( | ||
| 1116 | + isolate, "copy_string", | ||
| 1117 | + FunctionTemplate::New(isolate, FastCApiObject::CopyStringSlowCallback, | ||
| 1118 | + Local<Value>(), signature, 1, | ||
| 1119 | + ConstructorBehavior::kThrow, | ||
| 1120 | + SideEffectType::kHasSideEffect, ©_str_func)); | ||
| 1121 | + | ||
| 1075 | 1122 | CFunction add_all_c_func = | |
| 1076 | 1123 | CFunction::Make(FastCApiObject::AddAllFastCallback V8_IF_USE_SIMULATOR( | |
| 1077 | 1124 | FastCApiObject::AddAllFastCallbackPatch)); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,84 @@ | |||
| 1 | + // Copyright 2022 the V8 project authors. All rights reserved. | ||
| 2 | + // Use of this source code is governed by a BSD-style license that can be | ||
| 3 | + // found in the LICENSE file. | ||
| 4 | + | ||
| 5 | + // This file excercises one byte string support for fast API calls. | ||
| 6 | + | ||
| 7 | + // Flags: --turbo-fast-api-calls --expose-fast-api --allow-natives-syntax --turbofan | ||
| 8 | + // --always-turbofan is disabled because we rely on particular feedback for | ||
| 9 | + // optimizing to the fastest path. | ||
| 10 | + // Flags: --no-always-turbofan | ||
| 11 | + // The test relies on optimizing/deoptimizing at predictable moments, so | ||
| 12 | + // it's not suitable for deoptimization fuzzing. | ||
| 13 | + // Flags: --deopt-every-n-times=0 | ||
| 14 | + | ||
| 15 | + assertThrows(() => d8.test.FastCAPI()); | ||
| 16 | + const fast_c_api = new d8.test.FastCAPI(); | ||
| 17 | + | ||
| 18 | + function assertSlowCall(input) { | ||
| 19 | + assertEquals(new Uint8Array(input.length), copy_string(false, input)); | ||
| 20 | + } | ||
| 21 | + | ||
| 22 | + function assertFastCall(input) { | ||
| 23 | + const bytes = Uint8Array.from(input, c => c.charCodeAt(0)); | ||
| 24 | + assertEquals(bytes, copy_string(false, input)); | ||
| 25 | + } | ||
| 26 | + | ||
| 27 | + function copy_string(should_fallback = false, input) { | ||
| 28 | + const buffer = new Uint8Array(input.length); | ||
| 29 | + fast_c_api.copy_string(should_fallback, input, buffer); | ||
| 30 | + return buffer; | ||
| 31 | + } | ||
| 32 | + | ||
| 33 | + %PrepareFunctionForOptimization(copy_string); | ||
| 34 | + assertSlowCall('Hello'); | ||
| 35 | + %OptimizeFunctionOnNextCall(copy_string); | ||
| 36 | + | ||
| 37 | + fast_c_api.reset_counts(); | ||
| 38 | + assertFastCall('Hello'); | ||
| 39 | + assertFastCall(''); | ||
| 40 | + assertFastCall(['Hello', 'World'].join('')); | ||
| 41 | + assertOptimized(copy_string); | ||
| 42 | + assertEquals(3, fast_c_api.fast_call_count()); | ||
| 43 | + assertEquals(0, fast_c_api.slow_call_count()); | ||
| 44 | + | ||
| 45 | + // Fall back for twobyte strings. | ||
| 46 | + fast_c_api.reset_counts(); | ||
| 47 | + assertSlowCall('Hello\u{10000}'); | ||
| 48 | + assertSlowCall('नमस्ते'); | ||
| 49 | + assertSlowCall(['नमस्ते', 'World'].join('')); | ||
| 50 | + assertOptimized(copy_string); | ||
| 51 | + assertEquals(0, fast_c_api.fast_call_count()); | ||
| 52 | + assertEquals(3, fast_c_api.slow_call_count()); | ||
| 53 | + | ||
| 54 | + // Fall back for cons strings. | ||
| 55 | + function getTwoByteString() { | ||
| 56 | + return '\u1234t'; | ||
| 57 | + } | ||
| 58 | + function getCons() { | ||
| 59 | + return 'hello' + getTwoByteString() | ||
| 60 | + } | ||
| 61 | + | ||
| 62 | + fast_c_api.reset_counts(); | ||
| 63 | + assertSlowCall(getCons()); | ||
| 64 | + assertOptimized(copy_string); | ||
| 65 | + assertEquals(0, fast_c_api.fast_call_count()); | ||
| 66 | + assertEquals(1, fast_c_api.slow_call_count()); | ||
| 67 | + | ||
| 68 | + // Fall back for sliced strings. | ||
| 69 | + fast_c_api.reset_counts(); | ||
| 70 | + function getSliced() { | ||
| 71 | + return getCons().slice(1); | ||
| 72 | + } | ||
| 73 | + assertSlowCall(getSliced()); | ||
| 74 | + assertOptimized(copy_string); | ||
| 75 | + assertEquals(0, fast_c_api.fast_call_count()); | ||
| 76 | + assertEquals(1, fast_c_api.slow_call_count()); | ||
| 77 | + | ||
| 78 | + // Fall back for SMI and non-string inputs. | ||
| 79 | + fast_c_api.reset_counts(); | ||
| 80 | + assertSlowCall(1); | ||
| 81 | + assertSlowCall({}); | ||
| 82 | + assertSlowCall(new Uint8Array(1)); | ||
| 83 | + assertEquals(0, fast_c_api.fast_call_count()); | ||
| 84 | + assertEquals(3, fast_c_api.slow_call_count()); | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments