Check-in [7047d001f4]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Stack slices together in frames for easier debugging; Make debug slices only handled when debugging is enabled; Do not perform breakpoint if not debugging.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 7047d001f49416f4f98667110195ef1f1409ad47
User & Date: stephanie.gawroriski 2019-11-03 12:22:40
Context
2019-11-04
08:02
Backup developer notes. check-in: b7c1ab1db1 user: squirreljme tags: trunk
2019-11-03
12:22
Stack slices together in frames for easier debugging; Make debug slices only handled when debugging is enabled; Do not perform breakpoint if not debugging. check-in: 7047d001f4 user: stephanie.gawroriski tags: trunk
11:52
Make the CPU registers print out a bit nicer. check-in: 747fc8a67f user: stephanie.gawroriski tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to runt/libs/summercoat-vm/cc/squirreljme/vm/summercoat/NativeCPU.java.

63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
..
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
...
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
...
211
212
213
214
215
216
217











218
219
220
221
222
223
224
225





226

227
228
229
230
231
232
233
...
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
...
412
413
414
415
416
417
418
419
420
421
422


423
424
425
426
427
428

429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448

449
450
451
452
453
454
455
456
457

458
459
460
461
462
463
464
465
466
467
468



469
470
471
472
473
474
475
476
477
478
479


480
481
482
483
484
485
486
...
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
...
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
...
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
...
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
...
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
...
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
...
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
...
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
....
1625
1626
1627
1628
1629
1630
1631



1632
1633
1634
1635
1636
1637
1638
....
1673
1674
1675
1676
1677
1678
1679









1680
1681
1682
	
	/** Spill over protection for the cache. */
	public static final int METHOD_CACHE_SPILL =
		1024;
	
	/** The number of execution slices to store. */
	public static final int MAX_EXECUTION_SLICES =
		128;
	
	/** Threshhold for too many debug points */
	private static final int _POINT_THRESHOLD =
		65536;
	
	/** The machine state. */
	protected final MachineState state;
