Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, Serginio1, Вы писали: S>> И чем это плохо???? S>Плохо тем, что это не верифицируется. Потому, что нет способа убедиться, что ты вернул из пользовательского кода не просто управляемый указатель, а управляемый указатель на валидный объект. К сожалению, инструкции ldarga и ldloca портят всю картину.
Ну дык возврат стековой переменной должен быть пресечен уже на этапе компиляции. Или я не о том.
Что в данном случае верификация????
S>На самом деле, для кулдевелоперов есть-таки лазейка. Можно локализовать такой код в сборке, которой выдается привилегия игнорировать верификацию.
... << RSDN@Home 1.1.4 beta 4 rev. 303>>
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, Sinclair, Вы писали:
S>Более полное использование ссылок в интерфейсах могло бы разрешить нам порождение сверхвысокоэффективных многомерных массивов вэлью-типов обобщеннным способом. S>Если бы мы могли сделать вот такой интерфейс: S>
S>public interface IBitmap<PointType>
S>{
S> public int Height;
S> public int Width;
S> public PointType&this[int x, int y]{ get;}
S>}
S>
S>то это было бы офигеть как круто в смысле производительности.
А что было бы в смысле инкапсуляции? Ведь ты сразу октываешь возможность прямой модификации памяти. Вся инкапсуляция идет лесом.
Тут было бы разумно сделать следующее. Наложить на компилятор обязанности эмулировать модификацию поместу. Возомжно даже ввести в свойства новую семантику обеспечивающую такую модификацию. Ну, например:
class A<T>
{
T[] _array;
public T this[int index]
{
get { return _array[index]; }
set { _array[index] = value; }
replace
{
yeld return _array[index];
}
}
}
Тогда можно было и инкапсуляцию сохранить:
class A<T>
{
T[] _array;
public T this[int index]
{
get { return _array[index]; }
set { _array[index] = value; }
replace
{
T temp = _array[index];
yeld return temp;
if (!Check(temp))
throw new Exception("Попытка установить ошибочное значение!");
_array[index] = temp;
}
}
}
И эффектино обрабатывать случаи модификации по месту, так как оптимизировать ее уже было бы делом техники.
Возможно даж можно обойтись без расширения техники. В принципе ведь джит может определять, что свойства являются прямыми эксесорами к ячейкам памяти и видя модификацию по месту (которую он сейчас отвергает) просто оптимизировать код. Более того нечто похожее происходит при работе с простыми типами и просыми свойствами. Надо лишь распространить эту практику и дальше. Тогда и ссылки будут не нужны, и эффектиность с удосбтвом поднимутся.
... << RSDN@Home 1.1.4 beta 3 rev. 279>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Не смущай человека: TypedReference и T% — совершенно разные вещи.
Не, Пашь, я тебе уже хрен знает сколько времени пытаюсь объяснить, что это одно и тоже. Жц не может просто указателями пользоваться если они не на начало объекта в хипе указывают. Иначе сбивается алгоритм перестановки объектов в памяти. Так что джит видя возврат ссылки лепит приблизительно такую конструкцию. И эффектиность этого дела, по словам народа копающегося в ЖЦ, далека от прямых ссылок.
... << RSDN@Home 1.1.4 beta 3 rev. 279>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, Serginio1, Вы писали:
S>> Даешь ссылку не только в стеке.
VD>Это невозможно при данном устройстве ЖЦ. Да и вредно с точки зрения инкапсуляции.
Ну делегаты по своей сути тоже являются своего рода ссылками. И ничего. Приведенная мной структура будет съедобна для ЖЦ, тип известен нужно только смещение. Или ввели бы по аналогии с делегатами типизированные FieldInfo
... << RSDN@Home 1.1.4 beta 4 rev. 303>>
и солнце б утром не вставало, когда бы не было меня
VladD2,
> ПК>Не смущай человека: TypedReference и T% — совершенно разные вещи.
> Не, Пашь, я тебе уже хрен знает сколько времени пытаюсь объяснить, что это одно и тоже. Жц не может просто указателями пользоваться если они не на начало объекта в хипе указывают. Иначе сбивается алгоритм перестановки объектов в памяти. Так что джит видя возврат ссылки лепит приблизительно такую конструкцию.
О! Так это не оговорка, а заблуждение Смотри сюда:
public ref class A
{
public:
int% a();
private:
int x_; // чтоб i_ было не в начале объектаint i_;
};
Пока никаких TypedReference, обычные managed pointers.
Едем дальше. Вот во что это выливается после работы JIT:
int% A::a()
{
return i_;
00000000 push edi
00000001 push esi
00000002 test dword ptr [esp+FFFFFBC0h],eax
00000009 mov edi,ecx
0000000b cmp dword ptr ds:[001D8314h],0
00000012 je 00000019
00000014 call 760C389D
00000019 xor esi,esi
0000001b lea eax,[edi+8]
0000001e cmp ecx,dword ptr [eax]
00000020 mov esi,eax
}
00000022 mov eax,esi
00000024 pop esi
00000025 pop edi
00000026 ret
вызов:
void C::test()
{
00000000 push edi
00000001 push esi
00000002 test dword ptr [esp+FFFFFBC0h],eax
00000009 cmp dword ptr ds:[001D8314h],0
00000010 je 00000017
00000012 call 760C3935
00000017 xor edi,edi
00000019 xor edi,edi
A a;
0000001b mov ecx,3696CD8h
00000020 call FD2FE2C4
00000025 mov esi,eax
00000027 mov ecx,esi
00000029 call dword ptr ds:[03696D10h]
0000002f mov edi,esi
a.a() = 15;
00000031 mov ecx,edi
00000033 call dword ptr ds:[03696D0Ch]
00000039 mov esi,eax
0000003b mov dword ptr [esi],0Fh
}
00000041 nop
00000042 pop esi
00000043 pop edi
00000044 ret
И снова никаких TypedReference, после JIT остались одни "голые" указатели
> И эффектиность этого дела, по словам народа копающегося в ЖЦ, далека от прямых ссылок.
Как можно заметить, эффективность самих операций вполне нормальная. По сути прямые ссылки (точнее, указатели) и есть.
Posted via RSDN NNTP Server 2.0 alpha
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Sinclair,
> Поэтому единственный способ генерировать валидируемый мсил, оставляя возможности возврата ссылок из методов — это инлайнить все такие методы.
Не нужно ничего инлайнить. Можно верифицировать сами методы. Аналогичная верификация самих методов по спецификации все равно необходима, т.к., например, нужно гарантировать, что все переменные инициализированы и т.п.
> ПК>Вполне можно было ввести этот контроль при проверке определения соответствующей функции, просто им лень стало это делать:
> Ну, я вот не уверен, что проблема только в лени. Возможно, они имели в виду фатальные последствия для производительности, в связи с отсутствием возможности статической проверки.
Вот пример алгоритма: http://www.nesterovsky-bros.com/html/css2/Byref%20verification.html
> Кстати, вообще правила верификации MSIL разрабатывались таким образом, чтобы, к примеру, гарантированно можно было построить однопроходный верификатор. И я подозреваю — неспроста.
Алгоритм выше, по крайней мере на первый взгляд, вполне вписывается в эти условия...
Posted via RSDN NNTP Server 2.0 alpha
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Sinclair,
> S> И чем это плохо????
> Плохо тем, что это не верифицируется. Потому, что нет способа убедиться, что ты вернул из пользовательского кода не просто управляемый указатель, а управляемый указатель на валидный объект.
Подозреваю, что это не совсем так. Стандарт CLI не требует верифицировать подобное использование managed pointers, но это не означает, что некоторая реализация не сможет этого делать. Более того, стандарт явным образом разрешает реализациям расширять правила, определяющие что есть verifiable code. Полагаю, что реализация от Microsoft делает что-то в таком роде, т.к. C++/CLI замечательно компилирует возврат "правильных" managed pointers в режиме /clr:safe. При этом на возврат "неправильного" managed pointer (например, указывающего на стек):
int% A::a()
{
int i;
return i;
}
ругается таким образом:
d:\users\pavel\test\cli\cpp_cli\a.cpp(9) : error C4801:
Return by reference is not verifiable: gc-lvalue is from an unknown source
Posted via RSDN NNTP Server 2.0 alpha
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
P.S.
> стандарт явным образом разрешает реализациям расширять правила, определяющие что есть verifiable code. Полагаю, что реализация от Microsoft делает что-то в таком роде, т.к. C++/CLI замечательно компилирует возврат "правильных" managed pointers в режиме /clr:safe.
Да, кстати, вызовы этих функций тоже замечательно компилируются в режиме /clr:safe. Добавляю это замечание, т.к. по "стандартному" алгоритму неверифицируемыми считаются именно вызовы.
Posted via RSDN NNTP Server 2.0 alpha
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Serginio1,
> Не так не интересно > ПК>void C::test() > ПК>{ > ПК> A a; > int% b=a.a(); > > // что то делаем создаем объекты вызываем GC.Collect > > b = 15; > ПК> > ПК>} > ПК>[/c]
Легко (при этом, замечу, компилируемся в режиме /clr:safe):
void C::test()
{
A a;
int% b = a.a();
array<A^>^ arr = gcnew array<A^>(100);
for ( int i = 0; i < 100; ++i )
arr[i] = gcnew A();
for ( int i = 0; i < 100; ++i )
arr[i] = gcnew A();
GC::Collect();
b = 15;
}
Насколько я понимаю, GC замечательно отслеживает managed pointers, находящиеся в стеке, и изменяет их, если нужно. На то они и [b]managed pointers[b] Собственно, это и написано в спецификации.
Posted via RSDN NNTP Server 2.0 alpha
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Да еще. Лучше вызывать метод в котором будут порждаться и собираться мусор, желателлно с некоторой сортировкой массива объектов для изменения ссылок. Причем после сбороа мусора повторить операцию (на райт бариер за одно посмотреть). Что бы крыша у GC съехала. А в таком виде GC достаточно хорошо оптимизирует
... << RSDN@Home 1.1.4 beta 4 rev. 303>>
и солнце б утром не вставало, когда бы не было меня
Нет, это экземпляр ref класса. Просто C++/CLI позволяет не писать gcnew, если использовать синтаксис "как будто в стеке" для ref классов.
> Интересно посмотреть на ссылку экземпляра класса. Так как он должен поддвергнуться сборке мусора
Попробовал. В этом примере значения b одинаковы в начале и конце функции. При этом указывают они туда, куда надо: a->a() при записи в b меняется соответствующим образом.
Posted via RSDN NNTP Server 2.0 alpha
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Serginio1,
> Да еще. Лучше вызывать метод в котором будут порждаться и собираться мусор, желателлно с некоторой сортировкой массива объектов для изменения ссылок. Причем после сбороа мусора повторить операцию (на райт бариер за одно посмотреть). Что бы крыша у GC съехала. А в таком виде GC достаточно хорошо оптимизирует
Можно конкретный примерчик? Если на C++/CLI непривычно, можешь на C# (за исключением T%, ессно). А то я уже нить потерял...
Posted via RSDN NNTP Server 2.0 alpha
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен