aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/lscript/lscript_execute/lscript_execute.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra/lscript/lscript_execute/lscript_execute.cpp')
-rw-r--r--linden/indra/lscript/lscript_execute/lscript_execute.cpp985
1 files changed, 642 insertions, 343 deletions
diff --git a/linden/indra/lscript/lscript_execute/lscript_execute.cpp b/linden/indra/lscript/lscript_execute/lscript_execute.cpp
index 643f3f6..3adfe32 100644
--- a/linden/indra/lscript/lscript_execute/lscript_execute.cpp
+++ b/linden/indra/lscript/lscript_execute/lscript_execute.cpp
@@ -31,6 +31,7 @@
31 31
32#include "linden_common.h" 32#include "linden_common.h"
33 33
34#include <algorithm>
34#include <sstream> 35#include <sstream>
35 36
36#include "lscript_execute.h" 37#include "lscript_execute.h"
@@ -43,9 +44,9 @@
43void (*binary_operations[LST_EOF][LST_EOF])(U8 *buffer, LSCRIPTOpCodesEnum opcode); 44void (*binary_operations[LST_EOF][LST_EOF])(U8 *buffer, LSCRIPTOpCodesEnum opcode);
44void (*unary_operations[LST_EOF])(U8 *buffer, LSCRIPTOpCodesEnum opcode); 45void (*unary_operations[LST_EOF])(U8 *buffer, LSCRIPTOpCodesEnum opcode);
45 46
46char* LSCRIPTRunTimeFaultStrings[LSRF_EOF] = /*Flawfinder: ignore*/ 47const char* LSCRIPTRunTimeFaultStrings[LSRF_EOF] = /*Flawfinder: ignore*/
47{ 48{
48 "invalid", // LSRF_INVALID, 49 "Invalid", // LSRF_INVALID,
49 "Math Error", // LSRF_MATH, 50 "Math Error", // LSRF_MATH,
50 "Stack-Heap Collision", // LSRF_STACK_HEAP_COLLISION, 51 "Stack-Heap Collision", // LSRF_STACK_HEAP_COLLISION,
51 "Bounds Check Error", // LSRF_BOUND_CHECK_ERROR, 52 "Bounds Check Error", // LSRF_BOUND_CHECK_ERROR,
@@ -55,13 +56,11 @@ char* LSCRIPTRunTimeFaultStrings[LSRF_EOF] = /*Flawfinder: ignore*/
55 "Hit Sandbox Limit", // LSRF_SANDBOX, 56 "Hit Sandbox Limit", // LSRF_SANDBOX,
56 "Chat Overrun", // LSRF_CHAT_OVERRUN, 57 "Chat Overrun", // LSRF_CHAT_OVERRUN,
57 "Too Many Listens", // LSRF_TOO_MANY_LISTENS, 58 "Too Many Listens", // LSRF_TOO_MANY_LISTENS,
58 "Lists may not contain lists" // LSRF_NESTING_LISTS, 59 "Lists may not contain lists", // LSRF_NESTING_LISTS,
60 "CLI Exception" // LSRF_CLI
59}; 61};
60 62
61//static 63LLScriptExecuteLSL2::LLScriptExecuteLSL2(LLFILE *fp)
62S64 LLScriptExecute::sGlobalInstructionCount = 0;
63
64LLScriptExecute::LLScriptExecute(LLFILE *fp)
65{ 64{
66 U8 sizearray[4]; 65 U8 sizearray[4];
67 S32 filesize; 66 S32 filesize;
@@ -84,19 +83,26 @@ LLScriptExecute::LLScriptExecute(LLFILE *fp)
84 init(); 83 init();
85} 84}
86 85
87LLScriptExecute::LLScriptExecute(U8 *buffer) 86LLScriptExecuteLSL2::LLScriptExecuteLSL2(const U8* bytecode, U32 bytecode_size)
88{ 87{
89 mBuffer = buffer; 88 mBuffer = new U8[TOP_OF_MEMORY];
90 89 memset(mBuffer + bytecode_size, 0, TOP_OF_MEMORY - bytecode_size);
90 S32 src_offset = 0;
91 S32 dest_offset = 0;
92 bytestream2bytestream(mBuffer, dest_offset, bytecode, src_offset, bytecode_size);
93 mBytecodeSize = bytecode_size;
94 mBytecode = new U8[mBytecodeSize];
95 memcpy(mBytecode, bytecode, mBytecodeSize);
91 init(); 96 init();
92} 97}
93 98
94LLScriptExecute::~LLScriptExecute() 99LLScriptExecuteLSL2::~LLScriptExecuteLSL2()
95{ 100{
96 delete [] mBuffer; 101 delete[] mBuffer;
102 delete[] mBytecode;
97} 103}
98 104
99void LLScriptExecute::init() 105void LLScriptExecuteLSL2::init()
100{ 106{
101 S32 i, j; 107 S32 i, j;
102 108
@@ -270,7 +276,7 @@ void LLScriptExecute::init()
270 276
271 277
272// Utility routine for when there's a boundary error parsing bytecode 278// Utility routine for when there's a boundary error parsing bytecode
273void LLScriptExecute::recordBoundaryError( const LLUUID &id ) 279void LLScriptExecuteLSL2::recordBoundaryError( const LLUUID &id )
274{ 280{
275 set_fault(mBuffer, LSRF_BOUND_CHECK_ERROR); 281 set_fault(mBuffer, LSRF_BOUND_CHECK_ERROR);
276 llwarns << "Script boundary error for ID " << id << llendl; 282 llwarns << "Script boundary error for ID " << id << llendl;
@@ -278,7 +284,7 @@ void LLScriptExecute::recordBoundaryError( const LLUUID &id )
278 284
279 285
280// set IP to the event handler with some error checking 286// set IP to the event handler with some error checking
281void LLScriptExecute::setStateEventOpcoodeStartSafely( S32 state, LSCRIPTStateEventType event, const LLUUID &id ) 287void LLScriptExecuteLSL2::setStateEventOpcoodeStartSafely( S32 state, LSCRIPTStateEventType event, const LLUUID &id )
282{ 288{
283 S32 opcode_start = get_state_event_opcoode_start( mBuffer, state, event ); 289 S32 opcode_start = get_state_event_opcoode_start( mBuffer, state, event );
284 if ( opcode_start == -1 ) 290 if ( opcode_start == -1 )
@@ -296,12 +302,474 @@ void LLScriptExecute::setStateEventOpcoodeStartSafely( S32 state, LSCRIPTStateEv
296 302
297S32 lscript_push_variable(LLScriptLibData *data, U8 *buffer); 303S32 lscript_push_variable(LLScriptLibData *data, U8 *buffer);
298 304
299U32 LLScriptExecute::run(BOOL b_print, const LLUUID &id, char **errorstr, BOOL &state_transition) 305void LLScriptExecuteLSL2::resumeEventHandler(BOOL b_print, const LLUUID &id, F32 time_slice)
306{
307 // call opcode run function pointer with buffer and IP
308 mInstructionCount++;
309 S32 value = get_register(mBuffer, LREG_IP);
310 S32 tvalue = value;
311 S32 opcode = safe_instruction_bytestream2byte(mBuffer, tvalue);
312 mExecuteFuncs[opcode](mBuffer, value, b_print, id);
313 set_ip(mBuffer, value);
314 add_register_fp(mBuffer, LREG_ESR, -0.1f);
315 // lsa_print_heap(mBuffer);
316
317 if (b_print)
318 {
319 lsa_print_heap(mBuffer);
320 printf("ip: 0x%X\n", get_register(mBuffer, LREG_IP));
321 printf("sp: 0x%X\n", get_register(mBuffer, LREG_SP));
322 printf("bp: 0x%X\n", get_register(mBuffer, LREG_BP));
323 printf("hr: 0x%X\n", get_register(mBuffer, LREG_HR));
324 printf("hp: 0x%X\n", get_register(mBuffer, LREG_HP));
325 }
326
327 // NOTE: Babbage: all mExecuteFuncs return false.
328}
329
330void LLScriptExecuteLSL2::callEventHandler(LSCRIPTStateEventType event, S32 major_version, const LLUUID &id, F32 time_slice)
331{
332 // push a zero to be popped
333 lscript_push(mBuffer, 0);
334 // push sp as current bp
335 S32 sp = get_register(mBuffer, LREG_SP);
336 lscript_push(mBuffer, sp);
337
338 // Update current handler and current events registers.
339 set_event_register(mBuffer, LREG_IE, LSCRIPTStateBitField[event], major_version);
340 U64 current_events = get_event_register(mBuffer, LREG_CE, major_version);
341 current_events &= ~LSCRIPTStateBitField[event];
342 set_event_register(mBuffer, LREG_CE, current_events, major_version);
343
344 // now, push any additional stack space
345 U32 current_state = get_register(mBuffer, LREG_CS);
346 S32 additional_size = get_event_stack_size(mBuffer, current_state, event);
347 lscript_pusharge(mBuffer, additional_size);
348
349 // now set the bp correctly
350 sp = get_register(mBuffer, LREG_SP);
351 sp += additional_size;
352 set_bp(mBuffer, sp);
353
354 // set IP to the function
355 S32 opcode_start = get_state_event_opcoode_start(mBuffer, current_state, event);
356 set_ip(mBuffer, opcode_start);
357}
358
359//void callStateExitHandler()
360//{
361// // push a zero to be popped
362// lscript_push(mBuffer, 0);
363// // push sp as current bp
364// S32 sp = get_register(mBuffer, LREG_SP);
365// lscript_push(mBuffer, sp);
366//
367// // now, push any additional stack space
368// S32 additional_size = get_event_stack_size(mBuffer, current_state, LSTT_STATE_EXIT);
369// lscript_pusharge(mBuffer, additional_size);
370//
371// sp = get_register(mBuffer, LREG_SP);
372// sp += additional_size;
373// set_bp(mBuffer, sp);
374//
375// // set IP to the event handler
376// S32 opcode_start = get_state_event_opcoode_start(mBuffer, current_state, LSTT_STATE_EXIT);
377// set_ip(mBuffer, opcode_start);
378//}
379//
380//void callStateEntryHandler()
381//{
382// // push a zero to be popped
383// lscript_push(mBuffer, 0);
384// // push sp as current bp
385// S32 sp = get_register(mBuffer, LREG_SP);
386// lscript_push(mBuffer, sp);
387//
388// event = return_first_event((S32)LSCRIPTStateBitField[LSTT_STATE_ENTRY]);
389// set_event_register(mBuffer, LREG_IE, LSCRIPTStateBitField[event], major_version);
390// current_events &= ~LSCRIPTStateBitField[event];
391// set_event_register(mBuffer, LREG_CE, current_events, major_version);
392//
393// // now, push any additional stack space
394// S32 additional_size = get_event_stack_size(mBuffer, current_state, event) - size;
395// lscript_pusharge(mBuffer, additional_size);
396//
397// // now set the bp correctly
398// sp = get_register(mBuffer, LREG_SP);
399// sp += additional_size + size;
400// set_bp(mBuffer, sp);
401// // set IP to the function
402// S32 opcode_start = get_state_event_opcoode_start(mBuffer, current_state, event);
403// set_ip(mBuffer, opcode_start);
404//}
405
406void LLScriptExecuteLSL2::callQueuedEventHandler(LSCRIPTStateEventType event, S32 major_version, const LLUUID &id, F32 time_slice)
407{
408 LLScriptDataCollection* eventdata;
409
410 for (eventdata = mEventData.mEventDataList.getFirstData(); eventdata; eventdata = mEventData.mEventDataList.getNextData())
411 {
412 if (eventdata->mType == event)
413 {
414 // push a zero to be popped
415 lscript_push(mBuffer, 0);
416 // push sp as current bp
417 S32 sp = get_register(mBuffer, LREG_SP);
418 lscript_push(mBuffer, sp);
419
420 // Update current handler and current events registers.
421 set_event_register(mBuffer, LREG_IE, LSCRIPTStateBitField[event], major_version);
422 U64 current_events = get_event_register(mBuffer, LREG_CE, major_version);
423 current_events &= ~LSCRIPTStateBitField[event];
424 set_event_register(mBuffer, LREG_CE, current_events, major_version);
425
426 // push any arguments that need to be pushed onto the stack
427 // last piece of data will be type LST_NULL
428 LLScriptLibData *data = eventdata->mData;
429 U32 size = 0;
430 while (data->mType)
431 {
432 size += lscript_push_variable(data, mBuffer);
433 data++;
434 }
435 // now, push any additional stack space
436 U32 current_state = get_register(mBuffer, LREG_CS);
437 S32 additional_size = get_event_stack_size(mBuffer, current_state, event) - size;
438 lscript_pusharge(mBuffer, additional_size);
439
440 // now set the bp correctly
441 sp = get_register(mBuffer, LREG_SP);
442 sp += additional_size + size;
443 set_bp(mBuffer, sp);
444
445 // set IP to the function
446 S32 opcode_start = get_state_event_opcoode_start(mBuffer, current_state, event);
447 set_ip(mBuffer, opcode_start);
448
449 mEventData.mEventDataList.deleteCurrentData();
450 break;
451 }
452 }
453}
454
455void LLScriptExecuteLSL2::callNextQueuedEventHandler(U64 event_register, S32 major_version, const LLUUID &id, F32 time_slice)
456{
457 LLScriptDataCollection* eventdata = mEventData.getNextEvent();
458 if (eventdata)
459 {
460 LSCRIPTStateEventType event = eventdata->mType;
461
462 // make sure that we can actually handle this one
463 if (LSCRIPTStateBitField[event] & event_register)
464 {
465 // push a zero to be popped
466 lscript_push(mBuffer, 0);
467 // push sp as current bp
468 S32 sp = get_register(mBuffer, LREG_SP);
469 lscript_push(mBuffer, sp);
470
471 // Update current handler and current events registers.
472 set_event_register(mBuffer, LREG_IE, LSCRIPTStateBitField[event], major_version);
473 U64 current_events = get_event_register(mBuffer, LREG_CE, major_version);
474 current_events &= ~LSCRIPTStateBitField[event];
475 set_event_register(mBuffer, LREG_CE, current_events, major_version);
476
477 // push any arguments that need to be pushed onto the stack
478 // last piece of data will be type LST_NULL
479 LLScriptLibData *data = eventdata->mData;
480 U32 size = 0;
481 while (data->mType)
482 {
483 size += lscript_push_variable(data, mBuffer);
484 data++;
485 }
486
487 // now, push any additional stack space
488 U32 current_state = get_register(mBuffer, LREG_CS);
489 S32 additional_size = get_event_stack_size(mBuffer, current_state, event) - size;
490 lscript_pusharge(mBuffer, additional_size);
491
492 // now set the bp correctly
493 sp = get_register(mBuffer, LREG_SP);
494 sp += additional_size + size;
495 set_bp(mBuffer, sp);
496
497 // set IP to the function
498 S32 opcode_start = get_state_event_opcoode_start(mBuffer, current_state, event);
499 set_ip(mBuffer, opcode_start);
500 }
501 else
502 {
503 llwarns << "Shit, somehow got an event that we're not registered for!" << llendl;
504 }
505 delete eventdata;
506 }
507}
508
509U64 LLScriptExecuteLSL2::nextState()
510{
511 // copy NS to CS
512 S32 next_state = get_register(mBuffer, LREG_NS);
513 set_register(mBuffer, LREG_CS, next_state);
514
515 // copy new state's handled events into ER (SR + CS*4 + 4)
516 return get_handled_events(mBuffer, next_state);
517}
518
519//virtual
520void LLScriptExecuteLSL2::addEvent(LLScriptDataCollection* event)
521{
522 mEventData.addEventData(event);
523}
524
525//virtual
526void LLScriptExecuteLSL2::removeEventType(LSCRIPTStateEventType event_type)
527{
528 mEventData.removeEventType(event_type);
529}
530
531//virtual
532F32 LLScriptExecuteLSL2::getSleep() const
533{
534 return get_register_fp(mBuffer, LREG_SLR);
535}
536
537//virtual
538void LLScriptExecuteLSL2::setSleep(F32 value)
539{
540 set_register_fp(mBuffer, LREG_SLR, value);
541}
542
543//virtual
544U64 LLScriptExecuteLSL2::getCurrentHandler(S32 version)
545{
546 return get_event_register(mBuffer, LREG_IE, version);
547}
548
549//virtual
550F32 LLScriptExecuteLSL2::getEnergy() const
551{
552 return get_register_fp(mBuffer, LREG_ESR);
553}
554
555//virtual
556void LLScriptExecuteLSL2::setEnergy(F32 value)
557{
558 set_register_fp(mBuffer, LREG_ESR, value);
559}
560
561//virtual
562U32 LLScriptExecuteLSL2::getFreeMemory()
563{
564 return get_register(mBuffer, LREG_SP) - get_register(mBuffer, LREG_HP);
565}
566
567//virtual
568S32 LLScriptExecuteLSL2::getParameter()
569{
570 return get_register(mBuffer, LREG_PR);
571}
572
573//virtual
574void LLScriptExecuteLSL2::setParameter(S32 value)
575{
576 set_register(mBuffer, LREG_PR, value);
577}
578
579
580S32 LLScriptExecuteLSL2::writeState(U8 **dest, U32 header_size, U32 footer_size)
581{
582 // data format:
583 // 4 bytes of size of Registers, Name and Description, and Global Variables
584 // Registers, Name and Description, and Global Variables data
585 // 4 bytes of size of Heap
586 // Heap data
587 // 4 bytes of stack size
588 // Stack data
589
590 S32 registers_size = get_register(mBuffer, LREG_GFR);
591
592 if (get_register(mBuffer, LREG_HP) > TOP_OF_MEMORY)
593 reset_hp_to_safe_spot(mBuffer);
594
595 S32 heap_size = get_register(mBuffer, LREG_HP) - get_register(mBuffer, LREG_HR);
596 S32 stack_size = get_register(mBuffer, LREG_TM) - get_register(mBuffer, LREG_SP);
597 S32 total_size = registers_size + LSCRIPTDataSize[LST_INTEGER] +
598 heap_size + LSCRIPTDataSize[LST_INTEGER] +
599 stack_size + LSCRIPTDataSize[LST_INTEGER];
600
601 // actually allocate data
602 delete[] *dest;
603 *dest = new U8[header_size + total_size + footer_size];
604 memset(*dest, 0, header_size + total_size + footer_size);
605 S32 dest_offset = header_size;
606 S32 src_offset = 0;
607
608 // registers
609 integer2bytestream(*dest, dest_offset, registers_size);
610
611 // llinfos << "Writing CE: " << getCurrentEvents() << llendl;
612 bytestream2bytestream(*dest, dest_offset, mBuffer, src_offset, registers_size);
613
614 // heap
615 integer2bytestream(*dest, dest_offset, heap_size);
616
617 src_offset = get_register(mBuffer, LREG_HR);
618 bytestream2bytestream(*dest, dest_offset, mBuffer, src_offset, heap_size);
619
620 // stack
621 integer2bytestream(*dest, dest_offset, stack_size);
622
623 src_offset = get_register(mBuffer, LREG_SP);
624 bytestream2bytestream(*dest, dest_offset, mBuffer, src_offset, stack_size);
625
626 return total_size;
627}
628
629S32 LLScriptExecuteLSL2::writeBytecode(U8 **dest)
630{
631 // data format:
632 // registers through top of heap
633 // Heap data
634 S32 total_size = get_register(mBuffer, LREG_HP);
635
636 // actually allocate data
637 delete [] *dest;
638 *dest = new U8[total_size];
639 S32 dest_offset = 0;
640 S32 src_offset = 0;
641
642 bytestream2bytestream(*dest, dest_offset, mBuffer, src_offset, total_size);
643
644 return total_size;
645}
646
647S32 LLScriptExecuteLSL2::readState(U8 *src)
648{
649 // first, blitz heap and stack
650 S32 hr = get_register(mBuffer, LREG_HR);
651 S32 tm = get_register(mBuffer, LREG_TM);
652 memset(mBuffer + hr, 0, tm - hr);
653
654 S32 src_offset = 0;
655 S32 dest_offset = 0;
656 S32 size;
657
658 // read register size
659 size = bytestream2integer(src, src_offset);
660
661 // copy data into register area
662 bytestream2bytestream(mBuffer, dest_offset, src, src_offset, size);
663// llinfos << "Read CE: " << getCurrentEvents() << llendl;
664 if (get_register(mBuffer, LREG_TM) != TOP_OF_MEMORY)
665 {
666 llwarns << "Invalid state. Top of memory register does not match"
667 << " constant." << llendl;
668 reset_hp_to_safe_spot(mBuffer);
669 return -1;
670 }
671
672 // read heap size
673 size = bytestream2integer(src, src_offset);
674
675 // set dest offset
676 dest_offset = get_register(mBuffer, LREG_HR);
677
678 if (dest_offset + size > TOP_OF_MEMORY)
679 {
680 reset_hp_to_safe_spot(mBuffer);
681 return -1;
682 }
683
684 // copy data into heap area
685 bytestream2bytestream(mBuffer, dest_offset, src, src_offset, size);
686
687 // read stack size
688 size = bytestream2integer(src, src_offset);
689
690 // set dest offset
691 dest_offset = get_register(mBuffer, LREG_SP);
692
693 if (dest_offset + size > TOP_OF_MEMORY)
694 {
695 reset_hp_to_safe_spot(mBuffer);
696 return -1;
697 }
698
699 // copy data into heap area
700 bytestream2bytestream(mBuffer, dest_offset, src, src_offset, size);
701
702 // Return offset to first byte after read data.
703 return src_offset;
704}
705
706void LLScriptExecuteLSL2::reset()
707{
708 LLScriptExecute::reset();
709
710 const U8 *src = getBytecode();
711 S32 size = getBytecodeSize();
712
713 if (!src)
714 return;
715
716 // first, blitz heap and stack
717 S32 hr = get_register(mBuffer, LREG_HR);
718 S32 tm = get_register(mBuffer, LREG_TM);
719 memset(mBuffer + hr, 0, tm - hr);
720
721 S32 dest_offset = 0;
722 S32 src_offset = 0;
723
724 bytestream2bytestream(mBuffer, dest_offset, src, src_offset, size);
725}
726
727LLScriptExecute::LLScriptExecute() :
728 mReset(FALSE)
729{
730}
731
732void LLScriptExecute::reset()
733{
734 mReset = FALSE;
735}
736
737bool LLScriptExecute::isYieldDue() const
738{
739 if(mReset)
740 {
741 return true;
742 }
743
744 if(getSleep() > 0.f)
745 {
746 return true;
747 }
748
749 if(isFinished())
750 {
751 return true;
752 }
753
754 if(isStateChangePending())
755 {
756 return true;
757 }
758
759 return false;
760}
761
762// Run smallest number of instructions possible:
763// a single instruction for LSL2, a segment between save tests for Mono
764void LLScriptExecute::runInstructions(BOOL b_print, const LLUUID &id,
765 const char **errorstr,
766 BOOL &state_transition,
767 U32& events_processed,
768 F32 quanta)
300{ 769{
301 // is there a fault? 770 // is there a fault?
302 // if yes, print out message and exit 771 // if yes, print out message and exit
303 state_transition = FALSE; 772 S32 value = getVersion();
304 S32 value = get_register(mBuffer, LREG_VN);
305 S32 major_version = 0; 773 S32 major_version = 0;
306 if (value == LSL2_VERSION1_END_NUMBER) 774 if (value == LSL2_VERSION1_END_NUMBER)
307 { 775 {
@@ -313,323 +781,151 @@ U32 LLScriptExecute::run(BOOL b_print, const LLUUID &id, char **errorstr, BOOL &
313 } 781 }
314 else 782 else
315 { 783 {
316 set_fault(mBuffer, LSRF_VERSION_MISMATCH); 784 setFault(LSRF_VERSION_MISMATCH);
317 } 785 }
318 value = get_register(mBuffer, LREG_FR); 786 value = getFaults();
319 if (value) 787 if (value > LSRF_INVALID && value < LSRF_EOF)
320 { 788 {
321 if (b_print) 789 if (b_print)
322 { 790 {
323 printf("Error!\n"); 791 printf("Error!\n");
324 } 792 }
325 *errorstr = LSCRIPTRunTimeFaultStrings[value]; 793 *errorstr = LSCRIPTRunTimeFaultStrings[value];
326 return NO_DELETE_FLAG; 794 return;
327 } 795 }
328 else 796 else
329 { 797 {
330 *errorstr = NULL; 798 *errorstr = NULL;
331 } 799 }
332 800
333 // Get IP 801 if (! isFinished())
334 // is IP nonzero?
335 value = get_register(mBuffer, LREG_IP);
336
337 if (value)
338 { 802 {
339 // if yes, we're in opcodes, execute the next opcode by: 803 resumeEventHandler(b_print, id, quanta);
340 // call opcode run function pointer with buffer and IP 804 return;
341 mInstructionCount++;
342 sGlobalInstructionCount++;
343 S32 tvalue = value;
344 S32 opcode = safe_instruction_bytestream2byte(mBuffer, tvalue);
345 S32 b_ret_val = mExecuteFuncs[opcode](mBuffer, value, b_print, id);
346 set_ip(mBuffer, value);
347 add_register_fp(mBuffer, LREG_ESR, -0.1f);
348 // lsa_print_heap(mBuffer);
349
350 if (b_print)
351 {
352 lsa_print_heap(mBuffer);
353 printf("ip: 0x%X\n", get_register(mBuffer, LREG_IP));
354 printf("sp: 0x%X\n", get_register(mBuffer, LREG_SP));
355 printf("bp: 0x%X\n", get_register(mBuffer, LREG_BP));
356 printf("hr: 0x%X\n", get_register(mBuffer, LREG_HR));
357 printf("hp: 0x%X\n", get_register(mBuffer, LREG_HP));
358 }
359 // update IP
360 if (b_ret_val)
361 {
362 return DELETE_FLAG | CREDIT_MONEY_FLAG;
363 }
364 else
365 {
366 return NO_DELETE_FLAG;
367 }
368 } 805 }
369 else 806 else
370 { 807 {
371 // make sure that IE is zero 808 // make sure that IE is zero
372 set_event_register(mBuffer, LREG_IE, 0, major_version); 809 setCurrentHandler(0, major_version);
373 810
374 // if no, we're in a state and waiting for an event 811 // if no, we're in a state and waiting for an event
375 S32 next_state = get_register(mBuffer, LREG_NS); 812 U64 current_events = getCurrentEvents(major_version);
376 S32 current_state = get_register(mBuffer, LREG_CS); 813 U64 event_register = getEventHandlers(major_version);
377 U64 current_events = get_event_register(mBuffer, LREG_CE, major_version); 814
378 U64 event_register = get_event_register(mBuffer, LREG_ER, major_version); 815 // check NS to see if need to switch states (NS != CS)
379 // check NS to see if need to switch states (NS != CS) 816 if (isStateChangePending())
380 if (next_state != current_state)
381 { 817 {
382 state_transition = TRUE; 818 state_transition = TRUE;
819
383 // ok, blow away any pending events 820 // ok, blow away any pending events
384 mEventData.mEventDataList.deleteAllData(); 821 deleteAllEvents();
385 822
386 // if yes, check state exit flag is set 823 // if yes, check state exit flag is set
387 if (current_events & LSCRIPTStateBitField[LSTT_STATE_EXIT]) 824 if (current_events & LSCRIPTStateBitField[LSTT_STATE_EXIT])
388 { 825 {
389 // if yes, clear state exit flag 826 // if yes, clear state exit flag
390 set_event_register(mBuffer, LREG_IE, LSCRIPTStateBitField[LSTT_STATE_EXIT], major_version); 827 setCurrentHandler(LSCRIPTStateBitField[LSTT_STATE_EXIT], major_version);
391 current_events &= ~LSCRIPTStateBitField[LSTT_STATE_EXIT]; 828 current_events &= ~LSCRIPTStateBitField[LSTT_STATE_EXIT];
392 set_event_register(mBuffer, LREG_CE, current_events, major_version); 829 setCurrentEvents(current_events, major_version);
393 // check state exit event handler 830
394 // if there is a handler, call it 831 // check state exit event handler
832 // if there is a handler, call it
395 if (event_register & LSCRIPTStateBitField[LSTT_STATE_EXIT]) 833 if (event_register & LSCRIPTStateBitField[LSTT_STATE_EXIT])
396 { 834 {
397 // push a zero to be popped 835 ++events_processed;
398 lscript_push(mBuffer, 0); 836 callEventHandler(LSTT_STATE_EXIT, major_version, id, quanta);
399 // push sp as current bp 837 return;
400 S32 sp = get_register(mBuffer, LREG_SP);
401 lscript_push(mBuffer, sp);
402
403 // now, push any additional stack space
404 S32 additional_size = get_event_stack_size(mBuffer, current_state, LSTT_STATE_EXIT);
405 if ( additional_size == -1 )
406 {
407 recordBoundaryError( id );
408 }
409 else
410 {
411 lscript_pusharge(mBuffer, additional_size);
412
413 sp = get_register(mBuffer, LREG_SP);
414 sp += additional_size;
415 set_bp(mBuffer, sp);
416 // set IP to the event handler
417 setStateEventOpcoodeStartSafely( current_state, LSTT_STATE_EXIT, id );
418 }
419 return NO_DELETE_FLAG;
420 } 838 }
421 } 839 }
422 // if no handler or no state exit flag switch to new state 840
423 // set state entry flag and clear other CE flags 841 // if no handler or no state exit flag switch to new state
842 // set state entry flag and clear other CE flags
424 current_events = LSCRIPTStateBitField[LSTT_STATE_ENTRY]; 843 current_events = LSCRIPTStateBitField[LSTT_STATE_ENTRY];
425 set_event_register(mBuffer, LREG_CE, current_events, major_version); 844 setCurrentEvents(current_events, major_version);
426 // copy NS to CS 845
427 set_register(mBuffer, LREG_CS, next_state); 846 U64 handled_events = nextState();
428 // copy new state's handled events into ER (SR + CS*4 + 4) 847 setEventHandlers(handled_events, major_version);
429 U64 handled_events = get_handled_events(mBuffer, next_state);
430 set_event_register(mBuffer, LREG_ER, handled_events, major_version);
431 } 848 }
432// check to see if any current events are covered by events handled by this state (CE & ER != 0) 849
433// now, we want to look like we were called like a function 850 // try to get next event from stack
434// 0x0000: 00 00 00 00 (return ip)
435// 0x0004: bp (current sp)
436// 0x0008: parameters
437// push sp
438// add parameter size
439// pop bp
440// set ip
441
442 S32 size = 0;
443// try to get next event from stack
444 BOOL b_done = FALSE; 851 BOOL b_done = FALSE;
445 LSCRIPTStateEventType event = LSTT_NULL; 852 LSCRIPTStateEventType event = LSTT_NULL;
446 LLScriptDataCollection *eventdata;
447 853
448 next_state = get_register(mBuffer, LREG_NS); 854 current_events = getCurrentEvents(major_version);
449 current_state = get_register(mBuffer, LREG_CS); 855 event_register = getEventHandlers(major_version);
450 current_events = get_event_register(mBuffer, LREG_CE, major_version);
451 event_register = get_event_register(mBuffer, LREG_ER, major_version);
452 856
453 // first, check to see if state_entry or onrez are raised and handled 857 // first, check to see if state_entry or onrez are raised and handled
454 if ( (current_events & LSCRIPTStateBitField[LSTT_STATE_ENTRY]) 858 if ((current_events & LSCRIPTStateBitField[LSTT_STATE_ENTRY])
455 &&(current_events & event_register)) 859 &&(current_events & event_register))
456 { 860 {
457 // ok, this is easy since there isn't any data waiting, just set it 861 ++events_processed;
458 // push a zero to be popped 862 callEventHandler(LSTT_STATE_ENTRY, major_version, id, quanta);
459 lscript_push(mBuffer, 0);
460// push sp as current bp
461 S32 sp = get_register(mBuffer, LREG_SP);
462 lscript_push(mBuffer, sp);
463
464 event = return_first_event((S32)LSCRIPTStateBitField[LSTT_STATE_ENTRY]);
465 set_event_register(mBuffer, LREG_IE, LSCRIPTStateBitField[event], major_version);
466 current_events &= ~LSCRIPTStateBitField[event];
467 set_event_register(mBuffer, LREG_CE, current_events, major_version);
468// now, push any additional stack space
469 S32 additional_size = get_event_stack_size(mBuffer, current_state, event);
470 if ( additional_size == -1 )
471 { // b_done will be set, so we'll exit the loop at the bottom
472 recordBoundaryError( id );
473 }
474 else
475 {
476 additional_size -= size;
477 lscript_pusharge(mBuffer, additional_size);
478
479// now set the bp correctly
480 sp = get_register(mBuffer, LREG_SP);
481 sp += additional_size + size;
482 set_bp(mBuffer, sp);
483// set IP to the function
484 setStateEventOpcoodeStartSafely( current_state, event, id );
485 }
486 b_done = TRUE; 863 b_done = TRUE;
487 } 864 }
488 else if ( (current_events & LSCRIPTStateBitField[LSTT_REZ]) 865 else if ((current_events & LSCRIPTStateBitField[LSTT_REZ])
489 &&(current_events & event_register)) 866 &&(current_events & event_register))
490 { 867 {
491 for (eventdata = mEventData.mEventDataList.getFirstData(); eventdata; eventdata = mEventData.mEventDataList.getNextData()) 868 ++events_processed;
492 { 869 callQueuedEventHandler(LSTT_REZ, major_version, id, quanta);
493 if (eventdata->mType & LSCRIPTStateBitField[LSTT_REZ]) 870 b_done = TRUE;
494 {
495 // push a zero to be popped
496 lscript_push(mBuffer, 0);
497 // push sp as current bp
498 S32 sp = get_register(mBuffer, LREG_SP);
499 lscript_push(mBuffer, sp);
500
501 set_event_register(mBuffer, LREG_IE, LSCRIPTStateBitField[event], major_version);
502 current_events &= ~LSCRIPTStateBitField[event];
503 set_event_register(mBuffer, LREG_CE, current_events, major_version);
504
505 // push any arguments that need to be pushed onto the stack
506 // last piece of data will be type LST_NULL
507 LLScriptLibData *data = eventdata->mData;
508 while (data->mType)
509 {
510 size += lscript_push_variable(data, mBuffer);
511 data++;
512 }
513 // now, push any additional stack space
514 S32 additional_size = get_event_stack_size(mBuffer, current_state, event);
515 if ( additional_size == -1 )
516 { // b_done will be set, so we'll exit the loop at the bottom
517 recordBoundaryError( id );
518 }
519 else
520 {
521 additional_size -= size;
522 lscript_pusharge(mBuffer, additional_size);
523
524 // now set the bp correctly
525 sp = get_register(mBuffer, LREG_SP);
526 sp += additional_size + size;
527 set_bp(mBuffer, sp);
528 // set IP to the function
529 setStateEventOpcoodeStartSafely( current_state, event, id );
530 mEventData.mEventDataList.deleteCurrentData();
531 }
532 b_done = TRUE;
533 break;
534 }
535 }
536 } 871 }
537 872
538 while (!b_done) 873 while (!b_done)
539 { 874 {
540 eventdata = mEventData.getNextEvent(); 875 // Call handler for next queued event.
541 if (eventdata) 876 if(getEventCount() > 0)
542 { 877 {
543 event = eventdata->mType; 878 ++events_processed;
544 879 callNextQueuedEventHandler(event_register, major_version, id, quanta);
545 // make sure that we can actually handle this one 880 b_done = TRUE;
546 if (LSCRIPTStateBitField[event] & event_register)
547 {
548 // push a zero to be popped
549 lscript_push(mBuffer, 0);
550 // push sp as current bp
551 S32 sp = get_register(mBuffer, LREG_SP);
552 lscript_push(mBuffer, sp);
553
554 set_event_register(mBuffer, LREG_IE, LSCRIPTStateBitField[event], major_version);
555 current_events &= ~LSCRIPTStateBitField[event];
556 set_event_register(mBuffer, LREG_CE, current_events, major_version);
557
558 // push any arguments that need to be pushed onto the stack
559 // last piece of data will be type LST_NULL
560 LLScriptLibData *data = eventdata->mData;
561 while (data->mType)
562 {
563 size += lscript_push_variable(data, mBuffer);
564 data++;
565 }
566 b_done = TRUE;
567 // now, push any additional stack space
568 S32 additional_size = get_event_stack_size(mBuffer, current_state, event);
569 if ( additional_size == -1 )
570 { // b_done was just set, so we'll exit the loop at the bottom
571 recordBoundaryError( id );
572 }
573 else
574 {
575 additional_size -= size;
576 lscript_pusharge(mBuffer, additional_size);
577
578 // now set the bp correctly
579 sp = get_register(mBuffer, LREG_SP);
580 sp += additional_size + size;
581 set_bp(mBuffer, sp);
582 // set IP to the function
583 setStateEventOpcoodeStartSafely( current_state, event, id );
584 }
585 }
586 else
587 {
588 llwarns << "Shit, somehow got an event that we're not registered for!" << llendl;
589 }
590 delete eventdata;
591 } 881 }
592 else 882 else
593 { 883 {
594// if no data waiting, do it the old way: 884 // if no data waiting, do it the old way:
595 U64 handled_current = current_events & event_register; 885 U64 handled_current = current_events & event_register;
596 if (handled_current) 886 if (handled_current)
597 { 887 {
598 // push a zero to be popped
599 lscript_push(mBuffer, 0);
600 // push sp as current bp
601 S32 sp = get_register(mBuffer, LREG_SP);
602 lscript_push(mBuffer, sp);
603
604 event = return_first_event((S32)handled_current); 888 event = return_first_event((S32)handled_current);
605 set_event_register(mBuffer, LREG_IE, LSCRIPTStateBitField[event], major_version); 889 ++events_processed;
606 current_events &= ~LSCRIPTStateBitField[event]; 890 callEventHandler(event, major_version, id, quanta);
607 set_event_register(mBuffer, LREG_CE, current_events, major_version);
608 // now, push any additional stack space
609 S32 additional_size = get_event_stack_size(mBuffer, current_state, event);
610 if ( additional_size == -1 )
611 { // b_done will be set, so we'll exit the loop at the bottom
612 recordBoundaryError( id );
613 }
614 else
615 {
616 additional_size -= size;
617 lscript_pusharge(mBuffer, additional_size);
618
619 // now set the bp correctly
620 sp = get_register(mBuffer, LREG_SP);
621 sp += additional_size + size;
622 set_bp(mBuffer, sp);
623 // set IP to the function
624 setStateEventOpcoodeStartSafely( current_state, event, id );
625 }
626 } 891 }
627 b_done = TRUE; 892 b_done = TRUE;
628 } 893 }
629 } // while (!b_done) 894 }
630 } // end of else ... in state processing code 895 }
896}
631 897
632 return NO_DELETE_FLAG; 898// Run for a single timeslice, or until a yield is due
899F32 LLScriptExecute::runQuanta(BOOL b_print, const LLUUID &id, const char **errorstr, BOOL &state_transition, F32 quanta, U32& events_processed, LLTimer& timer)
900{
901 U32 timer_checks = 0;
902 F32 inloop = 0;
903
904 // Loop while not finished, yield not due and time remaining
905 // NOTE: Default implementation does not do adaptive timer skipping
906 // to preserve current LSL behaviour and not break scripts that rely
907 // on current execution speed.
908 while(true)
909 {
910 runInstructions(b_print, id, errorstr, state_transition,
911 events_processed, quanta);
912
913 static const S32 lsl_timer_check_skip = 4;
914 if(isYieldDue())
915 {
916 break;
917 }
918 else if(timer_checks++ == lsl_timer_check_skip)
919 {
920 inloop = timer.getElapsedTimeF32();
921 if(inloop > quanta)
922 {
923 break;
924 }
925 timer_checks = 0;
926 }
927 }
928 return inloop;
633} 929}
634 930
635BOOL run_noop(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id) 931BOOL run_noop(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
@@ -2309,14 +2605,24 @@ void list_list_operation(U8 *buffer, LSCRIPTOpCodesEnum opcode)
2309 } 2605 }
2310} 2606}
2311 2607
2608static U8 safe_op_index(U8 index)
2609{
2610 if(index >= LST_EOF)
2611 {
2612 // Operations on LST_NULL will always be unknown_operation.
2613 index = LST_NULL;
2614 }
2615 return index;
2616}
2617
2312BOOL run_add(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id) 2618BOOL run_add(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
2313{ 2619{
2314 if (b_print) 2620 if (b_print)
2315 printf("[0x%X]\tADD ", offset); 2621 printf("[0x%X]\tADD ", offset);
2316 offset++; 2622 offset++;
2317 U8 arg = safe_instruction_bytestream2byte(buffer, offset); 2623 U8 arg = safe_instruction_bytestream2byte(buffer, offset);
2318 U8 arg1 = arg >> 4; 2624 U8 arg1 = safe_op_index(arg >> 4);
2319 U8 arg2 = arg & 0xf; 2625 U8 arg2 = safe_op_index(arg & 0xf);
2320 if (b_print) 2626 if (b_print)
2321 { 2627 {
2322 print_type(arg1); 2628 print_type(arg1);
@@ -2334,8 +2640,8 @@ BOOL run_sub(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
2334 printf("[0x%X]\tSUB ", offset); 2640 printf("[0x%X]\tSUB ", offset);
2335 offset++; 2641 offset++;
2336 U8 arg = safe_instruction_bytestream2byte(buffer, offset); 2642 U8 arg = safe_instruction_bytestream2byte(buffer, offset);
2337 U8 arg1 = arg >> 4; 2643 U8 arg1 = safe_op_index(arg >> 4);
2338 U8 arg2 = arg & 0xf; 2644 U8 arg2 = safe_op_index(arg & 0xf);
2339 if (b_print) 2645 if (b_print)
2340 { 2646 {
2341 print_type(arg1); 2647 print_type(arg1);
@@ -2352,8 +2658,8 @@ BOOL run_mul(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
2352 printf("[0x%X]\tMUL ", offset); 2658 printf("[0x%X]\tMUL ", offset);
2353 offset++; 2659 offset++;
2354 U8 arg = safe_instruction_bytestream2byte(buffer, offset); 2660 U8 arg = safe_instruction_bytestream2byte(buffer, offset);
2355 U8 arg1 = arg >> 4; 2661 U8 arg1 = safe_op_index(arg >> 4);
2356 U8 arg2 = arg & 0xf; 2662 U8 arg2 = safe_op_index(arg & 0xf);
2357 if (b_print) 2663 if (b_print)
2358 { 2664 {
2359 print_type(arg1); 2665 print_type(arg1);
@@ -2370,8 +2676,8 @@ BOOL run_div(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
2370 printf("[0x%X]\tDIV ", offset); 2676 printf("[0x%X]\tDIV ", offset);
2371 offset++; 2677 offset++;
2372 U8 arg = safe_instruction_bytestream2byte(buffer, offset); 2678 U8 arg = safe_instruction_bytestream2byte(buffer, offset);
2373 U8 arg1 = arg >> 4; 2679 U8 arg1 = safe_op_index(arg >> 4);
2374 U8 arg2 = arg & 0xf; 2680 U8 arg2 = safe_op_index(arg & 0xf);
2375 if (b_print) 2681 if (b_print)
2376 { 2682 {
2377 print_type(arg1); 2683 print_type(arg1);
@@ -2388,8 +2694,8 @@ BOOL run_mod(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
2388 printf("[0x%X]\tMOD ", offset); 2694 printf("[0x%X]\tMOD ", offset);
2389 offset++; 2695 offset++;
2390 U8 arg = safe_instruction_bytestream2byte(buffer, offset); 2696 U8 arg = safe_instruction_bytestream2byte(buffer, offset);
2391 U8 arg1 = arg >> 4; 2697 U8 arg1 = safe_op_index(arg >> 4);
2392 U8 arg2 = arg & 0xf; 2698 U8 arg2 = safe_op_index(arg & 0xf);
2393 if (b_print) 2699 if (b_print)
2394 { 2700 {
2395 print_type(arg1); 2701 print_type(arg1);
@@ -2407,8 +2713,8 @@ BOOL run_eq(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
2407 printf("[0x%X]\tEQ ", offset); 2713 printf("[0x%X]\tEQ ", offset);
2408 offset++; 2714 offset++;
2409 U8 arg = safe_instruction_bytestream2byte(buffer, offset); 2715 U8 arg = safe_instruction_bytestream2byte(buffer, offset);
2410 U8 arg1 = arg >> 4; 2716 U8 arg1 = safe_op_index(arg >> 4);
2411 U8 arg2 = arg & 0xf; 2717 U8 arg2 = safe_op_index(arg & 0xf);
2412 if (b_print) 2718 if (b_print)
2413 { 2719 {
2414 print_type(arg1); 2720 print_type(arg1);
@@ -2425,8 +2731,8 @@ BOOL run_neq(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
2425 printf("[0x%X]\tNEQ ", offset); 2731 printf("[0x%X]\tNEQ ", offset);
2426 offset++; 2732 offset++;
2427 U8 arg = safe_instruction_bytestream2byte(buffer, offset); 2733 U8 arg = safe_instruction_bytestream2byte(buffer, offset);
2428 U8 arg1 = arg >> 4; 2734 U8 arg1 = safe_op_index(arg >> 4);
2429 U8 arg2 = arg & 0xf; 2735 U8 arg2 = safe_op_index(arg & 0xf);
2430 if (b_print) 2736 if (b_print)
2431 { 2737 {
2432 print_type(arg1); 2738 print_type(arg1);
@@ -2443,8 +2749,8 @@ BOOL run_leq(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
2443 printf("[0x%X]\tLEQ ", offset); 2749 printf("[0x%X]\tLEQ ", offset);
2444 offset++; 2750 offset++;
2445 U8 arg = safe_instruction_bytestream2byte(buffer, offset); 2751 U8 arg = safe_instruction_bytestream2byte(buffer, offset);
2446 U8 arg1 = arg >> 4; 2752 U8 arg1 = safe_op_index(arg >> 4);
2447 U8 arg2 = arg & 0xf; 2753 U8 arg2 = safe_op_index(arg & 0xf);
2448 if (b_print) 2754 if (b_print)
2449 { 2755 {
2450 print_type(arg1); 2756 print_type(arg1);
@@ -2461,8 +2767,8 @@ BOOL run_geq(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
2461 printf("[0x%X]\tGEQ ", offset); 2767 printf("[0x%X]\tGEQ ", offset);
2462 offset++; 2768 offset++;
2463 U8 arg = safe_instruction_bytestream2byte(buffer, offset); 2769 U8 arg = safe_instruction_bytestream2byte(buffer, offset);
2464 U8 arg1 = arg >> 4; 2770 U8 arg1 = safe_op_index(arg >> 4);
2465 U8 arg2 = arg & 0xf; 2771 U8 arg2 = safe_op_index(arg & 0xf);
2466 if (b_print) 2772 if (b_print)
2467 { 2773 {
2468 print_type(arg1); 2774 print_type(arg1);
@@ -2479,8 +2785,8 @@ BOOL run_less(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
2479 printf("[0x%X]\tLESS ", offset); 2785 printf("[0x%X]\tLESS ", offset);
2480 offset++; 2786 offset++;
2481 U8 arg = safe_instruction_bytestream2byte(buffer, offset); 2787 U8 arg = safe_instruction_bytestream2byte(buffer, offset);
2482 U8 arg1 = arg >> 4; 2788 U8 arg1 = safe_op_index(arg >> 4);
2483 U8 arg2 = arg & 0xf; 2789 U8 arg2 = safe_op_index(arg & 0xf);
2484 if (b_print) 2790 if (b_print)
2485 { 2791 {
2486 print_type(arg1); 2792 print_type(arg1);
@@ -2497,8 +2803,8 @@ BOOL run_greater(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
2497 printf("[0x%X]\tGREATER ", offset); 2803 printf("[0x%X]\tGREATER ", offset);
2498 offset++; 2804 offset++;
2499 U8 arg = safe_instruction_bytestream2byte(buffer, offset); 2805 U8 arg = safe_instruction_bytestream2byte(buffer, offset);
2500 U8 arg1 = arg >> 4; 2806 U8 arg1 = safe_op_index(arg >> 4);
2501 U8 arg2 = arg & 0xf; 2807 U8 arg2 = safe_op_index(arg & 0xf);
2502 if (b_print) 2808 if (b_print)
2503 { 2809 {
2504 print_type(arg1); 2810 print_type(arg1);
@@ -2640,13 +2946,12 @@ void quaternion_operation(U8 *buffer, LSCRIPTOpCodesEnum opcode)
2640 } 2946 }
2641} 2947}
2642 2948
2643
2644BOOL run_neg(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id) 2949BOOL run_neg(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
2645{ 2950{
2646 if (b_print) 2951 if (b_print)
2647 printf("[0x%X]\tNEG ", offset); 2952 printf("[0x%X]\tNEG ", offset);
2648 offset++; 2953 offset++;
2649 U8 arg = safe_instruction_bytestream2byte(buffer, offset); 2954 U8 arg = safe_op_index(safe_instruction_bytestream2byte(buffer, offset));
2650 if (b_print) 2955 if (b_print)
2651 { 2956 {
2652 print_type(arg); 2957 print_type(arg);
@@ -3675,56 +3980,50 @@ BOOL run_print(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
3675} 3980}
3676 3981
3677 3982
3678void lscript_run(char *filename, BOOL b_debug) 3983void lscript_run(const std::string& filename, BOOL b_debug)
3679{ 3984{
3680 LLTimer timer; 3985 LLTimer timer;
3681 if (filename == NULL) 3986
3987 const char *error;
3988 BOOL b_state;
3989 LLScriptExecuteLSL2 *execute = NULL;
3990
3991 if (filename.empty())
3682 { 3992 {
3683 llerrs << "filename is NULL" << llendl; 3993 llerrs << "filename is NULL" << llendl;
3684 // Just reporting error is likely not enough. Need 3994 // Just reporting error is likely not enough. Need
3685 // to check how to abort or error out gracefully 3995 // to check how to abort or error out gracefully
3686 // from this function. XXXTBD 3996 // from this function. XXXTBD
3687 } 3997 }
3688 else 3998 LLFILE* file = LLFile::fopen(filename, "r"); /* Flawfinder: ignore */
3999 if(file)
3689 { 4000 {
3690 char *error; 4001 execute = new LLScriptExecuteLSL2(file);
3691 BOOL b_state; 4002 fclose(file);
3692 LLScriptExecute *execute = NULL; 4003 }
3693 4004 if (execute)
3694 LLFILE* file = LLFile::fopen(filename, "r"); 4005 {
3695 if (file) 4006 timer.reset();
3696 { 4007 F32 time_slice = 3600.0f; // 1 hr.
3697 execute = new LLScriptExecute(file); 4008 U32 events_processed = 0;
3698 // note: LLScriptExecute() closes file for us 4009
3699 } 4010 do {
3700 file = LLFile::fopen(filename, "r"); 4011 LLTimer timer2;
3701 if (file) 4012 execute->runQuanta(b_debug, LLUUID::null, &error, b_state,
3702 { 4013 time_slice, events_processed, timer2);
3703 LLFILE* fp = LLFile::fopen("lscript.parse", "w"); /*Flawfinder: ignore*/ 4014 } while (!execute->isFinished());
3704 LLScriptLSOParse *parse = new LLScriptLSOParse(file); 4015
3705 parse->printData(fp); 4016 F32 time = timer.getElapsedTimeF32();
3706 delete parse; 4017 F32 ips = execute->mInstructionCount / time;
3707 fclose(file); 4018 llinfos << execute->mInstructionCount << " instructions in " << time << " seconds" << llendl;
3708 fclose(fp); 4019 llinfos << ips/1000 << "K instructions per second" << llendl;
3709 } 4020 printf("ip: 0x%X\n", get_register(execute->mBuffer, LREG_IP));
3710 file = LLFile::fopen(filename, "r"); 4021 printf("sp: 0x%X\n", get_register(execute->mBuffer, LREG_SP));
3711 if (file && execute) 4022 printf("bp: 0x%X\n", get_register(execute->mBuffer, LREG_BP));
3712 { 4023 printf("hr: 0x%X\n", get_register(execute->mBuffer, LREG_HR));
3713 timer.reset(); 4024 printf("hp: 0x%X\n", get_register(execute->mBuffer, LREG_HP));
3714 while (!execute->run(b_debug, LLUUID::null, &error, b_state)) 4025 delete execute;
3715 ; 4026 fclose(file);
3716 F32 time = timer.getElapsedTimeF32();
3717 F32 ips = execute->mInstructionCount / time;
3718 llinfos << execute->mInstructionCount << " instructions in " << time << " seconds" << llendl;
3719 llinfos << ips/1000 << "K instructions per second" << llendl;
3720 printf("ip: 0x%X\n", get_register(execute->mBuffer, LREG_IP));
3721 printf("sp: 0x%X\n", get_register(execute->mBuffer, LREG_SP));
3722 printf("bp: 0x%X\n", get_register(execute->mBuffer, LREG_BP));
3723 printf("hr: 0x%X\n", get_register(execute->mBuffer, LREG_HR));
3724 printf("hp: 0x%X\n", get_register(execute->mBuffer, LREG_HP));
3725 delete execute;
3726 fclose(file);
3727 }
3728 } 4027 }
3729} 4028}
3730 4029