................................................................................
	private final int[] _syscallerrors =
		new int[SystemCallIndex.NUM_SYSCALLS];
	
	/** Super visor properties. */
	private final int[] _supervisorproperties =
		new int[SupervisorPropertyIndex.NUM_PROPERTIES];
	
	/** Execution slices. */
	private final Deque<ExecutionSlice> _execslices =
		new LinkedList<>();
	
	/**
	 * Initializes the native CPU.
	 *
	 * @param __ms The machine state.
	 * @param __mem The memory space.
	 * @param __ps The profiler to use.
	 * @param __vcid Virtual CPU id.
................................................................................
	 */
	public final Frame enterFrame(int __pc, int... __args)
	{
		// Old frame, to source globals from
		LinkedList<Frame> frames = this._frames;
		Frame lastframe = frames.peekLast();
		
		// Debug
		if (ENABLE_DEBUG)
		{
			System.err.printf(">>>> %08x >>>>>>>>>>>>>>>>>>>>>>%n", __pc);
			System.err.printf(" > ARG %s%n", new IntegerList(__args));
			System.err.printf(" > WAS %s%n", (lastframe == null ? null :
				this.trace(lastframe)));
		}
		
		// Setup new frame
		Frame rv = new Frame();
		rv._pc = __pc;
		rv._entrypc = __pc;
		rv._lastpc = __pc;
		
		// Add to frame list
................................................................................
		
		// Failed
		catch (VMException|InvalidInstructionException e)
		{
			// Spacer
			System.err.println("********************************************");
			











			// Print all the various execution slices
			Deque<ExecutionSlice> execslices = this._execslices;
			System.err.printf("Printing the last %d instructions:%n",
				execslices.size());
			while (!execslices.isEmpty())
				execslices.removeFirst().print();
			
			// Spacer





			System.err.println("--------------------------------------------");

			
			// Print the call trace
			CallTraceElement[] calltrace = this.trace();
			System.err.println("Call trace:");
			for (CallTraceElement l : calltrace)
				System.err.printf("    %s%n", l);
			System.err.println();
................................................................................
		// Per operation handling
		final int[] args = new int[6];
		
		// Method cache to reduce tons of method reads
		final byte[] icache = new byte[METHOD_CACHE];
		int lasticache = -(METHOD_CACHE_SPILL + 1);
		
		// First debug point?
		boolean firstpoint = false;
		
		// Debug point counter
		int pointcounter = 0;
		
		// Execution list debug
		Deque<ExecutionSlice> execslices = this._execslices;
		
		// Execution is effectively an infinite loop
		LinkedList<Frame> frames = this._frames;
		for (int frameat = frames.size(), lastframe = -1; frameat >= __fl;
			frameat = frames.size())
		{
			// Reload parameters?
			if ((reload |= (lastframe != frameat)))
................................................................................
				}
			
			// Determine the encoding
			int encoding = NativeInstruction.encoding(op);
			
			// Set first point flag
			if (encoding == NativeInstructionType.DEBUG_ENTRY)
			{
				firstpoint = true;
				pointcounter = 0;
			}


			
			// Get slice for this instruction
			ExecutionSlice el = ExecutionSlice.of(this.trace(nowframe),
				nowframe, op, args, af.length, reglist);
			
			// Add to previous instructions, do not exceed slice limits

			if (execslices.size() >= MAX_EXECUTION_SLICES)
				execslices.removeFirst();
			execslices.addLast(el);
			
			// Print CPU debug info
			if (ENABLE_DEBUG)
				el.print();
			
			// Debug point checking
			if (encoding == NativeInstructionType.DEBUG_POINT)
			{
				// First point printing?
				boolean doprint = false;
				if (firstpoint && ENABLE_DEBUG)
				{
					doprint = true;
					firstpoint = false;
				}
				
				// Seems to be stuck?

				if (pointcounter++ >= _POINT_THRESHOLD)
				{
					doprint = true;
					pointcounter = 0;
				}
				
				// Print the point?
				if (doprint)
					el.print();

			}
			
			// By default the next instruction is the address after all
			// arguments have been read
			int nextpc = lasticache + rargp;
			
			// Handle the operation
			switch (encoding)
			{
					// CPU Breakpoint
				case NativeInstructionType.BREAKPOINT:



					// If profiling, immediately enter the frame to signal
					// a break point then exit it
					if (profiler != null)
					{
						profiler.enterFrame("<breakpoint>", "<breakpoint>",
							"<breakpoint>");
						profiler.exitFrame();
					}
					
					// {@squirreljme.error AE04 CPU breakpoint hit.}
					throw new VMException("AE04");


				
					// Debug entry point of method
				case NativeInstructionType.DEBUG_ENTRY:
					this.__debugEntry(nowframe, args[0], args[1], args[2],
						args[3]);
					break;
					
................................................................................
						if (read == check)
							memory.memWriteInt(addr + off, set);
						
						// Set the read value before check
						lr[args[1]] = read;
						
						// Debug
						if (ENABLE_DEBUG)
							todo.DEBUG.note("%08x(%d) = %d ? %d = %d",
								addr, off, read, check, set);
					}
					break;
				
					// Atomic decrement and get
				case NativeInstructionType.ATOMIC_INT_DECREMENT_AND_GET:
					synchronized (memory)
					{
................................................................................
						// old value; The new value)}
						if (newval < 0)
							throw new VMException(String.format(
								"AE05 %08x+%d %d %d", addr, off, newval + 1,
								newval));
						
						// Debug
						if (ENABLE_DEBUG)
							todo.DEBUG.note("%08x(%d) -= %d - 1 = %d",
								addr, off, newval + 1, newval);
					}
					break;
					
					// Atomic increment
				case NativeInstructionType.ATOMIC_INT_INCREMENT:
					synchronized (memory)
					{
................................................................................
						
						// Read, increment, and store
						int oldv;
						memory.memWriteInt(addr + off,
							(oldv = memory.memReadInt(addr + off)) + 1);
						
						// Debug
						if (ENABLE_DEBUG)
							todo.DEBUG.note("%08x(%d) += %d + 1 = %d",
								addr, off, oldv, oldv + 1);
					}
					break;
				
					// Copy
				case NativeInstructionType.COPY:
					lr[args[1]] = lr[args[0]];
					break;
................................................................................
						}
						catch (VMException e)
						{
							fail = e;
						}
						
						// Debug
						if (ENABLE_DEBUG)
							todo.DEBUG.note(
								"(int)%08x[%d] (%08x) -> %d (%08x)",
								addr, indx, addr + ioff,
								lr[rout], lr[rout]);
						
						// Failure happened?
						if (fail != null)
							throw fail;
					}
					break;
					
