Pull to refresh
4
0
Бобров Максим Юрьевич @demimurych

FAEBFE; Тех SEO аудит. 90+ WebVitals etc…

Send message

Я не могу и не имею права спорить с автором материала.

Но очень хочу спросить - дети в той же британии тоже учат грамматику чтобы говорить на английском?

Или там какой-то иной принцип?

а еще можно было прочитать спецификацию html5 и узнать из нее, что атрибут lang может и обязан ставиться на каждый фразовый контент в случае если страница мультиязычная.

после чего убедиться что google, строго в соответствии со стандартом интерпретирует подобное поведение стандарта

Автор материала, далеко не всегда перепроверял себя, на соответствие заявленного им, официальному источнику.

Как следствие, почти все о чем идет речь в материале, представляет из себя винегрет из того, что действительно имеет отношение к официальной спецификации языка JavaScript помноженной на заблуждения автора.

Судите сами:

Исчерпывающая информация есть в официальной документации

Автор материала не знает, что Mozilla Developer Network никогда не являлась официальной документацией. Единственным официальным источником, с 1998 года является сайт спецификации ECMAScript.

Всех нас учили, что в JavaScript есть примитивные и ссылочные типы данных. 

Кто Вас и тем более Всех этому учил, должен краснеть на месте. Потому, что согласно официальной спецификации языка JavaScript, никаких примитивных и тем более ссылочных типов - нет.

Даже если учесть общепринятый жаргон, относительно примитивных типов, то и в его рамках - никаких примитивных типов в языке JavaScript так же не существует. Потому как поведение тех типов, которые по умолчанию возвращают Primitive Value не укладываются в типичный набор критериев распространяемых в общем случае, на примитивные типы.

Главный из которых - строгая детерминированность поведения типа, вне зависимости от особенностей его использования.

То есть примитивный тип - это тип, который должен себя вести везде одинаково. При всех обстоятельствах. Чего в JavaScript нет.

Теория теорией, однако, JS-код исполняется не в теории, а на практике. Точнее, его компилирует и исполняет движок JS. Таких движков существует несколько, разрабатывались они разными людьми и для разных целей. Было бы наивно предполагать, что все они полностью идентичны друг другу. 

Сама по себе реализация стандарта, то есть тот самый код который обслуживает спецификацию - безусловно может быть разной. Но верхом глупости будет думать, что подобные реализации не соответствуют заявленной ими спецификации.

Примитивные типы данных,

это иммутабельные (не изменяемые) значения, хранимые в памяти и представленные в структурах языка на низком уровне. Собственно, в JavaScript к примитивным типам относится все, кроме Object, а именно: Null, Undefined, Boolean, Number, BigInt, String, Symbol

То что написал автор - не имеет никакого отношения к официальной спецификации. Согласно которой, никаких примитивных типов в языке JavaScript не существует. Такого термина просто нет в официальной спецификации. Не говоря уже о том, что поведение выше заявленных типов, не отвечает общепринятому определению примитивных типов.

Ссылочные типы данных, они же - объекты, это области памяти неопределенного размера, и доступные по идентификатору (ссылке на эту область памяти). В JavaScript, есть только один такой тип - Object

Согласно официальной спецификации абсолютно все типы в языке JavaScript являются ссылочными:

Algorithm steps may declare named aliases for any value using the form “Let x be someValue”. These aliases are reference-like in that both x and someValue refer to the same underlying data and modifications to either are visible to both. Algorithm steps that want to avoid this reference-like behaviour should explicitly make a copy of the right-hand side: “Let x be a copy of someValue” creates a shallow copy of someValue.

Это фундаментальная основа языка JavaScript которая закреплена на уровне главы формирующей операции используемый спецификацией.

Все алгоритмы спецификации, если явным образом не указано другого, описывают Expression или Statement в рамках заявленного в главе Algorithm Conventions алгоритма - а именно ссылочного типа.

Если быть максимальным занудой, то в академической среде, где работа с типами определяется как: By Value, By Reference и By Shared, работа со всеми типами в JavaScript отвечает термину By Shared. Что по сути своей является тем же ссылочным типом, и отличается только способом передачи в целевой индентификатор самой ссылки.

Иными словами - любые утверждения со стороны о том, что в языке JavaScript есть якобы типы, которые якобы примитивные противоречат как официальной спецификации, так и общепринятому жаргону.

