OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 #ifndef V8_CODE_STUBS_H_ | 5 #ifndef V8_CODE_STUBS_H_ |
6 #define V8_CODE_STUBS_H_ | 6 #define V8_CODE_STUBS_H_ |
7 | 7 |
8 #include "allocation.h" | 8 #include "allocation.h" |
9 #include "assembler.h" | 9 #include "assembler.h" |
10 #include "codegen.h" | 10 #include "codegen.h" |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
184 } | 184 } |
185 | 185 |
186 virtual void PrintName(StringStream* stream); | 186 virtual void PrintName(StringStream* stream); |
187 | 187 |
188 // Returns a name for logging/debugging purposes. | 188 // Returns a name for logging/debugging purposes. |
189 SmartArrayPointer<const char> GetName(); | 189 SmartArrayPointer<const char> GetName(); |
190 | 190 |
191 Isolate* isolate() const { return isolate_; } | 191 Isolate* isolate() const { return isolate_; } |
192 | 192 |
193 protected: | 193 protected: |
194 static bool CanUseFPRegisters(); | |
195 | |
196 // Generates the assembler code for the stub. | 194 // Generates the assembler code for the stub. |
197 virtual Handle<Code> GenerateCode() = 0; | 195 virtual Handle<Code> GenerateCode() = 0; |
198 | 196 |
199 virtual void VerifyPlatformFeatures(); | 197 virtual void VerifyPlatformFeatures(); |
200 | 198 |
201 // Returns whether the code generated for this stub needs to be allocated as | 199 // Returns whether the code generated for this stub needs to be allocated as |
202 // a fixed (non-moveable) code object. | 200 // a fixed (non-moveable) code object. |
203 virtual bool NeedsImmovableCode() { return false; } | 201 virtual bool NeedsImmovableCode() { return false; } |
204 | 202 |
205 virtual void PrintBaseName(StringStream* stream); | 203 virtual void PrintBaseName(StringStream* stream); |
(...skipping 955 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1161 } | 1159 } |
1162 | 1160 |
1163 virtual InlineCacheState GetICState() V8_FINAL V8_OVERRIDE { | 1161 virtual InlineCacheState GetICState() V8_FINAL V8_OVERRIDE { |
1164 return state_.GetICState(); | 1162 return state_.GetICState(); |
1165 } | 1163 } |
1166 | 1164 |
1167 virtual ExtraICState GetExtraICState() V8_FINAL V8_OVERRIDE { | 1165 virtual ExtraICState GetExtraICState() V8_FINAL V8_OVERRIDE { |
1168 return state_.GetExtraICState(); | 1166 return state_.GetExtraICState(); |
1169 } | 1167 } |
1170 | 1168 |
1171 virtual void VerifyPlatformFeatures() V8_FINAL V8_OVERRIDE { | 1169 virtual void VerifyPlatformFeatures() V8_FINAL V8_OVERRIDE { } |
1172 ASSERT(CpuFeatures::VerifyCrossCompiling(SSE2)); | |
1173 } | |
1174 | 1170 |
1175 virtual Handle<Code> GenerateCode() V8_OVERRIDE; | 1171 virtual Handle<Code> GenerateCode() V8_OVERRIDE; |
1176 | 1172 |
1177 const BinaryOpIC::State& state() const { return state_; } | 1173 const BinaryOpIC::State& state() const { return state_; } |
1178 | 1174 |
1179 virtual void PrintState(StringStream* stream) V8_FINAL V8_OVERRIDE; | 1175 virtual void PrintState(StringStream* stream) V8_FINAL V8_OVERRIDE; |
1180 | 1176 |
1181 virtual Major MajorKey() V8_OVERRIDE { return BinaryOpIC; } | 1177 virtual Major MajorKey() V8_OVERRIDE { return BinaryOpIC; } |
1182 virtual int NotMissMinorKey() V8_FINAL V8_OVERRIDE { | 1178 virtual int NotMissMinorKey() V8_FINAL V8_OVERRIDE { |
1183 return GetExtraICState(); | 1179 return GetExtraICState(); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1218 } | 1214 } |
1219 | 1215 |
1220 virtual InlineCacheState GetICState() V8_OVERRIDE { | 1216 virtual InlineCacheState GetICState() V8_OVERRIDE { |
1221 return state_.GetICState(); | 1217 return state_.GetICState(); |
1222 } | 1218 } |
1223 | 1219 |
1224 virtual ExtraICState GetExtraICState() V8_OVERRIDE { | 1220 virtual ExtraICState GetExtraICState() V8_OVERRIDE { |
1225 return state_.GetExtraICState(); | 1221 return state_.GetExtraICState(); |
1226 } | 1222 } |
1227 | 1223 |
1228 virtual void VerifyPlatformFeatures() V8_OVERRIDE { | 1224 virtual void VerifyPlatformFeatures() V8_OVERRIDE { } |
1229 ASSERT(CpuFeatures::VerifyCrossCompiling(SSE2)); | |
1230 } | |
1231 | 1225 |
1232 virtual void Generate(MacroAssembler* masm) V8_OVERRIDE; | 1226 virtual void Generate(MacroAssembler* masm) V8_OVERRIDE; |
1233 | 1227 |
1234 virtual void PrintState(StringStream* stream) V8_OVERRIDE; | 1228 virtual void PrintState(StringStream* stream) V8_OVERRIDE; |
1235 | 1229 |
1236 virtual Major MajorKey() V8_OVERRIDE { return BinaryOpICWithAllocationSite; } | 1230 virtual Major MajorKey() V8_OVERRIDE { return BinaryOpICWithAllocationSite; } |
1237 virtual int MinorKey() V8_OVERRIDE { return GetExtraICState(); } | 1231 virtual int MinorKey() V8_OVERRIDE { return GetExtraICState(); } |
1238 | 1232 |
1239 private: | 1233 private: |
1240 static void GenerateAheadOfTime(Isolate* isolate, | 1234 static void GenerateAheadOfTime(Isolate* isolate, |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1301 PretenureFlagBits::encode(pretenure_flag)) {} | 1295 PretenureFlagBits::encode(pretenure_flag)) {} |
1302 | 1296 |
1303 StringAddFlags flags() const { | 1297 StringAddFlags flags() const { |
1304 return StringAddFlagsBits::decode(bit_field_); | 1298 return StringAddFlagsBits::decode(bit_field_); |
1305 } | 1299 } |
1306 | 1300 |
1307 PretenureFlag pretenure_flag() const { | 1301 PretenureFlag pretenure_flag() const { |
1308 return PretenureFlagBits::decode(bit_field_); | 1302 return PretenureFlagBits::decode(bit_field_); |
1309 } | 1303 } |
1310 | 1304 |
1311 virtual void VerifyPlatformFeatures() V8_OVERRIDE { | 1305 virtual void VerifyPlatformFeatures() V8_OVERRIDE { } |
1312 ASSERT(CpuFeatures::VerifyCrossCompiling(SSE2)); | |
1313 } | |
1314 | 1306 |
1315 virtual Handle<Code> GenerateCode() V8_OVERRIDE; | 1307 virtual Handle<Code> GenerateCode() V8_OVERRIDE; |
1316 | 1308 |
1317 virtual void InitializeInterfaceDescriptor( | 1309 virtual void InitializeInterfaceDescriptor( |
1318 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE; | 1310 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE; |
1319 | 1311 |
1320 static void InstallDescriptors(Isolate* isolate); | 1312 static void InstallDescriptors(Isolate* isolate); |
1321 | 1313 |
1322 // Parameters accessed via CodeStubGraphBuilder::GetParameter() | 1314 // Parameters accessed via CodeStubGraphBuilder::GetParameter() |
1323 static const int kLeft = 0; | 1315 static const int kLeft = 0; |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1515 | 1507 |
1516 void Generate(MacroAssembler* masm); | 1508 void Generate(MacroAssembler* masm); |
1517 | 1509 |
1518 // The version of this stub that doesn't save doubles is generated ahead of | 1510 // The version of this stub that doesn't save doubles is generated ahead of |
1519 // time, so it's OK to call it from other stubs that can't cope with GC during | 1511 // time, so it's OK to call it from other stubs that can't cope with GC during |
1520 // their code generation. On machines that always have gp registers (x64) we | 1512 // their code generation. On machines that always have gp registers (x64) we |
1521 // can generate both variants ahead of time. | 1513 // can generate both variants ahead of time. |
1522 static void GenerateAheadOfTime(Isolate* isolate); | 1514 static void GenerateAheadOfTime(Isolate* isolate); |
1523 | 1515 |
1524 protected: | 1516 protected: |
1525 virtual void VerifyPlatformFeatures() V8_OVERRIDE { | 1517 virtual void VerifyPlatformFeatures() V8_OVERRIDE { } |
1526 ASSERT(CpuFeatures::VerifyCrossCompiling(SSE2)); | |
1527 }; | |
1528 | 1518 |
1529 private: | 1519 private: |
1530 // Number of pointers/values returned. | 1520 // Number of pointers/values returned. |
1531 const int result_size_; | 1521 const int result_size_; |
1532 SaveFPRegsMode save_doubles_; | 1522 SaveFPRegsMode save_doubles_; |
1533 | 1523 |
1534 Major MajorKey() { return CEntry; } | 1524 Major MajorKey() { return CEntry; } |
1535 int MinorKey(); | 1525 int MinorKey(); |
1536 | 1526 |
1537 bool NeedsImmovableCode(); | 1527 bool NeedsImmovableCode(); |
(...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1913 Register destination, | 1903 Register destination, |
1914 int offset, | 1904 int offset, |
1915 bool is_truncating, | 1905 bool is_truncating, |
1916 bool skip_fastpath = false) | 1906 bool skip_fastpath = false) |
1917 : PlatformCodeStub(isolate), bit_field_(0) { | 1907 : PlatformCodeStub(isolate), bit_field_(0) { |
1918 bit_field_ = SourceRegisterBits::encode(source.code()) | | 1908 bit_field_ = SourceRegisterBits::encode(source.code()) | |
1919 DestinationRegisterBits::encode(destination.code()) | | 1909 DestinationRegisterBits::encode(destination.code()) | |
1920 OffsetBits::encode(offset) | | 1910 OffsetBits::encode(offset) | |
1921 IsTruncatingBits::encode(is_truncating) | | 1911 IsTruncatingBits::encode(is_truncating) | |
1922 SkipFastPathBits::encode(skip_fastpath) | | 1912 SkipFastPathBits::encode(skip_fastpath) | |
1923 SSEBits::encode( | 1913 SSE3Bits::encode(CpuFeatures::IsSafeForSnapshot(isolate, SSE3) ? 1 : 0); |
1924 CpuFeatures::IsSafeForSnapshot(isolate, SSE2) ? | |
1925 CpuFeatures::IsSafeForSnapshot(isolate, SSE3) ? 2 : 1 : 0); | |
1926 } | 1914 } |
1927 | 1915 |
1928 Register source() { | 1916 Register source() { |
1929 return Register::from_code(SourceRegisterBits::decode(bit_field_)); | 1917 return Register::from_code(SourceRegisterBits::decode(bit_field_)); |
1930 } | 1918 } |
1931 | 1919 |
1932 Register destination() { | 1920 Register destination() { |
1933 return Register::from_code(DestinationRegisterBits::decode(bit_field_)); | 1921 return Register::from_code(DestinationRegisterBits::decode(bit_field_)); |
1934 } | 1922 } |
1935 | 1923 |
1936 bool is_truncating() { | 1924 bool is_truncating() { |
1937 return IsTruncatingBits::decode(bit_field_); | 1925 return IsTruncatingBits::decode(bit_field_); |
1938 } | 1926 } |
1939 | 1927 |
1940 bool skip_fastpath() { | 1928 bool skip_fastpath() { |
1941 return SkipFastPathBits::decode(bit_field_); | 1929 return SkipFastPathBits::decode(bit_field_); |
1942 } | 1930 } |
1943 | 1931 |
1944 int offset() { | 1932 int offset() { |
1945 return OffsetBits::decode(bit_field_); | 1933 return OffsetBits::decode(bit_field_); |
1946 } | 1934 } |
1947 | 1935 |
1948 void Generate(MacroAssembler* masm); | 1936 void Generate(MacroAssembler* masm); |
1949 | 1937 |
1950 virtual bool SometimesSetsUpAFrame() { return false; } | 1938 virtual bool SometimesSetsUpAFrame() { return false; } |
1951 | 1939 |
1952 protected: | 1940 protected: |
1953 virtual void VerifyPlatformFeatures() V8_OVERRIDE { | 1941 virtual void VerifyPlatformFeatures() V8_OVERRIDE { } |
1954 ASSERT(CpuFeatures::VerifyCrossCompiling(SSE2)); | |
1955 } | |
1956 | 1942 |
1957 private: | 1943 private: |
1958 static const int kBitsPerRegisterNumber = 6; | 1944 static const int kBitsPerRegisterNumber = 6; |
1959 STATIC_ASSERT((1L << kBitsPerRegisterNumber) >= Register::kNumRegisters); | 1945 STATIC_ASSERT((1L << kBitsPerRegisterNumber) >= Register::kNumRegisters); |
1960 class SourceRegisterBits: | 1946 class SourceRegisterBits: |
1961 public BitField<int, 0, kBitsPerRegisterNumber> {}; // NOLINT | 1947 public BitField<int, 0, kBitsPerRegisterNumber> {}; // NOLINT |
1962 class DestinationRegisterBits: | 1948 class DestinationRegisterBits: |
1963 public BitField<int, kBitsPerRegisterNumber, | 1949 public BitField<int, kBitsPerRegisterNumber, |
1964 kBitsPerRegisterNumber> {}; // NOLINT | 1950 kBitsPerRegisterNumber> {}; // NOLINT |
1965 class IsTruncatingBits: | 1951 class IsTruncatingBits: |
1966 public BitField<bool, 2 * kBitsPerRegisterNumber, 1> {}; // NOLINT | 1952 public BitField<bool, 2 * kBitsPerRegisterNumber, 1> {}; // NOLINT |
1967 class OffsetBits: | 1953 class OffsetBits: |
1968 public BitField<int, 2 * kBitsPerRegisterNumber + 1, 3> {}; // NOLINT | 1954 public BitField<int, 2 * kBitsPerRegisterNumber + 1, 3> {}; // NOLINT |
1969 class SkipFastPathBits: | 1955 class SkipFastPathBits: |
1970 public BitField<int, 2 * kBitsPerRegisterNumber + 4, 1> {}; // NOLINT | 1956 public BitField<int, 2 * kBitsPerRegisterNumber + 4, 1> {}; // NOLINT |
1971 class SSEBits: | 1957 class SSE3Bits: |
1972 public BitField<int, 2 * kBitsPerRegisterNumber + 5, 2> {}; // NOLINT | 1958 public BitField<int, 2 * kBitsPerRegisterNumber + 5, 1> {}; // NOLINT |
1973 | 1959 |
1974 Major MajorKey() { return DoubleToI; } | 1960 Major MajorKey() { return DoubleToI; } |
1975 int MinorKey() { return bit_field_; } | 1961 int MinorKey() { return bit_field_; } |
1976 | 1962 |
1977 int bit_field_; | 1963 int bit_field_; |
1978 | 1964 |
1979 DISALLOW_COPY_AND_ASSIGN(DoubleToIStub); | 1965 DISALLOW_COPY_AND_ASSIGN(DoubleToIStub); |
1980 }; | 1966 }; |
1981 | 1967 |
1982 | 1968 |
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2303 | 2289 |
2304 class KeyedStoreElementStub : public PlatformCodeStub { | 2290 class KeyedStoreElementStub : public PlatformCodeStub { |
2305 public: | 2291 public: |
2306 KeyedStoreElementStub(Isolate* isolate, | 2292 KeyedStoreElementStub(Isolate* isolate, |
2307 bool is_js_array, | 2293 bool is_js_array, |
2308 ElementsKind elements_kind, | 2294 ElementsKind elements_kind, |
2309 KeyedAccessStoreMode store_mode) | 2295 KeyedAccessStoreMode store_mode) |
2310 : PlatformCodeStub(isolate), | 2296 : PlatformCodeStub(isolate), |
2311 is_js_array_(is_js_array), | 2297 is_js_array_(is_js_array), |
2312 elements_kind_(elements_kind), | 2298 elements_kind_(elements_kind), |
2313 store_mode_(store_mode), | 2299 store_mode_(store_mode) { } |
2314 fp_registers_(CanUseFPRegisters()) { } | |
2315 | 2300 |
2316 Major MajorKey() { return KeyedStoreElement; } | 2301 Major MajorKey() { return KeyedStoreElement; } |
2317 int MinorKey() { | 2302 int MinorKey() { |
2318 return ElementsKindBits::encode(elements_kind_) | | 2303 return ElementsKindBits::encode(elements_kind_) | |
2319 IsJSArrayBits::encode(is_js_array_) | | 2304 IsJSArrayBits::encode(is_js_array_) | |
2320 StoreModeBits::encode(store_mode_) | | 2305 StoreModeBits::encode(store_mode_); |
2321 FPRegisters::encode(fp_registers_); | |
2322 } | 2306 } |
2323 | 2307 |
2324 void Generate(MacroAssembler* masm); | 2308 void Generate(MacroAssembler* masm); |
2325 | 2309 |
2326 private: | 2310 private: |
2327 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {}; | 2311 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {}; |
2328 class StoreModeBits: public BitField<KeyedAccessStoreMode, 8, 4> {}; | 2312 class StoreModeBits: public BitField<KeyedAccessStoreMode, 8, 4> {}; |
2329 class IsJSArrayBits: public BitField<bool, 12, 1> {}; | 2313 class IsJSArrayBits: public BitField<bool, 12, 1> {}; |
2330 class FPRegisters: public BitField<bool, 13, 1> {}; | |
2331 | 2314 |
2332 bool is_js_array_; | 2315 bool is_js_array_; |
2333 ElementsKind elements_kind_; | 2316 ElementsKind elements_kind_; |
2334 KeyedAccessStoreMode store_mode_; | 2317 KeyedAccessStoreMode store_mode_; |
2335 bool fp_registers_; | |
2336 | 2318 |
2337 DISALLOW_COPY_AND_ASSIGN(KeyedStoreElementStub); | 2319 DISALLOW_COPY_AND_ASSIGN(KeyedStoreElementStub); |
2338 }; | 2320 }; |
2339 | 2321 |
2340 | 2322 |
2341 class ToBooleanStub: public HydrogenCodeStub { | 2323 class ToBooleanStub: public HydrogenCodeStub { |
2342 public: | 2324 public: |
2343 enum Type { | 2325 enum Type { |
2344 UNDEFINED, | 2326 UNDEFINED, |
2345 BOOLEAN, | 2327 BOOLEAN, |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2493 | 2475 |
2494 ElementsKind kind_; | 2476 ElementsKind kind_; |
2495 | 2477 |
2496 DISALLOW_COPY_AND_ASSIGN(ArrayShiftStub); | 2478 DISALLOW_COPY_AND_ASSIGN(ArrayShiftStub); |
2497 }; | 2479 }; |
2498 | 2480 |
2499 | 2481 |
2500 class StoreArrayLiteralElementStub : public PlatformCodeStub { | 2482 class StoreArrayLiteralElementStub : public PlatformCodeStub { |
2501 public: | 2483 public: |
2502 explicit StoreArrayLiteralElementStub(Isolate* isolate) | 2484 explicit StoreArrayLiteralElementStub(Isolate* isolate) |
2503 : PlatformCodeStub(isolate), fp_registers_(CanUseFPRegisters()) { } | 2485 : PlatformCodeStub(isolate) { } |
2504 | 2486 |
2505 private: | 2487 private: |
2506 class FPRegisters: public BitField<bool, 0, 1> {}; | |
2507 | |
2508 Major MajorKey() { return StoreArrayLiteralElement; } | 2488 Major MajorKey() { return StoreArrayLiteralElement; } |
2509 int MinorKey() { return FPRegisters::encode(fp_registers_); } | 2489 int MinorKey() { return 0; } |
2510 | 2490 |
2511 void Generate(MacroAssembler* masm); | 2491 void Generate(MacroAssembler* masm); |
2512 | 2492 |
2513 bool fp_registers_; | |
2514 | |
2515 DISALLOW_COPY_AND_ASSIGN(StoreArrayLiteralElementStub); | 2493 DISALLOW_COPY_AND_ASSIGN(StoreArrayLiteralElementStub); |
2516 }; | 2494 }; |
2517 | 2495 |
2518 | 2496 |
2519 class StubFailureTrampolineStub : public PlatformCodeStub { | 2497 class StubFailureTrampolineStub : public PlatformCodeStub { |
2520 public: | 2498 public: |
2521 StubFailureTrampolineStub(Isolate* isolate, StubFunctionMode function_mode) | 2499 StubFailureTrampolineStub(Isolate* isolate, StubFunctionMode function_mode) |
2522 : PlatformCodeStub(isolate), | 2500 : PlatformCodeStub(isolate), |
2523 fp_registers_(CanUseFPRegisters()), | |
2524 function_mode_(function_mode) {} | 2501 function_mode_(function_mode) {} |
2525 | 2502 |
2526 static void GenerateAheadOfTime(Isolate* isolate); | 2503 static void GenerateAheadOfTime(Isolate* isolate); |
2527 | 2504 |
2528 private: | 2505 private: |
2529 class FPRegisters: public BitField<bool, 0, 1> {}; | 2506 class FunctionModeField: public BitField<StubFunctionMode, 0, 1> {}; |
2530 class FunctionModeField: public BitField<StubFunctionMode, 1, 1> {}; | |
2531 | 2507 |
2532 Major MajorKey() { return StubFailureTrampoline; } | 2508 Major MajorKey() { return StubFailureTrampoline; } |
2533 int MinorKey() { | 2509 int MinorKey() { |
2534 return FPRegisters::encode(fp_registers_) | | 2510 return FunctionModeField::encode(function_mode_); |
2535 FunctionModeField::encode(function_mode_); | |
2536 } | 2511 } |
2537 | 2512 |
2538 void Generate(MacroAssembler* masm); | 2513 void Generate(MacroAssembler* masm); |
2539 | 2514 |
2540 bool fp_registers_; | |
2541 StubFunctionMode function_mode_; | 2515 StubFunctionMode function_mode_; |
2542 | 2516 |
2543 DISALLOW_COPY_AND_ASSIGN(StubFailureTrampolineStub); | 2517 DISALLOW_COPY_AND_ASSIGN(StubFailureTrampolineStub); |
2544 }; | 2518 }; |
2545 | 2519 |
2546 | 2520 |
2547 class ProfileEntryHookStub : public PlatformCodeStub { | 2521 class ProfileEntryHookStub : public PlatformCodeStub { |
2548 public: | 2522 public: |
2549 explicit ProfileEntryHookStub(Isolate* isolate) : PlatformCodeStub(isolate) {} | 2523 explicit ProfileEntryHookStub(Isolate* isolate) : PlatformCodeStub(isolate) {} |
2550 | 2524 |
(...skipping 18 matching lines...) Expand all Loading... |
2569 | 2543 |
2570 | 2544 |
2571 class CallDescriptors { | 2545 class CallDescriptors { |
2572 public: | 2546 public: |
2573 static void InitializeForIsolate(Isolate* isolate); | 2547 static void InitializeForIsolate(Isolate* isolate); |
2574 }; | 2548 }; |
2575 | 2549 |
2576 } } // namespace v8::internal | 2550 } } // namespace v8::internal |
2577 | 2551 |
2578 #endif // V8_CODE_STUBS_H_ | 2552 #endif // V8_CODE_STUBS_H_ |
OLD | NEW |