mirror of
https://github.com/rubyjs/therubyrhino
synced 2023-03-27 23:21:34 -04:00
handle Rhino's 64K code generation (method) limit on the fly
simple retry running the failed compilation in interpreter mode
This commit is contained in:
parent
23c617345e
commit
05ece36c5d
2 changed files with 55 additions and 8 deletions
|
@ -240,23 +240,55 @@ module Rhino
|
|||
alias :version= :javascript_version=
|
||||
|
||||
# Enter this context for operations.
|
||||
# Some methods such as eval() will fail unless this context is open !
|
||||
# Some methods such as eval() will fail unless the context is open.
|
||||
def open(&block)
|
||||
do_open(&block)
|
||||
rescue JS::RhinoException => e
|
||||
if code_generation_error?(e)
|
||||
warn "[INFO] Rhino byte-code generation failed forcing #{@native} into interpreted mode"
|
||||
self.optimization_level = -1
|
||||
retry
|
||||
end
|
||||
raise Rhino::JSError.new(e)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def do_open
|
||||
factory.enterContext(@native)
|
||||
begin
|
||||
yield self
|
||||
ensure
|
||||
factory.exit
|
||||
def do_open # :nodoc
|
||||
factory.enterContext(@native)
|
||||
begin
|
||||
yield self
|
||||
ensure
|
||||
factory.exit
|
||||
end
|
||||
end
|
||||
|
||||
CODE_GENERATION_ERROR_MESSAGE = 'generated bytecode for method exceeds 64K limit' # :nodoc
|
||||
|
||||
CODE_GENERATION_TRACE_CLASS_NAME = 'org.mozilla.javascript.optimizer.Codegen' # :nodoc
|
||||
CODE_GENERATION_TRACE_METHOD_NAME = 'reportClassFileFormatException' # :nodoc
|
||||
# at org.mozilla.javascript.optimizer.Codegen.reportClassFileFormatException
|
||||
|
||||
def code_generation_error?(exception) # :nodoc
|
||||
if ( exception.is_a?(NativeException) rescue nil ) # JRuby 1.6 wrapping
|
||||
exception = exception.cause
|
||||
end
|
||||
if exception.class == Rhino::JS::EvaluatorException
|
||||
if exception.message.index(CODE_GENERATION_ERROR_MESSAGE)
|
||||
return true
|
||||
end
|
||||
# NOTE: unfortunately Rhino localizes the error messages!
|
||||
# and the ClassFileFormatException is not kept as a cause
|
||||
class_name = CODE_GENERATION_TRACE_CLASS_NAME
|
||||
method_name = CODE_GENERATION_TRACE_METHOD_NAME
|
||||
for trace in exception.getStackTrace()
|
||||
if class_name == trace.class_name && method_name == trace.method_name
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
false
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -166,4 +166,19 @@ describe Rhino::Context do
|
|||
end
|
||||
end
|
||||
|
||||
it "handles code generation error when 'generated bytecode for method exceeds 64K limit'" do
|
||||
context = Rhino::Context.new
|
||||
|
||||
big_script = ''
|
||||
10000.times { |i| big_script << "var s#{i} = '#{i}';\n" }
|
||||
10000.times { |i| big_script << "var n#{i} = +#{i} ;\n" }
|
||||
|
||||
lambda {
|
||||
context.eval big_script
|
||||
}.should_not raise_error
|
||||
|
||||
context.eval('( s9999 )').should == '9999'
|
||||
context.eval('( n9999 )').should == +9999
|
||||
end
|
||||
|
||||
end
|
Loading…
Reference in a new issue