Исключением являются типы связанные с TypedArray.

 Object - единственный мутабельный (изменяемый) тип данных в JavaScript. 

Object как тип, ничем не отличается от прочих типов языка JavaScript с точки зрения его описания. Но отличается тем что возвращается по умолчанию при запросе к идентификатору который с ним связан. В случае Object - возвращается структура типа. В случае типов, неправильно названных автором примитивными, по умолчанию возвращается primitive value. Чего не достаточно чтобы считать тип примитивным.

Производя какие-либо манипуляции с объектом, меняется значение непосредственно в области памяти

Ничего подобного не происходит. Это фантазии автора материала. Структура Object ничем не отличается по своему поведению от структуры Record в рамках которой описываются идентификаторы которые связывают с типами вида String, Number etc...

Как в первом так и во втором случае, работа происходит абсолютно идентичным образом, что зафиксировано официальной спецификацией.

Объект остается в памяти, пока есть активная ссылка на него. Если ссылка удалена или больше не используется в сценарии, такой объект будет вскоре уничтожен сборщиком мусора, но об этом в следующий раз.

Официальная спецификации - никак не управляет тем что будет с обьектом или еще чем-то.

Официальная спецификация никаким образом не заявляет поведение Garbage Collector-а или любой другой машинерии про то же самое.

Это все лежит на плечах, конкретного RunTime, работа которого ВООБЩЕ не зависит от того, будет ли уничтожен какой-то обьект на который нет ссылки или не будет.

Больше того, если уж мы говорим о V8, то в его рамках, Garbage Collector, сто раз подумает прежде чем удалять что -то из памяти даже если на это что-то 100500 раз нет никаких ссылок. По одной простой причине - если память есть и ее достаточно, то последнее что нужно делать, это заниматься чисткой чего-то на что нет ссылок. Особенно в контексте того, что то, что потеряло ссылку, буквально завтра может ее снова обрести. А процесс заведения нового обьекта не в пример дороже чем работа Garbage Collecotr-а.

Согласно документация, тип Number в JavaScript является 64-битным числом двойной точности в соответствии со стандартом IEEE 754

Нет. Согласно официальной документации, представление типа Number может радикальным образом отличаться в зависимости от выражения в котором числовой литерал используется. И может быть действительно как число с плавающей точкой для выражения деления числа.

Одновременно с чем, оно может быть 32-битовым целым со знаком в рамках бинарных операций например and. При этом уничтожая всю метаинформацию о том, какая дробная часть (мантисса) было до этого.

Но и это далеко не все. В рамках спецификации, для сдвигов числовой литерал в выражении может становиться 32 битовым целым БЕЗ знака.

И все это, подчеркиваю, в рамках официальной спецификации.
(Передаем привет секте примитивных типов в JavaScript)

Посмотрим на это число в V8 в режиме дебага. Для этого воспользуемся системным хелпером движка %DebugPrint

DebugPrint: Smi: 0x1 (1)

Выяглядит вполне ожидаемо. Мы видим простое значение 0x1 с неким типом Smi. Но разве тут не должен быть тип Number, как говорится в спецификации ECMAScript? К сожалению, найти ответы на подобные вопросы в официальной документации движка не представляется возможным, 

Еще как представляется.

То, что увидел автор материала, является частью поведения оптимизирующего алгоритма современного RunTime.

Который, вместо того, чтобы создавать дополнительные структуры данных, и ссылки на них, разместит эти данные вместо самого указателя, в ситуации, когда эти данные туда поместятся.

Ну люди добрые, Вы же программисты. Если у Вас ссылка на структуру представляется 32 битами, при этом эта структура должна описать число 1, которое легко помещается в те самые 32 бита, зачем создавать структуру?

В современном V8 эта оптимизация называется Pointer Compression. Вот ссылка на статью, в официальном блоге инженеров V8, где подробно описывается это поведение.

Все последующие рассуждения автора про SMI в V8, касаются частного случая применения алгоритма оптимизации Pointer Compression. Который не обязательно будет включен для любой HOST среды. Например в Node, где используется ровно тот-же самый RunTime V8, оптимизация Pointer Compression отключена.

Как следствие, поведение в Node, связанное с обработкой численных литералов, отличается от того же поведения в браузере. Например Node может работать с 64 целыми числами если того позволяет архитектура. Чего не может делать Google Chrome. При этом Google Chrome, благодаря тому самому Pointer Compression становится в полтора раза эффективнее Node в случае обработки массивов данных, где каждый индекс укладывается в 31бит со знаком.