................................................................................
					// Load from constant pool
				case NativeInstructionType.LOAD_POOL:
					{
						lr[args[1]] = memory.memReadInt(
							lr[NativeCode.POOL_REGISTER] + (args[0] * 4));
						
						// Debug
						if (ENABLE_DEBUG)
							todo.DEBUG.note("Read pool: %d -> %d", args[0],
								lr[args[1]]);
					}
					break;
					
					// Integer math
				case NativeInstructionType.MATH_CONST_INT:
				case NativeInstructionType.MATH_REG_INT:
					{
................................................................................
									throw new todo.OOPS(dt.name());
							}
							
							// Set value
							lr[args[0]] = v;
							
							// Debug
							if (ENABLE_DEBUG)
								todo.DEBUG.note(
									"%c %08x+%d (%08x) -> %d (%08x)",
									(isjava ? 'J' : 'N'),
									base, offs, addr, v, v);
						}
						
						// Stores
						else
						{
							// Value to store
							int v = lr[args[0]];
................................................................................
									
									// Unknown
								default:
									throw new todo.OOPS(dt.name());
							}
							
							// Debug
							if (ENABLE_DEBUG)
								todo.DEBUG.note(
									"%c %08x+%d (%08x) <- %d (%08x)",
									(isjava ? 'J' : 'N'),
									base, offs, addr, v, v);
						}
					}
					break;
					
					// Return from method call
				case NativeInstructionType.RETURN:
					{
................................................................................
						// A reload is done as the frame has changed
						reload = true;
						
						// Clear point counter
						pointcounter = 0;
						
						// Debug
						if (ENABLE_DEBUG)
							System.err.printf(
								"<<<< %08x <<<<<<<<<<<<<<<<<<<<<<%n",
								(now != null ? now._pc : 0));
					}
					break;
				
					// System call
				case NativeInstructionType.SYSTEM_CALL:
					{
						// The arguments to the system calls are in registers
................................................................................
	/**
	 * This represents a single frame in the execution stack.
	 *
	 * @since 2019/04/21
	 */
	public static final class Frame
	{



		/** Registers for this frame. */
		final int[] _registers =
			new int[MAX_REGISTERS];
		
		/** The entry PC address. */
		int _entrypc;
		
................................................................................
		int _injop;
		
		/** The current Java address. */
		int _injpc;
		
		/** The current task ID. */
		int _taskid;









	}
}








|







 







<
<
<
<







 







<
<
<
<
<
<
<
<
<







 







>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
|
|
|
|
>
>
>
>
>
|
>







 







<
<
<



<
<
<







 







<
<

|
>
>
|
|
|
|
|
|
>
|
|
|

<
|
|
<
<
|
|
<
<
<
<
<
<
<
<
|
>
|
|
|
|
|
|
|
|
|
>











>
>
>
|
|
|
|
|
|
|
|
|
|
|
>
>







 







|

|







 







|

|







 







|

|







 







|



|







 







|

|







 







|



|







 







|



|







 







|


|







 







>
>
>







 







>
>
>
>
>
>
>
>
>



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
..
93
94
95
96
97
98
99




100
101
102
103
104
105
106
...
131
132
133
134
135
136
137









138
139
140
141
142
143
144
...
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
...
267
268
269
270
271
272
273



274
275
276



277
278
279
280
281
282
283
...
410
411
412
413
414
415
416


417
418
419
420
421
422
423
424
425
426
427
428
429
430
431

432
433


434
435








436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
...
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
...
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
...
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
...
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
...
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
...
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
...
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
...
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
....
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
....
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
	
	/** Spill over protection for the cache. */
	public static final int METHOD_CACHE_SPILL =
		1024;
	
	/** The number of execution slices to store. */
	public static final int MAX_EXECUTION_SLICES =
		32;
	
	/** Threshhold for too many debug points */
	private static final int _POINT_THRESHOLD =
		65536;
	
	/** The machine state. */
	protected final MachineState state;
