count pages in pdf without opening c# : Delete pages from pdf application SDK tool html winforms azure online antocuni-thesis7-part323

interact directly with the target platform: thus, the backend connects the abstract layer
used by the frontend and the concrete level of the target platform. In this section, we
describe the interface for ootype backends. The interface for lltype backends is the same
for the most part and the dierences are minimal (for example, they do not have any notion
of oosend).
Concretely, the backend must implement the
CPU
class: the frontend stores a reference to
a singleton instance of this class, and invokes method on it.
CPU
is the only class seen
by the frontend, but internally the code of the backend is divided into more classes. The
subsequent subsections describes the interface of the
CPU
class. Then, the next sections of
this chapter will explain how the CLI backend implements this interface.
7.2.1 Descriptors
As described in Section 7.1, the ootype version of the JIT frontend is aware of the object
oriented entities of the target platform. However, the concrete internal representation of
classes, methods, etc. used by ootype is obviously dierent from the representation used by
the native tools of the platform. For example, in ootype the concept of \class" is denoted
by instances of the class
pypy.rpython.ootype.Instance
,while on the CLI side we use
instances of
System.Type
.
The concept of descriptors lls the gaps between the two worlds: a descriptor is a token
that can be obtained by the frontend at translation time. Such token is opaque and the
frontend has no way to inspect its inside, and its only use is to be passed back to the
backend later. The following table lists all possible descriptors:
Descriptor
Meaning
typedescr(T)
the type T
arradescr(T)
the array type whose items are of type T
methdescr(T, name)
the method name of the type T
fielddescr(T, name)
the eld name of the type T
calldescr(ARGS, RESULT) a static
3
method type of the specied signature
7.2.2 Executing operations
As already explained, during the tracing phase the operations are both executed and
recorded. Toguaranteecorrectness, the resultof the execution must thesame that would be
3
I.e., a method which is not bound to any particular instance. Static methods are the CLI/JVM
equivalent of functions.
62
Delete pages from pdf - application SDK tool:C# PDF Page Extract Library: copy, paste, cut PDF pages in C#.net, ASP.NET, MVC, Ajax, WinForms, WPF
Easy to Use C# Code to Extract PDF Pages, Copy Pages from One PDF File and Paste into Others
www.rasteredge.com
Delete pages from pdf - application SDK tool:VB.NET PDF Page Extract Library: copy, paste, cut PDF pages in vb.net, ASP.NET, MVC, Ajax, WinForms, WPF
Detailed VB.NET Guide for Extracting Pages from Microsoft PDF Doc
www.rasteredge.com
obtained by the underlying VM. For simple operations the JIT frontend knows everything
it needs for execution: for example, the operation
int_add(40, 2)
yields always the same
result whatever platform we are targeting.
However, some operations cannot be performed without knowing the implementation de-
tails of the target platform. Take, for example, the operation
getfield_gc
4
,which reads
the content of a eld of an object: depending on the platform, it could be implemented in
very dierent ways, e.g. by fetching a value stored in memory at a certain oset from the
address of the object (as it is the case for the x86 backend), or by invoking the re ection
APIs of the runtime system to actually get the desired value (as the CLI backend might
do, but the actual implementation is slightly dierent for eciency reasons).
Therefore the JIT frontend has to delegate the execution of some operations to the back-
end. The needed extra information are passed as descriptors: following the
getfield_gc
example, the eld to read from is encoded in a elddescr.
The backend exports one method for each of the operations it implements, as shown by
Figure 7.3. Each method takes a descriptor and a list of arguments, which contains the
actual operands. The dierence between
do_new_with_vtable
and
do_runtimenew
is the
same as between creating an object in C# using the statement
new
and creating an object
using the re ection.
Note that these methods directly execute the operations, but do not emit machine code
for them. Machine code generation is described in Section 7.3.
7.2.3 Loops and bridges
The most important task of the backend is to translate loop and bridges (see Section 6.4)
into ecient machine code that can be directly executed on thetarget platform. To request
the compilation of a loop, the frontend calls the method
compile_loop
,passing the trace,
i.e. the list of operations to be emitted, and the list of input arguments. Despite the name
for historical reasons,
compile_loop
is also called to compile entry bridges.
Similarly, to compile inner and exit bridges the frontend calls
compile_bridge
,which takes
the same parameters as
compile_loop
,with the addition of a token that describes which
hot guard the bridge starts from. The backend connects the existing guard and the newly
created bridge so that the next time the guard fails, the bridge will be executed.
4
the _gc sux is there for historical reasons and makes sense only for lltype, thus can be ignored for
ootype
63
application SDK tool:VB.NET PDF Page Delete Library: remove PDF pages in vb.net, ASP.
doc.Save(outPutFilePath). How to VB.NET: Delete Consecutive Pages from PDF. doc.Save(outPutFilePath). How to VB.NET: Delete Specified Pages from PDF.
www.rasteredge.com
application SDK tool:C# PDF Page Delete Library: remove PDF pages in C#.net, ASP.NET
doc.Save(outPutFilePath); Demo Code: How to Delete Consecutive Pages from PDF in C#.NET. Demo Code: How to Delete Specified Pages from PDF in C#.NET.
www.rasteredge.com
Operation
Arguments
Descr
do
new
with
vtable
typedescr
New object of type typedescr
do
new
array
length
typedescr
New array typedescr[length]
do
runtimenew
class
New object of type class
do
getfield
gc
obj
fielddescr Get the specied eld out of obj
do
setfield
gc
obj, value
fielddescr Set the specied eld of obj to value
do
oosend
args
array
methdescr
Call the specied instance method. The
receiver is in args
array[0]
do
instanceof
obj
typedescr
Test whether obj is an instance of
typedescr
do
arraylen
gc
array
arraydescr Return the length of array
do
getarrayitem
gc
array, i
arraydescr Return array[i]
do
setarrayitem
gc
array, i, value
arraydescr array[i] = value
do
call
args
array
calldescr
Call thestaticmethodin args
array[0]
Figure 7.3: The operations implemented by the JIT backends
7.2.4 Executing loops
Once compiled, a loop is ready to be executed: before doing so, the JIT frontend needs
to pass it the correct input arguments, so that it starts in the right state. The backend
exposes three methods for setting the input arguments:
set_future_value_int(i, value)
set_future_value_float(i, value)
set_future_value_ref(i, value)
Each of them sets the ith input argument to value, and they only dier for the type of the
value
parameter
5
,which can be respectively
int
,
float
or
object
6
.
Note that the type of
value
for
set_future_value_ref
is
object
: whenever an object is
used as an input argument, it is casted to
object
,passed to
set_future_value_ref
,and
casted back to its original type inside the loop. This has to be done because the frontend
does not know in advance all the possible types that could be used for input arguments.
Once the input arguments have been set, the JIT frontend triggers the execution of the
loop by invokingthe
execute_token
method, which takes asingleparameters that uniquely
identies the loop in question. Then, the loop runs until a guard fails.
5
We need three distinct names because the C backend does not support the overloading of functions.
6
The sux _ref stands for \reference value", i.e. an object for ootype and a pointer for lltype
64
application SDK tool:C# PDF File & Page Process Library SDK for C#.net, ASP.NET, MVC
C# view PDF online, C# convert PDF to tiff, C# read PDF, C# convert PDF to text, C# extract PDF pages, C# comment annotate PDF, C# delete PDF pages, C# convert
www.rasteredge.com
application SDK tool:C# PDF Page Insert Library: insert pages into PDF file in C#.net
how to merge PDF document files by C# code, how to rotate PDF document page, how to delete PDF page using C# .NET, how to reorganize PDF document pages and how
www.rasteredge.com
At this point, the JIT frontend needs to know the values of the internal variables of
the loop to restart the interpreter in the right state. These can be queried by invok-
ing
get_latest_value_int
,
get_latest_value_float
and
get_latest_value_ref
,which
work in a similar way as their
set_future_value_
*
counterparts.
Note that in this way input arguments passing and value returning is not very ecient,
as a method invocation is needed for each of them. However, tracing JITs spend most of
their time inside the loops, so this process does not aect negatively eciency.
7.3 Compiling loops
As anticipated by Section 4.1, the PyPy JIT emits new bytecode at runtime. In .NET, the
unit of compilation is the method, hence each compiled loop generates a method.
The signature of all the generated methods is
void Loop(InputArgs args)
,expressed in
C# syntax. The only parameter is of type
InputArgs
, which contains three arrays of
integers,  oats and objects. The
CPU
holds an instance of
InputArgs
,which is then passed
to all the loops when invoked
7
.The methods
set_future_value_
*
store the actual values
of the input arguments in these arrays.
Despite its name, which survives for historical reasons,
InputArgs
is used both for input
arguments and for return values. Thus, the generated code will store the relevant values
into the same arrays, which will then be read by
get_latest_value_
*
.
Agenerated method is composed of three parts:
 the setup code, which initializes all the local variables to their starting values,
