| 
									
										
										
										
											2021-10-24 13:30:49 +02:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2024-05-06 06:44:08 +02:00
										 |  |  |  * Copyright (c) 2021-2024, Andreas Kling <kling@serenityos.org> | 
					
						
							| 
									
										
										
										
											2021-10-24 13:30:49 +02:00
										 |  |  |  * | 
					
						
							|  |  |  |  * SPDX-License-Identifier: BSD-2-Clause | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-08 12:25:58 +02:00
										 |  |  | #include <LibJS/Bytecode/BasicBlock.h>
 | 
					
						
							| 
									
										
										
										
											2021-10-24 13:30:49 +02:00
										 |  |  | #include <LibJS/Bytecode/Executable.h>
 | 
					
						
							| 
									
										
										
										
											2024-05-06 06:44:08 +02:00
										 |  |  | #include <LibJS/Bytecode/Instruction.h>
 | 
					
						
							| 
									
										
										
										
											2023-10-08 12:25:58 +02:00
										 |  |  | #include <LibJS/Bytecode/RegexTable.h>
 | 
					
						
							| 
									
										
										
										
											2023-10-03 08:18:10 +02:00
										 |  |  | #include <LibJS/SourceCode.h>
 | 
					
						
							| 
									
										
										
										
											2021-10-24 13:30:49 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | namespace JS::Bytecode { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-27 13:23:59 +01:00
										 |  |  | JS_DEFINE_ALLOCATOR(Executable); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-03 08:18:10 +02:00
										 |  |  | Executable::Executable( | 
					
						
							| 
									
										
										
										
											2024-05-06 06:44:08 +02:00
										 |  |  |     Vector<u8> bytecode, | 
					
						
							| 
									
										
										
										
											2023-10-03 08:18:10 +02:00
										 |  |  |     NonnullOwnPtr<IdentifierTable> identifier_table, | 
					
						
							|  |  |  |     NonnullOwnPtr<StringTable> string_table, | 
					
						
							|  |  |  |     NonnullOwnPtr<RegexTable> regex_table, | 
					
						
							| 
									
										
										
										
											2024-02-02 09:52:25 +01:00
										 |  |  |     Vector<Value> constants, | 
					
						
							| 
									
										
										
										
											2023-10-03 08:18:10 +02:00
										 |  |  |     NonnullRefPtr<SourceCode const> source_code, | 
					
						
							|  |  |  |     size_t number_of_property_lookup_caches, | 
					
						
							|  |  |  |     size_t number_of_global_variable_caches, | 
					
						
							|  |  |  |     size_t number_of_registers, | 
					
						
							|  |  |  |     bool is_strict_mode) | 
					
						
							| 
									
										
										
										
											2024-05-06 06:44:08 +02:00
										 |  |  |     : bytecode(move(bytecode)) | 
					
						
							| 
									
										
										
										
											2023-10-03 08:18:10 +02:00
										 |  |  |     , string_table(move(string_table)) | 
					
						
							|  |  |  |     , identifier_table(move(identifier_table)) | 
					
						
							|  |  |  |     , regex_table(move(regex_table)) | 
					
						
							| 
									
										
										
										
											2024-02-02 09:52:25 +01:00
										 |  |  |     , constants(move(constants)) | 
					
						
							| 
									
										
										
										
											2023-10-03 08:18:10 +02:00
										 |  |  |     , source_code(move(source_code)) | 
					
						
							|  |  |  |     , number_of_registers(number_of_registers) | 
					
						
							|  |  |  |     , is_strict_mode(is_strict_mode) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     property_lookup_caches.resize(number_of_property_lookup_caches); | 
					
						
							|  |  |  |     global_variable_caches.resize(number_of_global_variable_caches); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Executable::~Executable() = default; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-24 13:30:49 +02:00
										 |  |  | void Executable::dump() const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2024-02-04 13:16:07 +01:00
										 |  |  |     warnln("\033[37;1mJS bytecode executable\033[0m \"{}\"", name); | 
					
						
							| 
									
										
										
										
											2024-05-06 06:44:08 +02:00
										 |  |  |     InstructionStreamIterator it(bytecode, this); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     size_t basic_block_offset_index = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     while (!it.at_end()) { | 
					
						
							|  |  |  |         bool print_basic_block_marker = false; | 
					
						
							|  |  |  |         if (basic_block_offset_index < basic_block_start_offsets.size() | 
					
						
							|  |  |  |             && it.offset() == basic_block_start_offsets[basic_block_offset_index]) { | 
					
						
							|  |  |  |             ++basic_block_offset_index; | 
					
						
							|  |  |  |             print_basic_block_marker = true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         StringBuilder builder; | 
					
						
							|  |  |  |         builder.appendff("[{:4x}] ", it.offset()); | 
					
						
							|  |  |  |         if (print_basic_block_marker) | 
					
						
							|  |  |  |             builder.appendff("{:4}: ", basic_block_offset_index - 1); | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             builder.append("      "sv); | 
					
						
							|  |  |  |         builder.append((*it).to_byte_string(*this)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         warnln("{}", builder.string_view()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ++it; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!exception_handlers.is_empty()) { | 
					
						
							|  |  |  |         warnln(""); | 
					
						
							|  |  |  |         warnln("Exception handlers:"); | 
					
						
							|  |  |  |         for (auto& handlers : exception_handlers) { | 
					
						
							|  |  |  |             warnln("    from {:4x} to {:4x} handler {:4x} finalizer {:4x}", | 
					
						
							|  |  |  |                 handlers.start_offset, | 
					
						
							|  |  |  |                 handlers.end_offset, | 
					
						
							|  |  |  |                 handlers.handler_offset.value_or(0), | 
					
						
							|  |  |  |                 handlers.finalizer_offset.value_or(0)); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-02-04 13:16:07 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     warnln(""); | 
					
						
							| 
									
										
										
										
											2021-10-24 13:30:49 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-03 11:34:36 +01:00
										 |  |  | void Executable::visit_edges(Visitor& visitor) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Base::visit_edges(visitor); | 
					
						
							| 
									
										
										
										
											2024-04-15 13:58:21 +02:00
										 |  |  |     visitor.visit(constants); | 
					
						
							| 
									
										
										
										
											2024-03-03 11:34:36 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-06 06:44:08 +02:00
										 |  |  | Optional<Executable::ExceptionHandlers const&> Executable::exception_handlers_for_offset(size_t offset) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     for (auto& handlers : exception_handlers) { | 
					
						
							|  |  |  |         if (handlers.start_offset <= offset && offset < handlers.end_offset) | 
					
						
							|  |  |  |             return handlers; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return {}; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | UnrealizedSourceRange Executable::source_range_at(size_t offset) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (offset >= bytecode.size()) | 
					
						
							|  |  |  |         return {}; | 
					
						
							|  |  |  |     auto it = InstructionStreamIterator(bytecode.span().slice(offset), this); | 
					
						
							|  |  |  |     VERIFY(!it.at_end()); | 
					
						
							| 
									
										
										
										
											2024-05-06 07:51:14 +02:00
										 |  |  |     auto mapping = source_map.get(offset); | 
					
						
							|  |  |  |     if (!mapping.has_value()) | 
					
						
							|  |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2024-05-06 06:44:08 +02:00
										 |  |  |     return UnrealizedSourceRange { | 
					
						
							|  |  |  |         .source_code = source_code, | 
					
						
							| 
									
										
										
										
											2024-05-06 07:51:14 +02:00
										 |  |  |         .start_offset = mapping->source_start_offset, | 
					
						
							|  |  |  |         .end_offset = mapping->source_end_offset, | 
					
						
							| 
									
										
										
										
											2024-05-06 06:44:08 +02:00
										 |  |  |     }; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-24 13:30:49 +02:00
										 |  |  | } |