................................................................................
	private final int[] _syscallerrors =
		new int[SystemCallIndex.NUM_SYSCALLS];
	
	/** Super visor properties. */
	private final int[] _supervisorproperties =
		new int[SupervisorPropertyIndex.NUM_PROPERTIES];
	




	/**
	 * Initializes the native CPU.
	 *
	 * @param __ms The machine state.
	 * @param __mem The memory space.
	 * @param __ps The profiler to use.
	 * @param __vcid Virtual CPU id.
................................................................................
	 */
	public final Frame enterFrame(int __pc, int... __args)
	{
		// Old frame, to source globals from
		LinkedList<Frame> frames = this._frames;
		Frame lastframe = frames.peekLast();
		









		// Setup new frame
		Frame rv = new Frame();
		rv._pc = __pc;
		rv._entrypc = __pc;
		rv._lastpc = __pc;
		
		// Add to frame list
................................................................................
		
		// Failed
		catch (VMException|InvalidInstructionException e)
		{
			// Spacer
			System.err.println("********************************************");
			
			// Only print execution slices if debugging is enabled
			if (ENABLE_DEBUG)
			{
				// Each frame has its own slices
				for (Frame l : this._frames)
				{
					// Traces for this frame
					System.err.print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
					System.err.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
					System.err.printf(">>>>>>>>>>>> %s%n", this.trace(l));
					
					// Print all the various execution slices
					Deque<ExecutionSlice> execslices = l._execslices;
					System.err.printf("Printing the last %d instructions:%n",
						execslices.size());
					while (!execslices.isEmpty())
						execslices.removeFirst().print(System.err);
					
					// Spacer
					System.err.println();
				}
				
				// Spacer
				System.err.println(
					"--------------------------------------------");
			}
			
			// Print the call trace
			CallTraceElement[] calltrace = this.trace();
			System.err.println("Call trace:");
			for (CallTraceElement l : calltrace)
				System.err.printf("    %s%n", l);
			System.err.println();
................................................................................
		// Per operation handling
		final int[] args = new int[6];
		
		// Method cache to reduce tons of method reads
		final byte[] icache = new byte[METHOD_CACHE];
		int lasticache = -(METHOD_CACHE_SPILL + 1);
		



		// Debug point counter
		int pointcounter = 0;
		



		// Execution is effectively an infinite loop
		LinkedList<Frame> frames = this._frames;
		for (int frameat = frames.size(), lastframe = -1; frameat >= __fl;
			frameat = frames.size())
		{
			// Reload parameters?
			if ((reload |= (lastframe != frameat)))
................................................................................
				}
			
			// Determine the encoding
			int encoding = NativeInstruction.encoding(op);
			
			// Set first point flag
			if (encoding == NativeInstructionType.DEBUG_ENTRY)


				pointcounter = 0;
			
			// Only track slices if we are debugging
			if (ENABLE_DEBUG)
			{
				// Get slice for this instruction
				ExecutionSlice el = ExecutionSlice.of(this.trace(nowframe),
					nowframe, op, args, af.length, reglist);
				
				// Add to previous instructions, do not exceed slice limits
				Deque<ExecutionSlice> execslices = nowframe._execslices;
				if (execslices.size() >= MAX_EXECUTION_SLICES)
					execslices.removeFirst();
				execslices.addLast(el);
			

				// In debug points check to see if the execution seems to
				// be stuck in here (really long methods)


				if (encoding == NativeInstructionType.DEBUG_POINT)
				{








					// Seems to be stuck?
					boolean doprint = false;
					if (pointcounter++ >= _POINT_THRESHOLD)
					{
						doprint = true;
						pointcounter = 0;
					}
					
					// Print the point?
					if (doprint)
						el.print();
				}
			}
			
			// By default the next instruction is the address after all
			// arguments have been read
			int nextpc = lasticache + rargp;
			
			// Handle the operation
			switch (encoding)
			{
					// CPU Breakpoint
				case NativeInstructionType.BREAKPOINT:
					// Breakpoints only function when debugging is enabled
					if (ENABLE_DEBUG)
					{
						// If profiling, immediately enter the frame to signal
						// a break point then exit it
						if (profiler != null)
						{
							profiler.enterFrame("<breakpoint>", "<breakpoint>",
								"<breakpoint>");
							profiler.exitFrame();
						}
						
						// {@squirreljme.error AE04 CPU breakpoint hit.}
						throw new VMException("AE04");
					}
					break;
				
					// Debug entry point of method
				case NativeInstructionType.DEBUG_ENTRY:
					this.__debugEntry(nowframe, args[0], args[1], args[2],
						args[3]);
					break;
					
................................................................................
						if (read == check)
							memory.memWriteInt(addr + off, set);
						
						// Set the read value before check
						lr[args[1]] = read;
						
						// Debug
						/*if (ENABLE_DEBUG)
							todo.DEBUG.note("%08x(%d) = %d ? %d = %d",
								addr, off, read, check, set);*/
					}
					break;
				
					// Atomic decrement and get
				case NativeInstructionType.ATOMIC_INT_DECREMENT_AND_GET:
					synchronized (memory)
					{
................................................................................
						// old value; The new value)}
						if (newval < 0)
							throw new VMException(String.format(
								"AE05 %08x+%d %d %d", addr, off, newval + 1,
								newval));
						
						// Debug
						/*if (ENABLE_DEBUG)
							todo.DEBUG.note("%08x(%d) -= %d - 1 = %d",
								addr, off, newval + 1, newval);*/
					}
					break;
					
					// Atomic increment
				case NativeInstructionType.ATOMIC_INT_INCREMENT:
					synchronized (memory)
					{
................................................................................
						
						// Read, increment, and store
						int oldv;
						memory.memWriteInt(addr + off,
							(oldv = memory.memReadInt(addr + off)) + 1);
						
						// Debug
						/*if (ENABLE_DEBUG)
							todo.DEBUG.note("%08x(%d) += %d + 1 = %d",
								addr, off, oldv, oldv + 1);*/
					}
					break;
				
					// Copy
				case NativeInstructionType.COPY:
					lr[args[1]] = lr[args[0]];
					break;
................................................................................
						}
						catch (VMException e)
						{
							fail = e;
						}
						
						// Debug
						/*if (ENABLE_DEBUG)
							todo.DEBUG.note(
								"(int)%08x[%d] (%08x) -> %d (%08x)",
								addr, indx, addr + ioff,
								lr[rout], lr[rout]);*/
						
						// Failure happened?
						if (fail != null)
							throw fail;
					}
					break;
					