according to the content of
args
 the loop body, which actually executes the loop. Generating the body is easy, as
each operation can be easily mapped into a sequence of CLI instructions. Section
7.4 explains in detail how the code is actually generated
 the tear-down code: for each guard, there is a bit of code which is triggered when
it fails and stores the relevant local variables into
args
7
Thus, since CPU is a singleton, so is InputArgs. This works well as long as we support only one
thread, but in case of multi-threading we may want to have a per-thread InputArgs instance
65
application SDK tool:VB.NET PDF Page Insert Library: insert pages into PDF file in vb.
Page: Insert PDF Pages. |. Home ›› XDoc.PDF ›› VB.NET PDF: Insert PDF Page. Add and Insert Multiple PDF Pages to PDF Document Using VB.
www.rasteredge.com
application SDK tool:VB.NET PDF delete text library: delete, remove text from PDF file
VB.NET PDF - How to Delete Text from PDF File in VB.NET. VB.NET Programming Guide to Delete Text from PDF File Using XDoc.PDF SDK for VB.NET.
www.rasteredge.com
Not = [’ldc.i4.0’’ceq’]
operations = {
’same_as’:
[PushAllArgs, StoreResult],
’bool_not’:
[PushAllArgs] + Not + [StoreResult],
...
’ooisnull’:
[PushAllArgs, ’ldnull’’ceq’, StoreResult],
’oononnull’:
[PushAllArgs, ’ldnull’’ceq’] + Not + [StoreResult],
...
’int_add’:
’add’,
’int_sub’:
’sub’,
’int_mul’:
’mul’,
’int_floordiv’:
’div’,
’int_mod’:
’rem’,
’int_lt’:
’clt’,
...
}
Figure 7.4: Operations table for the static CLI backend
7.4 Code generation
To generate the actual loop body, the backend needs to convert each operation of the
intermediate representation used by the JIT into one or more CLI instructions. This
intermediate representation directly derives from the one used by the translation toolchain
(see Section 3.2): in particular, most of the operations have the same name and semantics.
By exploiting this fact, we can write the JIT backend very eciently without need to teach
it explicitly how to translate each operation: the CLI static backend
8
already knows how to
convert operations into CLI instructions, thus we just need a way to reuse this knowledge.
The CLI static backend contains a table mapping operations into CLI instructions: Figure
7.4 shows an excerpt of this table. We won’t explain in detail its content, but from the
gure it should be clear that it uses an internal language to express CLI instructions: in
particular, every string such as
’add’
,
’sub’
or
’ldnull’
is translated directly into the
corresponding CLI instruction, and moreover there are internal commands to do a more
complex translation (e.g.,
PushAllArgs
pushes all the arguments of the operation on the
CLI stack).
Unfortunately, the CLI JIT backend cannot directly use this table for generating the code.
8
It is important here not to confuse the CLI static and JIT backends: the rst operates at translation
time, and produces a text le containing the classes and the methods composing pypy-cli, which is then
compiled into an executable. On the other hand, the JIT backend operates at runtime and generates CLI
bytecode by invoking the API exposed by the Reflection.Emit namespace.
66
application SDK tool:C# Word - Delete Word Document Page in C#.NET
doc.Save(outPutFilePath); Delete Consecutive Pages from Word in C#. int[] detelePageindexes = new int[] { 1, 3, 5, 7, 9 }; // Delete pages.
www.rasteredge.com
application SDK tool:C# PDF metadata Library: add, remove, update PDF metadata in C#.
Allow C# Developers to Read, Add, Edit, Update and Delete PDF Metadata in .NET Project. Remove and delete metadata from PDF file.
www.rasteredge.com
def emit_op_getfield_gc(self, op):
descr = op.descr
assert isinstance(descr, FieldDescr)
clitype = descr.get_self_clitype()
fieldinfo = descr.get_field_info()
obj = op.args[0]
# push the object on the stack, and maybe cast it to the correct type
obj.load(self)
if obj.getCliType(self) is not clitype:
self.il.Emit(OpCodes.Castclass, clitype)
# actually load the field value
self.il.Emit(OpCodes.Ldfld, fieldinfo)
# store the result in the proper variable
self.store_result(op)
Figure 7.5: Implementation of the
getfield_gc
operation
As explained in Section 6.2 the JIT frontend and backends need to be written in RPython,
while the
operations
table is not
9
.However, we can use the metaprogramming capabilities
of RPython to automatically generate valid RPython code from the table.
Due to the way itis designed, the Translation Toolchain starts to analyze RPython modules
only after they have been imported: this means that at import time we can use the full
Python language to generate RPython classes and functions that will be later fed into the
Translation Toolchain. In fact, we can think of Python as the metaprogramming language
for RPython[AACM07].
def emit_op_int_add(self, op):
self.push_all_args(op)
self.il.Emit(OpCodes.Add)
self.store_result(op)
Figure 7.6: Method generated for
int_add
The basic idea is turn each row in the table
into a method that emits the corresponding
CLI instructions: Figure 7.6 shows for exam-
ple the method generated for the
int_add
op-
eration, where
self.il
is an object of type
System.Reflection.Emit.ILGenerator
and it
is used to emit the actual CLI bytecode.
By exploiting this technique, we were able to
considerably cut both the time needed to write the backend and the number of bugs, as
the operation table was already well tested in the static CLI backend. However, there were
more complex operations for which a simple translation from the operation table is not
9
Remind that the Translation Toolchain does not need to be written in RPython, thus the static CLI
backend can freely use the table.
67
enough: in those cases, we wrote the corresponding method manually, as for example it is
the case of
getfield_gc
,shown in Figure 7.5: in this example, it is also possible to see an
usage of the
FieldDescr
descriptor introduced by Section 7.2.1.
7.5 Compiling inner bridges
Consider Figures 6.9 and 6.10, reported here for convenience as Figures 7.7 and 7.8.
After the trace has been produced, the JIT frontend invokes the backend by calling
compile_loop
, which in turns generates a .NET method that contains the code of the
loop. Later guard
true(t
1
)(highlighted in blue) becomes hot, and the JIT frontend pro-
duces a new trace, which is shown in green in Figure 7.8. At this point, the frontend calls
compile_bridge
.
loop(i
0
,a
0
)
t
0
=int
mod(i
0
,2)
t
1
= int
is
true(t
0
)
guard
true(t
1
)
a
1
= int
mul(a
0
,2)
i
1
=int
add(i
0
,1)
t
2
= int
lt(i
1
,100)
guard
true(t
2
)
jump(i
1
,a
1
)
Figure 7.7: The trace produced
by the code in Figure 6.8
loop(i
0
,a
0
)
t
0
= int
mod(i
0
,2)
t
1
=int
is
true(t
0
)
guard
true(t
1
)
a
1
=int
mul(a
0
,2)
i
1
= int
add(i
0
,1)
t
2
=int
lt(i
1
,100)
guard
true(t
2
)
jump(i
1
,a
1
)
a
3
= int
add(a
2
,1)
i
3
= int
add(i
2
,1)
t
3
=int
lt(i
3
,100)
guard
true(t
3
)
jump(i
3
,a
3
)
i
2
i
0
a
2
a
0
Figure 7.8: The trace tree produced when the guard
becomes hot
The x86 backend implements
compile_bridge
in a straightforward way: rst, it emits the
code for the new trace in memory, then it modies the machine code for guard
true(t
1
)to
jump to the newly generated bridge. However, this implementation strategy does not work
with the CLI. As described in Section 4.3, .NET methods are immutable after they have
68
been compiled, thus, we cannot modify the code of the guard.
There are three main alternatives to solve the problem:
Recompiling the whole method Although we cannot modify the original method, we
can always create a new one that contains the code for both the original loop and the
new inner bridge. The code generated in this way is optimal, as we can directly use
the fast
br
CLI instruction tojump from thefailing guard to thebridge. However, this
solution may imply that a considerable ammount of time is wasted for re-compiling
code: each time a new bridge is generated, the loop it belongs to must be recompiled
together with all its current bridges. In the worst case, the time taken before having
astable loop (i.e. a loop that does no longer need to be recompiled because all its
fast paths have been generated) is quadratic on the number of its paths
Using a trampoline The CLI does not oer the possibility of augmenting the code of
amethod after its compilation, but it is possible to simulate this behaviour. The
idea is to have a trampoline that transfers the execution to a child method, which
after execution returns a delegate (see Section 4.6) pointing to the next method to
be called by the trampoline, and so on. The next method delegates returned by the
children are not hard-coded in the bytecode, but stored in some place where they can
be modied from the outside: later, we can alter the  ow of control by modifying the
next method delegate that is called when the guard fails to point to the newly created
method that implements the bridge. The advantage of this technique is that we can
compile new bridges without recompiling the existing loops, while the disadvantage
is that it is extremely slow at runtime, because each control transfer involves a lot of
operations. The author of this thesis has already explored this solution in [CAR09]
and [ABCR08].
Using tail calls Tail calls are described in Section 4.4 and oer an alternative to the
previous solution: instead ofhaving the control  ow bouncingbetween thetrampoline
and thechildren methods, we eliminate the former and directly transfer the execution
from one method to the next one with a tail call. Again, the next method delegates
are stored in some place where they can be modied, so that they can be edited when
we compile a new bridge. In an ideal world, tail calls would be the perfect solution
for us: they enable incremental compilation of bridges, and if implemented in the
right way they are as ecient as local jumps. However, at the moment of writing
they are too slow and too buggy to be used in practice when performance matters.
We chose to implement the rst alternative, and to recompile the whole method every time
anew bridge is generated. This way, the programs take more time to reach a stable state,
but from that point on the code produced is as ecient as we can.
69
Abetter solution would consist in a mixed approach between the \recompile" approach
and one of the other two outlined alternative solutions. At rst, we could attach bridges
using a trampoline or tail calls: then, when we see that the loop is \stable enough" and
that no more fast path are discovered, we could recompile the whole loop into an ecient
method. This approach has not been implemented yet, but we plan to experiment on it as
afuture work.
7.5.1 Entry and exit bridges
loop 1
...
...
exit bridge
loop 2
...
...
exit bridge
Figure 7.9: Mutual recursive loops
Both entry and exit bridges (see section
6.4) are executed only once, then they
jump toanother loop. Since they arecre-
ated after the target loop, implementing
them on the CLI poses the same prob-
lems as for inner bridges.
However, we chose to implement them
dierently: the rationale is that con-
trarily to inner bridges, which are sup-
posed tobe executed often and thus need
to be implemented eciently, entry and
exit bridges are executed only once, then
they transfer the execution to a loop
which will probably run for a consider-
able amount of time. Hence, it is per-
fectly reasonable to use a slower imple-
mentation, if it has other advantages.
In particular, we implement jumps be-
tween bridges and loops as tail calls: this
way we can avoid to recompile the whole
loop tree every time we generate an en-
try or exit bridge that jumps to it.
Note that tail calls are necessary because it is possible to have loops that mutually jump
to each other, as shown by Figure 7.9. In case we used simple calls instead of tail calls, we
would exhaust the stack space after a while.
70
71
Documents you may be interested
Documents you may be interested