IKVM11  11
Java SE 11 Virtual Machine for .NET
Loading...
Searching...
No Matches
InstructionState.cs
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2014 Jeroen Frijters
3
4 This software is provided 'as-is', without any express or implied
5 warranty. In no event will the authors be held liable for any damages
6 arising from the use of this software.
7
8 Permission is granted to anyone to use this software for any purpose,
9 including commercial applications, and to alter it and redistribute it
10 freely, subject to the following restrictions:
11
12 1. The origin of this software must not be misrepresented; you must not
13 claim that you wrote the original software. If you use this software
14 in a product, an acknowledgment in the product documentation would be
15 appreciated but is not required.
16 2. Altered source versions must be plainly marked as such, and must not be
17 misrepresented as being the original software.
18 3. This notice may not be removed or altered from any source distribution.
19
20 Jeroen Frijters
21 jeroen@frijters.net
22
23*/
24using System;
25using System.Collections.Generic;
27
28namespace IKVM.Runtime
29{
30
32 {
33
35 {
36
37 int[] data;
38 int count;
39 bool shared;
40
41 internal LocalStoreSites Copy()
42 {
43 var n = new LocalStoreSites();
44 n.data = data;
45 n.count = count;
46 n.shared = true;
47 return n;
48 }
49
50 internal static LocalStoreSites Alloc()
51 {
52 var n = new LocalStoreSites();
53 n.data = new int[4];
54 return n;
55 }
56
57 internal void Add(int store)
58 {
59 for (int i = 0; i < count; i++)
60 if (data[i] == store)
61 return;
62
63 if (count == data.Length)
64 {
65 var newarray = new int[data.Length * 2];
66 Buffer.BlockCopy(data, 0, newarray, 0, data.Length * 4);
67 data = newarray;
68 shared = false;
69 }
70
71 if (shared)
72 {
73 shared = false;
74 data = (int[])data.Clone();
75 }
76
77 data[count++] = store;
78 }
79
80 internal int this[int index] => data[index];
81
82 internal int Count => count;
83
84 internal static void MarkShared(LocalStoreSites[] localStoreSites)
85 {
86 for (int i = 0; i < localStoreSites.Length; i++)
87 localStoreSites[i].shared = true;
88 }
89
90 }
91
92 enum ShareFlags : byte
93 {
94 None = 0,
95 Stack = 1,
96 Locals = 2,
97 All = Stack | Locals
98 }
99
101 RuntimeJavaType[] _stack;
104 RuntimeJavaType[] _locals;
106 internal bool _changed = true;
108 internal bool _initialized = false;
109
120 InstructionState(RuntimeContext context, RuntimeJavaType[] stack, int stackLen, int stackEnd, RuntimeJavaType[] locals, bool uninitializedThis)
121 {
122 _context = context ?? throw new ArgumentNullException(nameof(context));
123 _flags = ShareFlags.All;
124 _stack = stack;
125 _stackLen = stackLen;
126 _stackEnd = stackEnd;
127 _locals = locals;
128 _uninitializedThis = uninitializedThis;
129 _initialized = true;
130 }
131
139 internal InstructionState(RuntimeContext context, int maxLocals, int maxStack)
140 {
141 _context = context ?? throw new ArgumentNullException(nameof(context));
142 _flags = ShareFlags.None;
143 _stack = new RuntimeJavaType[maxStack];
144 _stackEnd = maxStack;
145 _locals = new RuntimeJavaType[maxLocals];
146 _initialized = true;
147 }
148
153 internal InstructionState Copy()
154 {
156 }
157
162 internal void CopyTo(ref InstructionState target)
163 {
164 if (_initialized == false)
165 throw new InvalidOperationException();
166
167 target._flags = ShareFlags.All;
168 target._stack = _stack;
169 target._stackLen = _stackLen;
170 target._stackEnd = _stackEnd;
171 target._locals = _locals;
172 target._uninitializedThis = _uninitializedThis;
173 target._changed = true;
174 target._initialized = _initialized;
175 }
176
181 internal InstructionState CopyLocals()
182 {
183 var copy = new InstructionState(_context, new RuntimeJavaType[_stack.Length], 0, _stack.Length, _locals, _uninitializedThis);
184 copy._flags &= ~ShareFlags.Stack;
185 return copy;
186 }
187
196 {
197 if (s1._initialized == false)
198 return s2.Copy();
199
200 if (s1._stackLen != s2._stackLen || s1._stackEnd != s2._stackEnd)
201 throw new VerifyError($"Inconsistent stack height: {s1._stackLen + s1._stack.Length - s1._stackEnd} != {s2._stackLen + s2._stack.Length - s2._stackEnd}");
202
203 var s = s1.Copy();
204 s._changed = s1._changed;
205
206 for (int i = 0; i < s._stackLen; i++)
207 {
208 var type1 = s._stack[i];
209 var type2 = s2._stack[i];
210 if (type1 == type2)
211 {
212 // perfect match, nothing to do
213 }
214 else if ((type1 == s1._context.VerifierJavaTypeFactory.ExtendedDouble && type2 == s1._context.PrimitiveJavaTypeFactory.DOUBLE) || (type2 == s1._context.VerifierJavaTypeFactory.ExtendedDouble && type1 == s1._context.PrimitiveJavaTypeFactory.DOUBLE))
215 {
216 if (type1 != s1._context.VerifierJavaTypeFactory.ExtendedDouble)
217 {
218 s.StackCopyOnWrite();
219 s._stack[i] = s1._context.VerifierJavaTypeFactory.ExtendedDouble;
220 s._changed = true;
221 }
222 }
223 else if ((type1 == s1._context.VerifierJavaTypeFactory.ExtendedFloat && type2 == s1._context.PrimitiveJavaTypeFactory.FLOAT) || (type2 == s1._context.VerifierJavaTypeFactory.ExtendedFloat && type1 == s1._context.PrimitiveJavaTypeFactory.FLOAT))
224 {
225 if (type1 != s1._context.VerifierJavaTypeFactory.ExtendedFloat)
226 {
227 s.StackCopyOnWrite();
228 s._stack[i] = s1._context.VerifierJavaTypeFactory.ExtendedFloat;
229 s._changed = true;
230 }
231 }
232 else if (!type1.IsPrimitive)
233 {
234 var baseType = FindCommonBaseType(s1._context, type1, type2);
235 if (baseType == s1._context.VerifierJavaTypeFactory.Invalid)
236 throw new VerifyError(string.Format("cannot merge {0} and {1}", type1.Name, type2.Name));
237
238 if (type1 != baseType)
239 {
240 s.StackCopyOnWrite();
241 s._stack[i] = baseType;
242 s._changed = true;
243 }
244 }
245 else
246 {
247 throw new VerifyError(string.Format("cannot merge {0} and {1}", type1.Name, type2.Name));
248 }
249 }
250
251 for (int i = 0; i < s._locals.Length; i++)
252 {
253 var type = s._locals[i];
254 var type2 = s2._locals[i];
255 var baseType = FindCommonBaseType(s1._context, type, type2);
256 if (type != baseType)
257 {
258 s.LocalsCopyOnWrite();
259 s._locals[i] = baseType;
260 s._changed = true;
261 }
262 }
263
264 if (!s._uninitializedThis && s2._uninitializedThis)
265 {
266 s._uninitializedThis = true;
267 s._changed = true;
268 }
269
270 return s;
271 }
272
273 internal void SetUnitializedThis(bool state)
274 {
275 _uninitializedThis = state;
276 }
277
278 internal void CheckUninitializedThis()
279 {
281 throw new VerifyError("Base class constructor wasn't called");
282 }
283
284 internal static RuntimeJavaType FindCommonBaseType(RuntimeContext context, RuntimeJavaType type1, RuntimeJavaType type2)
285 {
286 // types are equal
287 if (type1 == type2)
288 return type1;
289
290 // merging java.lang.Object with anything can only result in java.lang.Object
291 if (type1 == context.JavaBase.TypeOfJavaLangObject || type2 == context.JavaBase.TypeOfJavaLangObject)
292 return context.JavaBase.TypeOfJavaLangObject;
293
294 // first type is null, return second
295 if (type1 == context.VerifierJavaTypeFactory.Null)
296 return type2;
297
298 // second type is null, return first
299 if (type2 == context.VerifierJavaTypeFactory.Null)
300 return type1;
301
302 // verifier invalid
303 if (type1 == context.VerifierJavaTypeFactory.Invalid || type2 == context.VerifierJavaTypeFactory.Invalid)
304 return context.VerifierJavaTypeFactory.Invalid;
305
306 if (RuntimeVerifierJavaType.IsFaultBlockException(type1))
307 {
308 RuntimeVerifierJavaType.ClearFaultBlockException(type1);
309 return FindCommonBaseType(context, context.JavaBase.TypeOfjavaLangThrowable, type2);
310 }
311
312 if (RuntimeVerifierJavaType.IsFaultBlockException(type2))
313 {
314 RuntimeVerifierJavaType.ClearFaultBlockException(type2);
315 return FindCommonBaseType(context, type1, context.JavaBase.TypeOfjavaLangThrowable);
316 }
317
318 // primitive types cannot be merged
319 if (type1.IsPrimitive || type2.IsPrimitive)
320 return context.VerifierJavaTypeFactory.Invalid;
321
322 // this type without init being run cannot be merged
323 if (type1 == context.VerifierJavaTypeFactory.UninitializedThis || type2 == context.VerifierJavaTypeFactory.UninitializedThis)
324 return context.VerifierJavaTypeFactory.Invalid;
325
326 // new verifier type cannot be merged
327 if (RuntimeVerifierJavaType.IsNew(type1) || RuntimeVerifierJavaType.IsNew(type2))
328 return context.VerifierJavaTypeFactory.Invalid;
329
330 // this type can only be its own underlying
331 if (RuntimeVerifierJavaType.IsThis(type1))
332 type1 = ((RuntimeVerifierJavaType)type1).UnderlyingType;
333
334 // this type can only be its own underlying
335 if (RuntimeVerifierJavaType.IsThis(type2))
336 type2 = ((RuntimeVerifierJavaType)type2).UnderlyingType;
337
338 // unloadable types cannot be merged
339 if (type1.IsUnloadable || type2.IsUnloadable)
340 return context.VerifierJavaTypeFactory.Unloadable;
341
342 // unpack array types into underlying element
343 if (type1.ArrayRank > 0 && type2.ArrayRank > 0)
344 {
345 int rank = 1;
346 int rank1 = type1.ArrayRank - 1;
347 int rank2 = type2.ArrayRank - 1;
348 var elem1 = type1.ElementTypeWrapper;
349 var elem2 = type2.ElementTypeWrapper;
350 while (rank1 != 0 && rank2 != 0)
351 {
352 elem1 = elem1.ElementTypeWrapper;
353 elem2 = elem2.ElementTypeWrapper;
354 rank++;
355 rank1--;
356 rank2--;
357 }
358
359 // NOTE arrays of value types have special merging semantics!
360 // NOTE we don't have to test for the case where the element types are the same, because that
361 // is only relevant if the ranks are the same, but if that is the case the types are completely
362 // identical, in which case the identity test at the top of this method already returned.
363 RuntimeJavaType baseType;
364 if (elem1.IsPrimitive || elem2.IsPrimitive || elem1.IsNonPrimitiveValueType || elem2.IsNonPrimitiveValueType)
365 {
366 baseType = context.JavaBase.TypeOfJavaLangObject;
367 rank--;
368 if (rank == 0)
369 return baseType;
370 }
371 else
372 {
373 baseType = FindCommonBaseTypeHelper(context, elem1, elem2);
374 }
375
376 // rebuild array type
377 return baseType.MakeArrayType(rank);
378 }
379
380 return FindCommonBaseTypeHelper(context, type1, type2);
381 }
382
383 static RuntimeJavaType FindCommonBaseTypeHelper(RuntimeContext context, RuntimeJavaType type1, RuntimeJavaType type2)
384 {
385 if (type1 == type2)
386 return type1;
387
388 // NOTE according to a paper by Alessandro Coglio & Allen Goldberg titled
389 // "Type Safety in the JVM: Some Problems in Java 2 SDK 1.2 and Proposed Solutions"
390 // the common base of two interfaces is java.lang.Object, and there is special
391 // treatment for java.lang.Object types that allow it to be assigned to any interface
392 // type, the JVM's typesafety then depends on the invokeinterface instruction to make
393 // sure that the reference actually implements the interface.
394 // NOTE the ECMA CLI spec also specifies this interface merging algorithm, so we can't
395 // really do anything more clever than this.
396 if (type1.IsInterface && type2.IsInterface)
397 return context.JavaBase.TypeOfJavaLangObject;
398
399 // t1 is an interface and is implemented by t2, common base type is t1
400 if (type1.IsInterface)
401 return type2.ImplementsInterface(type1) ? type1 : context.JavaBase.TypeOfJavaLangObject;
402
403 // t2 is an interface and is implemented by t1, common base type is t2
404 if (type2.IsInterface)
405 return type1.ImplementsInterface(type2) ? type2 : context.JavaBase.TypeOfJavaLangObject;
406
407 var st1 = new Stack<RuntimeJavaType>();
408 while (type1 != null)
409 {
410 st1.Push(type1);
411 type1 = type1.BaseTypeWrapper;
412 }
413
414 var st2 = new Stack<RuntimeJavaType>();
415 while (type2 != null)
416 {
417 st2.Push(type2);
418 type2 = type2.BaseTypeWrapper;
419 }
420
421 // pop each item off of the stacks until they do not match
422 var type = context.JavaBase.TypeOfJavaLangObject;
423 for (; ; )
424 {
425 type1 = st1.Count > 0 ? st1.Pop() : null;
426 type2 = st2.Count > 0 ? st2.Pop() : null;
427 if (type1 != type2)
428 return type;
429
430 type = type1;
431 }
432 }
433
434 void SetLocal1(int index, RuntimeJavaType type)
435 {
436 try
437 {
439 if (index > 0 && _locals[index - 1] != _context.VerifierJavaTypeFactory.Invalid && _locals[index - 1].IsWidePrimitive)
440 _locals[index - 1] = _context.VerifierJavaTypeFactory.Invalid;
441
442 _locals[index] = type;
443 }
444 catch (IndexOutOfRangeException)
445 {
446 throw new VerifyError("Illegal local variable number");
447 }
448 }
449
450 void SetLocal2(int index, RuntimeJavaType type)
451 {
452 try
453 {
455 if (index > 0 && _locals[index - 1] != _context.VerifierJavaTypeFactory.Invalid && _locals[index - 1].IsWidePrimitive)
456 _locals[index - 1] = _context.VerifierJavaTypeFactory.Invalid;
457
458 _locals[index] = type;
459 _locals[index + 1] = _context.VerifierJavaTypeFactory.Invalid;
460 }
461 catch (IndexOutOfRangeException)
462 {
463 throw new VerifyError("Illegal local variable number");
464 }
465 }
466
467 internal void GetLocalInt(int index)
468 {
469 if (GetLocalType(index) != _context.PrimitiveJavaTypeFactory.INT)
470 throw new VerifyError("Invalid local type");
471 }
472
473 internal void SetLocalInt(int index, int instructionIndex)
474 {
476 }
477
478 internal void GetLocalLong(int index)
479 {
480 if (GetLocalType(index) != _context.PrimitiveJavaTypeFactory.LONG)
481 throw new VerifyError("incorrect local type, not long");
482 }
483
484 internal void SetLocalLong(int index, int instructionIndex)
485 {
487 }
488
489 internal void GetLocalFloat(int index)
490 {
491 if (GetLocalType(index) != _context.PrimitiveJavaTypeFactory.FLOAT)
492 throw new VerifyError("incorrect local type, not float");
493 }
494
495 internal void SetLocalFloat(int index, int instructionIndex)
496 {
498 }
499
500 internal void GetLocalDouble(int index)
501 {
502 if (GetLocalType(index) != _context.PrimitiveJavaTypeFactory.DOUBLE)
503 throw new VerifyError("incorrect local type, not double");
504 }
505
506 internal void SetLocalDouble(int index, int instructionIndex)
507 {
509 }
510
511 internal RuntimeJavaType GetLocalType(int index)
512 {
513 try
514 {
515 return _locals[index];
516 }
517 catch (IndexOutOfRangeException)
518 {
519 throw new VerifyError("Illegal local variable number");
520 }
521 }
522
523 // this is used by the compiler (indirectly, through MethodAnalyzer.GetLocalTypeWrapper),
524 // we've already verified the code so we know we won't run outside the array boundary,
525 // and we don't need to record the fact that we're reading the local.
526 internal RuntimeJavaType GetLocalTypeEx(int index)
527 {
528 return _locals[index];
529 }
530
531 internal void SetLocalType(int index, RuntimeJavaType type, int instructionIndex)
532 {
533 if (type.IsWidePrimitive)
534 SetLocal2(index, type);
535 else
536 SetLocal1(index, type);
537 }
538
539 internal void PushType(RuntimeJavaType type)
540 {
541 if (type.IsIntOnStackPrimitive)
543
544 PushHelper(type);
545 }
546
547 internal void PushInt()
548 {
550 }
551
552 internal void PushLong()
553 {
555 }
556
557 internal void PushFloat()
558 {
560 }
561
562 internal void PushExtendedFloat()
563 {
565 }
566
567 internal void PushDouble()
568 {
570 }
571
572 internal void PushExtendedDouble()
573 {
575 }
576
577 internal void PopInt()
578 {
579 PopIntImpl(PopAnyType());
580 }
581
582 internal static void PopIntImpl(RuntimeJavaType type)
583 {
584 if (type != type.Context.PrimitiveJavaTypeFactory.INT)
585 throw new VerifyError("Int expected on stack");
586 }
587
588 internal bool PopFloat()
589 {
590 var tw = PopAnyType();
591 PopFloatImpl(tw);
592 return tw == _context.VerifierJavaTypeFactory.ExtendedFloat;
593 }
594
595 internal static void PopFloatImpl(RuntimeJavaType tw)
596 {
597 if (tw != tw.Context.PrimitiveJavaTypeFactory.FLOAT && tw != tw.Context.VerifierJavaTypeFactory.ExtendedFloat)
598 throw new VerifyError("Float expected on stack");
599 }
600
601 internal bool PopDouble()
602 {
603 var tw = PopAnyType();
604 PopDoubleImpl(tw);
605 return tw == _context.VerifierJavaTypeFactory.ExtendedDouble;
606 }
607
608 internal static void PopDoubleImpl(RuntimeJavaType tw)
609 {
610 if (tw != tw.Context.PrimitiveJavaTypeFactory.DOUBLE && tw != tw.Context.VerifierJavaTypeFactory.ExtendedDouble)
611 throw new VerifyError("Double expected on stack");
612 }
613
614 internal void PopLong()
615 {
616 PopLongImpl(PopAnyType());
617 }
618
619 internal static void PopLongImpl(RuntimeJavaType tw)
620 {
621 if (tw != tw.Context.PrimitiveJavaTypeFactory.LONG)
622 {
623 throw new VerifyError("Long expected on stack");
624 }
625 }
626
627 internal RuntimeJavaType PopArrayType()
628 {
629 return PopArrayTypeImpl(PopAnyType());
630 }
631
632 internal static RuntimeJavaType PopArrayTypeImpl(RuntimeJavaType type)
633 {
634 if (!RuntimeVerifierJavaType.IsNullOrUnloadable(type) && type.ArrayRank == 0)
635 throw new VerifyError("Array reference expected on stack");
636
637 return type;
638 }
639
640 // null or an initialized object reference
641 internal RuntimeJavaType PopObjectType()
642 {
643 return PopObjectTypeImpl(PopType());
644 }
645
646 internal static RuntimeJavaType PopObjectTypeImpl(RuntimeJavaType type)
647 {
648 if (type.IsPrimitive || RuntimeVerifierJavaType.IsNew(type) || type == type.Context.VerifierJavaTypeFactory.UninitializedThis)
649 throw new VerifyError("Expected object reference on stack");
650
651 return type;
652 }
653
654 // null or an initialized object reference derived from baseType (or baseType)
655 internal RuntimeJavaType PopObjectType(RuntimeJavaType baseType)
656 {
657 return PopObjectTypeImpl(baseType, PopObjectType());
658 }
659
660 internal static RuntimeJavaType PopObjectTypeImpl(RuntimeJavaType baseType, RuntimeJavaType type)
661 {
662 // HACK because of the way interfaces references works, if baseType
663 // is an interface or array of interfaces, any reference will be accepted
664 if (!baseType.IsUnloadable && !baseType.IsInterfaceOrInterfaceArray && !(type.IsUnloadable || type.IsAssignableTo(baseType)))
665 throw new VerifyError("Unexpected type " + type.Name + " where " + baseType.Name + " was expected");
666
667 return type;
668 }
669
670 internal RuntimeJavaType PeekType()
671 {
672 if (_stackLen == 0)
673 throw new VerifyError("Unable to pop operand off an empty stack");
674
675 return _stack[_stackLen - 1];
676 }
677
678 internal void MultiPopAnyType(int count)
679 {
680 while (count-- != 0)
681 PopAnyType();
682 }
683
684 internal RuntimeJavaType PopFaultBlockException()
685 {
686 return _stack[--_stackLen];
687 }
688
689 internal RuntimeJavaType PopAnyType()
690 {
691 if (_stackLen == 0)
692 throw new VerifyError("Unable to pop operand off an empty stack");
693
694 var type = _stack[--_stackLen];
695 if (type.IsWidePrimitive || type == _context.VerifierJavaTypeFactory.ExtendedDouble)
696 _stackEnd++;
697
698 if (RuntimeVerifierJavaType.IsThis(type))
699 type = ((RuntimeVerifierJavaType)type).UnderlyingType;
700
701 if (RuntimeVerifierJavaType.IsFaultBlockException(type))
702 {
703 RuntimeVerifierJavaType.ClearFaultBlockException(type);
704 type = _context.JavaBase.TypeOfjavaLangThrowable;
705 }
706
707 return type;
708 }
709
710 // NOTE this can *not* be used to pop double or long
711 internal RuntimeJavaType PopType()
712 {
713 return PopTypeImpl(PopAnyType());
714 }
715
716 internal static RuntimeJavaType PopTypeImpl(RuntimeJavaType type)
717 {
718 if (type.IsWidePrimitive || type == type.Context.VerifierJavaTypeFactory.ExtendedDouble)
719 throw new VerifyError("Attempt to split long or double on the stack");
720
721 return type;
722 }
723
724 // this will accept null, a primitive type of the specified type or an initialized reference of the
725 // specified type or derived from it
726 // NOTE this can also be used to pop double or long
727 internal RuntimeJavaType PopType(RuntimeJavaType baseType)
728 {
729 return PopTypeImpl(baseType, PopAnyType());
730 }
731
732 internal static RuntimeJavaType PopTypeImpl(RuntimeJavaType baseType, RuntimeJavaType type)
733 {
734 if (baseType.IsIntOnStackPrimitive)
735 baseType = baseType.Context.PrimitiveJavaTypeFactory.INT;
736
737 if (RuntimeVerifierJavaType.IsNew(type) || type == type.Context.VerifierJavaTypeFactory.UninitializedThis)
738 throw new VerifyError("Expecting to find object/array on stack");
739
740 if (type == baseType)
741 return type;
742
743 if (type == baseType.Context.VerifierJavaTypeFactory.ExtendedDouble && baseType == baseType.Context.PrimitiveJavaTypeFactory.DOUBLE)
744 return type;
745
746 if (type == baseType.Context.VerifierJavaTypeFactory.ExtendedFloat && baseType == baseType.Context.PrimitiveJavaTypeFactory.FLOAT)
747 return type;
748
749 if (type.IsPrimitive == false && baseType.IsPrimitive == false)
750 {
751 if (baseType == baseType.Context.JavaBase.TypeOfJavaLangObject)
752 return type;
753
754 if (type.IsUnloadable || baseType.IsUnloadable)
755 return type;
756
757 // because of the way interfaces references works, if baseType
758 // is an interface or array of interfaces, any reference will be accepted
759 if (baseType.IsInterfaceOrInterfaceArray)
760 return type;
761
762 if (type.IsAssignableTo(baseType))
763 return type;
764
765 if (HasMissingBaseType(type) || HasMissingBaseType(baseType))
766 return type;
767 }
768
769 throw new VerifyError("Unexpected type " + type.Name + " where " + baseType.Name + " was expected");
770 }
771
772 static bool HasMissingBaseType(RuntimeJavaType tw)
773 {
774#if IMPORTER
775 for (RuntimeJavaType baseTypeWrapper; (baseTypeWrapper = tw.BaseTypeWrapper) != null; tw = baseTypeWrapper)
776 {
777 if (baseTypeWrapper.IsUnloadable)
778 {
779 tw.Context.StaticCompiler.IssueMissingTypeMessage(tw.TypeAsBaseType.BaseType);
780 return true;
781 }
782 }
783#endif
784 return false;
785 }
786
787 internal int GetStackHeight()
788 {
789 return _stackLen;
790 }
791
792 internal RuntimeJavaType GetStackSlot(int pos)
793 {
794 var tw = _stack[_stackLen - 1 - pos];
795 if (tw == _context.VerifierJavaTypeFactory.ExtendedDouble)
797 else if (tw == _context.VerifierJavaTypeFactory.ExtendedFloat)
799
800 return tw;
801 }
802
803 internal RuntimeJavaType GetStackSlotEx(int pos)
804 {
805 return _stack[_stackLen - 1 - pos];
806 }
807
808 internal RuntimeJavaType GetStackByIndex(int index)
809 {
810 return _stack[index];
811 }
812
813 void PushHelper(RuntimeJavaType type)
814 {
815 if (type.IsWidePrimitive || type == _context.VerifierJavaTypeFactory.ExtendedDouble)
816 _stackEnd--;
817
818 if (_stackLen >= _stackEnd)
819 throw new VerifyError("Stack overflow");
820
822 _stack[_stackLen++] = type;
823 }
824
825 internal void MarkInitialized(RuntimeJavaType type, RuntimeJavaType initType, int instructionIndex)
826 {
827 System.Diagnostics.Debug.Assert(type != null && initType != null);
828
829 for (int i = 0; i < _locals.Length; i++)
830 {
831 if (_locals[i] == type)
832 {
834 _locals[i] = initType;
835 }
836 }
837
838 for (int i = 0; i < _stackLen; i++)
839 {
840 if (_stack[i] == type)
841 {
843 _stack[i] = initType;
844 }
845 }
846 }
847
852 {
853 if ((_flags & ShareFlags.Stack) != 0)
854 {
855 _flags &= ~ShareFlags.Stack;
856 _stack = (RuntimeJavaType[])_stack.Clone();
857 }
858 }
859
864 {
865 if ((_flags & ShareFlags.Locals) != 0)
866 {
867 _flags &= ~ShareFlags.Locals;
868 _locals = (RuntimeJavaType[])_locals.Clone();
869 }
870 }
871
872 internal void ClearFaultBlockException()
873 {
874 if (RuntimeVerifierJavaType.IsFaultBlockException(_stack[0]))
875 {
877 _changed = true;
878 _stack[0] = _context.JavaBase.TypeOfjavaLangThrowable;
879 }
880 }
881
882 }
883
884}
Maintains services relevant to an instane of the IKVM runtime.
RuntimePrimitiveJavaTypeFactory PrimitiveJavaTypeFactory
Gets the RuntimePrimitiveJavaTypeFactory associated with this instance of the runtime.
RuntimeVerifierJavaTypeFactory VerifierJavaTypeFactory
Gets the RuntimeVerifierJavaTypeFactory associated with this instance of the runtime.
CoreClasses JavaBase
Gets the CoreClasses associated with this instance of the runtime.
static InstructionState operator+(InstructionState s1, InstructionState s2)
Creates a new state which is the merged combination of the two specified states.
static bool HasMissingBaseType(RuntimeJavaType tw)
void SetLocal2(int index, RuntimeJavaType type)
readonly RuntimeContext _context
void StackCopyOnWrite()
Copies the stack for future modification.
void PushHelper(RuntimeJavaType type)
static RuntimeJavaType FindCommonBaseTypeHelper(RuntimeContext context, RuntimeJavaType type1, RuntimeJavaType type2)
InstructionState(RuntimeContext context, RuntimeJavaType[] stack, int stackLen, int stackEnd, RuntimeJavaType[] locals, bool uninitializedThis)
Initializes a new instance.
void SetLocal1(int index, RuntimeJavaType type)
void LocalsCopyOnWrite()
Copies the locals for future modification.