................................................................................
					// Load from constant pool
				case NativeInstructionType.LOAD_POOL:
					{
						lr[args[1]] = memory.memReadInt(
							lr[NativeCode.POOL_REGISTER] + (args[0] * 4));
						
						// Debug
						/*if (ENABLE_DEBUG)
							todo.DEBUG.note("Read pool: %d -> %d", args[0],
								lr[args[1]]);*/
					}
					break;
					
					// Integer math
				case NativeInstructionType.MATH_CONST_INT:
				case NativeInstructionType.MATH_REG_INT:
					{
................................................................................
									throw new todo.OOPS(dt.name());
							}
							
							// Set value
							lr[args[0]] = v;
							
							// Debug
							/*if (ENABLE_DEBUG)
								todo.DEBUG.note(
									"%c %08x+%d (%08x) -> %d (%08x)",
									(isjava ? 'J' : 'N'),
									base, offs, addr, v, v);*/
						}
						
						// Stores
						else
						{
							// Value to store
							int v = lr[args[0]];
................................................................................
									
									// Unknown
								default:
									throw new todo.OOPS(dt.name());
							}
							
							// Debug
							/*if (ENABLE_DEBUG)
								todo.DEBUG.note(
									"%c %08x+%d (%08x) <- %d (%08x)",
									(isjava ? 'J' : 'N'),
									base, offs, addr, v, v);*/
						}
					}
					break;
					
					// Return from method call
				case NativeInstructionType.RETURN:
					{
................................................................................
						// A reload is done as the frame has changed
						reload = true;
						
						// Clear point counter
						pointcounter = 0;
						
						// Debug
						/*if (ENABLE_DEBUG)
							System.err.printf(
								"<<<< %08x <<<<<<<<<<<<<<<<<<<<<<%n",
								(now != null ? now._pc : 0));*/
					}
					break;
				
					// System call
				case NativeInstructionType.SYSTEM_CALL:
					{
						// The arguments to the system calls are in registers
................................................................................
	/**
	 * This represents a single frame in the execution stack.
	 *
	 * @since 2019/04/21
	 */
	public static final class Frame
	{
		/** Execution slices. */
		final Deque<ExecutionSlice> _execslices;
		
		/** Registers for this frame. */
		final int[] _registers =
			new int[MAX_REGISTERS];
		
		/** The entry PC address. */
		int _entrypc;
		
................................................................................
		int _injop;
		
		/** The current Java address. */
		int _injpc;
		
		/** The current task ID. */
		int _taskid;
		
		/**
		 * Potential initialization.
		 */
		{
			this._execslices = (ENABLE_DEBUG ?
				new LinkedList<ExecutionSlice>() :
				(Deque<ExecutionSlice>)null);
		}
	}
}