В чем легко убедиться используя тот же самый DebugPrint в Node и в браузере для одного и того же числа в пределах 31 бита.

Вместо ИГОГО:

Автору, как мне кажется, нужно переосмыслить весь написанный им материал и исправить допущенные им неточности. Иначе этот материал представляет из себя больше дезинформацию, нежели попытку просветить необразованное JS комьюнити.

если вы о Яндекс, то он перестал быть сколько-нибудь значимым конкурентом гугл где-то в 13-14 году, когда уже окончательно из Я были изгнаны все кто его создавал.

Задачи семантики в рамках html5 - єто формирование верстки, анализируя которую, любое сторонее программное обеспечение, которое следует тому же стандарту, может используя алгоритмы машинного анализа, зафиксировать однозначным образом, ровно тот же смысл, который был заложен автором оригинальной верстки.

В прямом смысле слова - смысл.

В случае Вашего примера с версткой, которая направлена на оптимизацию формирования отображения никакого "смысла" кроме оптимизации формы отображения - не передается.

Если Вам кажется, что я ошибаюсь, то будте так добры привести пример такого "смысла"

Я еще раз подчеркну, под термином семантика, подразумевается, в прямом смысле єто слова, формирование смысла - такого, как видит его человек.

Пример: Есть секция - черешня. Вложенные секции к ней - єто секция белая и секция красная. Как следствие формируется связь между термином Черешня и двумя связанными с ним качествами равноправными между собой: красная и белая. То есть черешня может быть белой, а может быть красной.

Пример выше, в очень упрощенном виде, иллюстрирует то, что называется семантикой стандарта html5, который разрешает задачи формирования смысла представляемого ей (версткой) контента.

Язык html, в его редакции html5, в первую очередь, направлен на представление семантики (смысла) документа (контента), посредством формирования связей между его секциями. Подавлшющее большинство тегов решают задачи определения тонкостей єтих связей.

То что нарисовали Вы в примере, не может быть принципиально реализовано на языке html, потому как Вы дали пример формирования отображения, а не описания семантики (смысла контента)

єто не знак равенства. Єто знак связывания.

Никак. И єто то самое место, где дружит императивная парадигма с функциональной.

Єтим свистоперделкам сто лет в обед.

Все отключается через chrome://flags поиск по слову omnibox

Может быть образования?

К примеру, солид дяди боба, єто попытка адаптировать естественные для функционального программирования обстоятельсва, к реалиям императивного программирования.

Стоит ли сообщить дяде Бобу, о его манипуляции с акронимами?

Еще чаще єтот код выполняется. Так может код нужно писать так, чтобы он єффективно выполнялся, а не читался?

Может в прокладке между стулом и клавиатурой? (;

Представленный материал не имеет ничего общего с официальной спецификацией языка ECMAScript. И представляет из себя как пересказ современных мифов о языке, так и, ничем не подтверждаемые, персональные представления автора.

То есть представления, которые прямо противоречат официальной спецификации.

Судите сами:

Тем не менее у JavaScript есть такой механизм как Event Loop, который как раз и позволяет выполнять "асинхронные" операции.

JavaScript не имел и не имеет такого механизма как EventLoop. EventLoop это специфическая для HOST среды особенность, которая, в том числе, может выполнять JavaScript код.  

Например поведение EventLoop в HOST среде реализующей стандарт HTML5 описано именно в стандарте HTML5.  Одновременно с этим, поведение схожего механизма в Node - описано в документации для libuv

При этом поведение в первой и второй HOST среде обладает достаточными различиями, чтобы утверждать - не может быть единого описания работы EventLoop даже в случае, если мы упрощаем задачу вычеркивая несущественные особенности реализации.

Да просто потому что JavaScript тоже выполняет их синхронно, асинхронности в самом JavaScript как таковой нет. 

Всем свидетелям секты однопоточного JavaScript, крайне рекомендую к прочтению современную спецификацию. Например вот  с этой главы официальной спецификации

Если заявлений официальной спецификации недостаточно, то можно почитать, что об этом думают авторы спецификации HTML5

После чего, либо изменить свою точку зрения, либо оставаться адептами одно-поточного JavaScript-а.

Для тех, кто обескуражен дам краткое ИГОГО:

  1. Спецификация языка JavaScript уже больше 8 лет, содержит в себе необходимые нормы для организации выполнения кода в более чем один поток.

  2. Под термином поток, следует понимать не thread в его академическом смысле, но возможность организации выполнения более одной единицы кода в одно и тоже время.

  3. Для реализации заявленного, в том числе, в официальной спецификации реализован Atomics Object регламентирующий все типичные проблемы возникающие при доступе к одному и тому же сегменту памяти разными потоками. Вплоть до создания отдельной очереди обрабатывающей таймауты для операций, которые пытаются прочитать, заблокированную другим потоком, область памяти. 

  4. В современной спецификации не существует реализации возможности самостоятельного запуска параллельного выполнения JS кода. Однако существует все необходимое, чтобы эту возможность через свое API предоставила HOST среда. Что и сделало возможным в свое время появление таких вещей как Worker-ы.

С синхронным кодом все более или менее ясно: интерпретатор проходится по каждой инструкции выполняет ее и все работает.

Заявленное не имеет ничего общего с тем как современная спецификация регламентирует работу JS кода

С асинхронным кодом все немножко сложнее. Рассмотрим следующий пример: [...]

Как мы можем увидеть console.log, который был в setTimeout почему-то выполнился позже, но почему так случилось?

Тут в силу и вступает Event Loop. Так как setTimeout это асинхронная операция (таймер высчитывается на стороне браузера, а не в JS).

console.log, setTimeout - это API предоставляемые HOST средой. Никакого отношения к тому, как выполняется JS код они не имеют. Ровно как не имеют отношения к тому, как выполняется асинхронный код в языке JavaScript. 

Регламентируют работу этих API сама HOST среда. И только она решает как и когда будет что-то выполнено. В рамках HOST среды типичного браузера, то есть среды реализующей стандарт HMTL5 - регламентом работы для этого API служит спецификация HTML5. Где и раскрыты мистические шаги описывающие поведение setTimeout.

Другое дело обстоит с таймером, время которое ожидает таймаут будет считаться на стороне браузера, поэтому операция как бы "пропадет" из очереди.

setTimeout это внешнее API. ВСЕ что с ним связано регламентируется HOST средой которая это API реализует. Никакого отношения к этому JS не имеет. Операция никуда не пропадает даже под соусом как бы.

  

Таймер попал в Event Loop, где будет ждать покуда браузер не пришлет сигнал, о том что время для таймаута вышло и коллбэк внутри таймера можно выполнять.

Это полнейшая чушь не только с точки зрения спецификации JavaScript, но и с точки зрения стандарта HTML5 - появление в любой из очередей ссылки на задачу для выполнения какого-либо кода, происходит только тогда, когда этот код УЖЕ нужно выполнять. Иными словами, таймер или коллбэк  не существует в EventLoop до тех пор пока тот самый таймер не истечет.

Где происходит истечение этого таймера? В недрах HOST среды которая обслуживает это API. 

Event Loop будет держать все что в нем содержится, покуда у нас не очистится Call Stack. Только после того как все синхронные операции в функции выполнились Event Loop отдаст нам наш таймер, который мы сможем выполнить

Это полнейшая чушь. Event Loop стандарта HTML5 оперирует термином Task. Task внутри себя может содержать что угодно - от одной команды до громадного блока команд.  Например весь код callback функции - это один task. 

Как уже было сказано выше интерпретатор в JavaScript выполняет одну операцию за раз, все что является асинхронным он отправляет в Event Loop.

Это фантазии автора, которые если и отвечают реальности - то только в одном частном случае. 

Однако, вы наверное могли слышать о таких вещах как "макротаски" и "микротаски".

В рамках стандарта HTML5, EventLoop содержит в себе две основные дефиниции: это  task queue и micro task queue. Никаких макротасков и прочих тасков НЕТ. 

  

Дело в том, что Event Loop - единственный механизм в JavaScript, который позволяет реализовать асинхронность

В языке JavaScript НЕТ EventLoop. Решать задачи выполнения асинхронного кода может ТОЛЬКО HOST среда. Потому, что язык JavaScript это скриптовый язык - у которого НЕ МОЖЕТ БЫТЬ своего ввода вывода. Как следствие, язык JavaScript НЕ МОЖЕТ иметь своего API для обслуживания событий или создания тредов. Это задача HOST среды. 

Event Loop является стеком, где хранятся все задачи, которые не вошли в синхронный поток выполнения.

Нет никакого синхронного потока выполнения. 

  

В микрозадачи попадают в основном только две категории: then у промисов, а также Intersection Observer.

Microtask queue это калька с механизма ECMAScript спецификации HostEnqueuePromiseJob. Который создан таковым потому, что авторы спецификации Promise настаивали на строгом соблюдении порядка выполнения задач связанных с разрешением промисов. 

Intersection Observer - это API стандарта HTML5 которое попало в microtask queue стандарта HTML5 по тем же причинам - авторам API было чрезвычайно важно чтобы порядок выполнения задач связанных с API был строго детерминирован. И чтобы не городить лишних огородов его просто добавили туда же.

Согласно стандарту HTML5, один EventLoop может выполнять задачи от нескольких разных Агентов. Например - браузер имеет три вкладки. Код этих трех вкладок - может выполняться одним агентом ( что было стандартом до 2015 года) и как следствие в одном EventLoop могли присутствовать задачи запускающие код, который совершенно был не связан с любым другим кодом. 

В рамках этой истории, крайне важно иметь гарантии, что те задачи для которых порядок выполнения операций КРИТИЧЕСКИ важен - получат этот порядок. 

Современное поведение браузера как HOST среды, по умолчанию создает отдельный Агент для каждой вкладки и как следствие отдельный Event Loop. Что продиктовано было причинами безопасности связанными с появившимся уязвимостями типа Spectre и Meltdown и схожие с ними, которых сейчас насчитывается уже с десяток.

Важно отметить, что подобное поведение негативно сказывается не только на производительности  JS кода, но и на потребляемых ресурсах при дополнительных гарантиях позволяющих избегать проблем обозначенных выше.

Если бы мы делали свой Event Loop, то он бы выглядел следующим образом:

Эта реализация не имеет ничего общего со стандартом. Например:

for (const task of eventLoop.microtasks) {

    task.execute();

  }

код пытается показать, что первым шагом выполняются все задачи из очереди microtask. Что противоречит даже логике, потому, что в заявленной очереди ничего появиться не может до выполнения хотя бы одной задачи из Task Queue. 

Начало выполнения очереди microtask queue происходит ТОЛЬКО после выполнения Task из Task queue. Шаг 2.7.

Самое интересное в данном коде находится внизу, внутри цикла while

В этом коде нет ничего интересного потому, что он показывает что угодно, но только не то, как работает Event Loop стандарта HTML5. И при этом не имеет вообще ничего общего с Event Loop из LibUv.

Все дальнейшее комментировать нет уже никаких сил.

Вместо ИГОГО

Использовать этот материал в образовательных целях крайне не рекомендуется, поскольку он отражает исключительно представление автора о том как это работает, одновременно вступая в прямое противоречие с официальной спецификацией регламентирующей как функционирование языка ECMAScript так и описывающей поведение EventLoop как часть стандарта HTML5.

Все пояснения материала, относительно того, как "что-то работает" не имеют ничего общего с реальностью и представляют из себя винегрет из существующих мифов и фантазии автора. (комментарием ниже я разбираю все детали єтого)

Касательно же вопроса о том откуда взялись макро и микротаски нужно сказать слюдующее:

Термин Task queue и microtask queue принадлежат спецификации html5 и не имеют никакого отношения к javascript. Однако Вы правы в том, что заподозрили связь между термином и существующей тому причиной.

Официальная спецификация языка JS седержала раньше две очереди: generic queue и promise queue которые никакого отношения к евент луп не имеют, но при єтом накладывают некоторые огранечения на то, как хост среда может выполнять тот или оной код. Авторы стандарта html5 просто зеркально отобразили єти очереди в свой стандарт, дополнив их необходимым им функционалом.

Важно понимать то, что в js нет и не может быть ничего подобного евент луп. То есть оригинальные очереди решают вовсем иные задачи нежели те, которые приписываются event loop

Автор материала совершенно запутался в том, где JavaScript (функция обрабатывающая событие), где внешнее API ( генерация events и подписка на них - то есть связывание binding функции с событием) и что именно является узким горлышком.

На фоне чего, декларация на тему "синтетической обработке событий" в "современных" js фреймворках, вызывает неподдельный скепсис относительно того, что автор понимает о чем говорит.

Любопытно еще и то, что, все тоже самое, умеет делать Google Developer Tools вызываемый из Google Chrome и подобных браузеров.

И делать все єто, он умеет уже не менее 5 лет. Кроме, разве что, создания каталогов в один клик.

Кто вдруг не в курсе - вкладка source => создать сниппет. Или комманда => открыть текущий код в source tab.

Ну и конечно все те-же самые ctrl - p, ctrl - shift - p...

Без которых работа в современном dev tools мало продуктивна.

Все те, кто выбрал синюю таблетку предпочли неопределённый риск смерти вместо 100% гарантии жизни. Если каждый выберет красную, то все выживут без исключения. Поэтому нет ни одного рационального повода выбирать синюю таблетку.

А еще есть люди, которые сталкивались с разного рода статиской в ввиде лайков, дизлайков и т.д. И вот среди них бытует мнение, что всегда есть около 10% проголосовавших, которые пенепутали лайк с дизлайком, зеленое с красным, палец вверх с пальцем вниз, или вообще кот лег на клавиатуру.

Так что Вы меня простите, но я все же надавлю на синюю.

работает и не лагает

в каких условиях? на каком устройстве? в каком окружении?

практика - подобная озвученной, когда якобы производительность устраивает - порочна. правильным следовало бы считать практику - получения максимальной производительности в рамках доступных ресурсов как на разработку, так и на обеспечение функционирования программы.

Предварительная оптимизация, как корень всех зол

єто фраза сказанная Дональдом Кнуттом не о том, что ненужно оптимизировать. Она о том, что нужно писать код так, чтобы компилятор мог єто сделать за человека.

В рамках архитектуры языка JavaScript, иммутабельность, а главное процесс модификации данных, делается не копированием, но путем создания цепочки прототипов.

Например у нас есть Exotic Object Array - [1,2,3] и мы хотим получить еще один подобный обьект с измененным элементом с индексом 1 на `Primitive Value` 7.
Для этого ненужно копировать обьект, а нужно сделать следующее:

var srcArray = [1,2,3];
var copyArray = Array(srcArray.length);
Object.setPrototypeOf( copyArray, srcArray);
copyArray[1] = 7;
//
copyArray[0]; // 1
copyArray[1]; // 7
copyArray[2]; // 3

То есть Вы получаете цепочку всех вычислений вышего Array, где каждый шаг изменения - это отдельный прототип.

Как следствие, никакой необходимости в копировании обьектов нет. А есть необходимость в правильной структуре данных. Что является фундаментом оптимизации любого прикладного кода.

Есть такое неписанное правило - если Вам понадобилась копия данных, то Вам нужно думать не о том, как данные копировать, но о том, что в архитектуре Вашего приложения есть ошибка.

Естественно это не касается системного программирования.

Поехали по спецификации:
delete это унарный оператор, который может удалять идентификаторы только не в строгом режиме.

Под словом удалять, подразумевается не факт того, что из Enviroment Record текущего окружения удаляется запись о идентификаторе, но подразумевается удаление ссылки (unbinding) на данные в записи идентификатора.

Как следствие этого процесса, любой код, в котором использовался этот идентификатор и который был оптимизирован будет подовергнут деоптимизации при первом же случае его выполнения.

Далее. Поскольку наш код, как мы установили, работает не в строгом режиме, это означает в том числе, возможность связывания Object Enviroment Record с текущей Enviroment Record. Как следствие, использование delete на идентификатор автоматически будет приводит и к удалению property из обьекта который связан с Object Enviroment Record.

Так же не забываем, что когда мы работаем с идентификаторами заявленными при помощи variable statement в Global Enviroment Record, это процесс будет приводить к автоматическому созданию property в global object. Как следствие применение delete к любому подобному идентификатору из Global Enviroment будет приводить к удалению property из global object

Как видим: даже если мы предположим, что delete вызывалось к идентификатору, который заявлен не в Global Enviroment и не использовался with statement (то есть мы отсекаем случай с Obejct Enviroment), даже в этом случае unbinding идентификатора с данными приведет к деоптимизации того кода, который был оптимизирован с использованием этого идентификатора.

1
23 ...

Information

Rating
5,109-th
Location
Харьков, Харьковская обл., Украина
Date of birth
Registered
Activity

Specialization

Pentester, Reverse Engineer
Lead